Skip to content

docs(spec): add internationalization guidance for Streamable HTTP#2355

Closed
SamMorrowDrums wants to merge 1 commit into
modelcontextprotocol:mainfrom
SamMorrowDrums:docs/streamable-http-i18n
Closed

docs(spec): add internationalization guidance for Streamable HTTP#2355
SamMorrowDrums wants to merge 1 commit into
modelcontextprotocol:mainfrom
SamMorrowDrums:docs/streamable-http-i18n

Conversation

@SamMorrowDrums

Copy link
Copy Markdown
Contributor

Summary

This change adds explicit guidance on internationalization (i18n) to the Streamable HTTP transport specification, noting that servers MAY use standard HTTP content negotiation to serve localized user-facing content.

Motivation

MCP defines several user-facing string fields (title, description on tools, resources, prompts, and server metadata) that are intended for display in user interfaces. For Streamable HTTP servers, the HTTP protocol already provides well-established mechanisms for content negotiation via the Accept-Language header (RFC 9110 §12.5.4), but the MCP specification makes no mention of this capability. Making it explicit encourages server authors to consider i18n and gives clients confidence that sending Accept-Language is a supported pattern.

This approach:

Changes

  • Streamable HTTP transport (docs/specification/draft/basic/transports.mdx): Added an "Internationalization" subsection covering Accept-Language / Content-Language header usage and fallback behavior.

References

AI Disclosure

This PR was authored with assistance from GitHub Copilot CLI.

Add a section to the Streamable HTTP transport specification noting that
servers MAY use standard HTTP content negotiation (Accept-Language header)
to serve localized versions of user-facing content such as tool titles
and descriptions.

This makes explicit what is already implicitly available via HTTP
semantics, and provides a path for i18n without requiring changes to the
MCP message schema.

References:
- RFC 9110 §12 (Content Negotiation)
- RFC 9110 §12.5.4 (Accept-Language)
- BCP 47 / RFC 5646 (Language Tags)
- Issue modelcontextprotocol#86 (i18n discussion)

Co-authored-by: Copilot <[email protected]>
@pja-ant

pja-ant commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

Hmm, but if we lean on HTTP then does that not mean that we have no standard for stdio servers? We can introduce that later, but then we need to have two ways to do i18n.

@SamMorrowDrums

SamMorrowDrums commented Mar 5, 2026

Copy link
Copy Markdown
Contributor Author

@pja-ant I both agree but

  • STDIO servers can be directly configured, so a config convention could emerge without requiring a spec change
  • we already did this for auth where we lean into HTTP ... I kind of thought that was setting the precedent for leaning into the http transport for what it already has more generally - one of the key drivers for choosing it, it's very mature.

Personally I could go either way on this, but it feels like we should be careful about reinventing the wheel. I wouldn't be against also adding this to the initialize payload for other transports lacking the envelope that http offers. I'm not sure that should prevent this being available now though, we are literally about to go the other direction with the http spec where we are replaying payload values as http headers, so values being both in the payload and in headers will become the standard soon I expect.

@SamMorrowDrums SamMorrowDrums mentioned this pull request Mar 8, 2026
9 tasks
@kurtisvg

kurtisvg commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

It seems like we should try to minimize the gaps between transports as much as possible. Is there a reason we couldn't put this as a field in _meta and mirror it to the header like we're doing for some other values?

@SamMorrowDrums

Copy link
Copy Markdown
Contributor Author

@kurtisvg no, except that the mirroring proposal isn't baked in yet, but do you agree that the http model is likely the sensible i18n communication/resolution mechanism to copy? I feel like it makes sense to at least lift and shift it, rather than come up with something else.

@kurtisvg

kurtisvg commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

@kurtisvg no, except that the mirroring proposal isn't baked in yet, but do you agree that the http model is likely the sensible i18n communication/resolution mechanism to copy? I feel like it makes sense to at least lift and shift it, rather than come up with something else.

Yes, I'm +1 to reusing over reinventing (unless we have a good rationale why)

@SamMorrowDrums

Copy link
Copy Markdown
Contributor Author

Superseded by #2792, which converts this into a cross-transport SEP per the feedback from @pja-ant and @kurtisvg above.

The SEP defines language preference in _meta first (so stdio works the same way) and mirrors into the standard Accept-Language / Content-Language HTTP headers on Streamable HTTP — applying the header/payload mirroring pattern established by SEP-2243, and the per-request stateless model from SEP-2575 (so a user can switch language mid-conversation without renegotiation).

I'll close this PR once #2792 has a sponsor; happy to close sooner if maintainers prefer.

@SamMorrowDrums

Copy link
Copy Markdown
Contributor Author

Closing in favor of #2792, which converts this into a cross-transport SEP per the feedback above. See the SEP for full motivation, the per-request _meta field, the strict HTTP header/body mirror, and the alignment with SEP-2243 and SEP-2575.

SamMorrowDrums added a commit to SamMorrowDrums/modelcontextprotocol that referenced this pull request May 27, 2026
Adds a transport-agnostic, fully opt-in i18n mechanism for MCP using
_meta['io.modelcontextprotocol/acceptLanguage'] on requests and
_meta['io.modelcontextprotocol/contentLanguage'] on responses, mirrored
into the standard HTTP Accept-Language / Content-Language headers on the
Streamable HTTP transport with a strict-mismatch rule consistent with
SEP-2243.

Per-request scope (no handshake-bound state) aligns with SEP-2575 and
supports mid-conversation language switching. Reuses BCP 47, RFC 4647
language-range matching, and existing ecosystem libraries verbatim,
no bespoke matcher or schema.

Supersedes modelcontextprotocol#2355. Proposes subsuming the locale aspect of SEP-1809.

Reference implementation:
modelcontextprotocol/typescript-sdk#2158 (en/fr/de server + client,
stdio and Streamable HTTP, unit and integration tests including
mid-session language switch on stdio).

Co-authored-by: Copilot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants