The Model Context Protocol is going global, and the manifest schema needed to catch up.

I just merged PR #132 adding localization and theming support to MCPB (Model Context Protocol Bundles) manifest v0.3. This post breaks down the design decisions and why they matter for anyone building MCP infrastructure.

The Problem: Manifest Bloat vs. User Experience

When you’re building desktop MCP servers that need to work across languages and UI themes, you face a fundamental tension:

Inline everything → Clean implementation, massive manifests
External resources → Lean manifests, more complexity

For a single language? Inline works fine. For 20+ languages? The manifest becomes unwieldy, especially in desktop contexts where you’re loading this data repeatedly. Windows alone ships in hundreds of languages and locales—this pattern needs to scale.

And that’s before considering theme-aware icons. Do you inline base64-encoded images for every size and theme variant? Of course not.

The Design: Per-Locale Resource Discovery

The solution establishes a resource discovery pattern:

{
  "manifest_version": "0.3",
  "display_name": "Sample MCP Server",
  "description": "Provides advanced features",
  "localization": {
    "resources": "resources/${locale}.json",
    "default_locale": "en-US"
  }
}

Key Design Choices

BCP 47 Compliance
Locale identifiers must follow BCP 47 (e.g., en-US, fr-FR, zh-Hans). This isn’t just pedantic spec compliance—it’s essential for cross-platform consistency. Every major platform uses BCP 47, so we do too.

Default Locale in Main Manifest
The default locale content lives directly in the manifest. This means:

  • Zero-resource fallback: if locale files fail to load, you still have usable text
  • Simpler implementation for monolingual servers
  • Clear contract: the manifest is always valid on its own

Graceful Fallback
When a locale file is missing a field, fall back to a language-appropriate locale (e.g., from es-UY to es-MX), and if that fails, the default locale value. This is critical for partial translations and incremental localization work.

Client-Side Resolution
Clients resolve the resource path relative to the server’s installation directory. This keeps the manifest portable and doesn’t require absolute paths or URL schemes.

Localizable Fields

Not everything needs localization. Here’s what we’re supporting:

  • display_name - User-facing name in UI
  • description - Short description
  • long_description - Extended description for details views
  • keywords - When rendered as user-visible labels
  • author.name - If displayed in UI

Explicitly not localizable: structured data like name (package identifier), URLs, version numbers, etc.

Sample Locale File

A French locale file (fr-FR.json) looks like:

{
  "display_name": "Serveur MCP Exemple",
  "description": "Fournit des fonctionnalités avancées",
  "long_description": "Description détaillée pour les utilisateurs",
  "keywords": ["protocole", "contexte", "serveur"]
}

Clean, simple, focused on user-visible text.

Theming: Beyond Light and Dark

Theme-aware icons follow the same principle: avoid bloat while supporting real requirements.

"icons": [
  {
    "src": "assets/icons/icon-16-light.png",
    "sizes": "16x16",
    "theme": "light"
  },
  {
    "src": "assets/icons/icon-16-dark.png",
    "sizes": "16x16",
    "theme": "dark"
  }
]

This aligns with the MCP Registry server.json pattern, creating consistency across the ecosystem.

Why theme matters:
Desktop applications increasingly support system-wide theme preferences. A black icon on a dark background is unusable. Supporting theme variants is table stakes for good UX.

Why not localize icons?
Icons are visual and typically language-agnostic. Regional variations exist (left-to-right vs. right-to-left UI, cultural symbols), but those are edge cases better handled through platform-specific _meta conventions if needed.

The Trade-offs We Made

External Resources > Inline

Why: Manifest size matters in desktop contexts. Clients can lazy-load locale files and cache them separately from the manifest.

Cost: Slightly more implementation complexity. Clients need resource resolution logic.

Verdict: Worth it. The alternative (inline everything) doesn’t scale beyond a handful of languages.

BCP 47 Strict

Why: Cross-platform consistency. macOS, Windows, Linux, and web all use BCP 47.

Cost: More complex than simple language codes (en vs. en-US).

Verdict: Pay the complexity tax once at the spec level, avoid platform-specific quirks everywhere else.

Default Locale in Manifest

Why: Robustness. The manifest is always valid, even if resource loading fails.

Cost: Slight duplication (default locale exists in manifest and potentially in a locale file).

Verdict: Robustness wins. Agents and clients need guaranteed text, even in degraded scenarios.

Why This Matters for the MCP Ecosystem

This isn’t just about one manifest format. It’s about establishing patterns that work across the MCP ecosystem.

Desktop bundles (MCPB) and registry servers are converging on shared patterns. When both use the same icon schema, the same extensibility mechanisms (_meta), and now similar localization approaches, the ecosystem gets stronger.

Developers learn once, apply everywhere. If you know how localization works in MCPB, you can apply similar patterns to registry servers or custom MCP implementations.

Tools can work across implementations. Build a localization tool for one format, adapt it trivially for the other.

This is how open ecosystems scale: through alignment on fundamentals while allowing platform-specific extensions.

Implementation Details

If you’re building MCP clients or servers:

For Servers:

  • Place locale files in a resources/ directory
  • Use BCP 47 locale identifiers (en-US.json, fr-FR.json)
  • Include all localizable fields in each locale file
  • Default locale content goes directly in the manifest

For Clients:

  • Detect user’s locale (system preference or user selection)
  • Resolve the locale file path relative to server’s install directory
  • Load and parse the JSON
  • Fall back to manifest defaults for missing fields
  • Cache locale data to avoid repeated I/O

Fallback chain:

  1. Try user’s specific locale (es-UY)
  2. Try language-appropriate fallback locale (es-MX)
  3. Fall back to default locale from manifest
  4. Use field value from manifest if all else fails

The Broader Pattern

This work continues a theme: bringing desktop MCP implementations and web-based implementations closer together.

Previous work:

This work:

  • Localization framework
  • Theme-aware assets

The goal isn’t unification—desktop and web have different constraints. The goal is alignment where it makes sense, reducing ecosystem fragmentation while preserving platform-appropriate flexibility.

Get Involved

The MCPB spec is evolving through community contributions. If you’re building MCP infrastructure:

  • Review the updated schema
  • Open issues for problems or enhancements
  • Contribute PRs for improvements

The Model Context Protocol ecosystem is still young. Patterns we establish now will echo through years of tooling. Get involved early.


This work emerged from conversations between the Anthropic team, and Windows about real needs in desktop MCP implementations. Special thanks to the reviewers who helped shape this design.

Links:

Updated: