Use case
We run MCP clients that reach third party servers alongside our own. On first
connection a person sees an approval prompt listing each tool with its name
and description, and approves the server from that view.
That prompt is the only place a human reads the metadata. Everything after it
goes to the model directly, on every turn. So the approval rests on rendered
text while the model receives the raw bytes, and today those two are free to
differ. A description carrying code points that the prompt leaves unrendered
would be approved on sight and then supplied to the model in full.
Current behaviour
Tool, prompt and resource metadata reaches the caller exactly as the server
sent it. ToolNameValidator already runs on the client listing path and
warns about names that fall outside the spec, so checking server supplied
metadata on arrival has a precedent... the description, title and schema text
remain unchecked.
MCP allows the metadata a host renders for approval and the bytes later
placed in the model context to differ. A code point that lacks a glyph is
therefore absent from an approval dialog while arriving at the model intact.
The Unicode TAG block, U+E0000 to U+E007F, behaves this way in every
mainstream terminal, chat client and IDE.
Proposal
A check on the client listing paths reporting two classes of character:
- the Unicode TAG block,
U+E0000 to U+E007F
- bidirectional overrides and isolates,
U+202A to U+202E and U+2066 to
U+2069, which reorder how the surrounding text is displayed
Warn by default so current behaviour is preserved, with a system property to
fail the listing instead, following the shape ToolNameValidator already
uses.
Zero width joiners and the remaining format characters would be left alone,
since they carry meaning in Indic, Arabic and Persian text and in emoji
sequences.
Reporting only. A stripped description is still text the server chose, and
editing a name would break the calls that use it.
Open questions
Whether the character set stays fixed or becomes configurable. Fixed seems
safer to me, since a configurable blocklist invites someone to add the whole
Cf category, which would fire on Persian and Indic descriptions.
Whether this belongs in the SDK at all, or sits better in the host above it.
Happy to drop it if you see it as a host concern.
Use case
We run MCP clients that reach third party servers alongside our own. On first
connection a person sees an approval prompt listing each tool with its name
and description, and approves the server from that view.
That prompt is the only place a human reads the metadata. Everything after it
goes to the model directly, on every turn. So the approval rests on rendered
text while the model receives the raw bytes, and today those two are free to
differ. A description carrying code points that the prompt leaves unrendered
would be approved on sight and then supplied to the model in full.
Current behaviour
Tool, prompt and resource metadata reaches the caller exactly as the server
sent it.
ToolNameValidatoralready runs on the client listing path andwarns about names that fall outside the spec, so checking server supplied
metadata on arrival has a precedent... the description, title and schema text
remain unchecked.
MCP allows the metadata a host renders for approval and the bytes later
placed in the model context to differ. A code point that lacks a glyph is
therefore absent from an approval dialog while arriving at the model intact.
The Unicode TAG block,
U+E0000toU+E007F, behaves this way in everymainstream terminal, chat client and IDE.
Proposal
A check on the client listing paths reporting two classes of character:
U+E0000toU+E007FU+202AtoU+202EandU+2066toU+2069, which reorder how the surrounding text is displayedWarn by default so current behaviour is preserved, with a system property to
fail the listing instead, following the shape
ToolNameValidatoralreadyuses.
Zero width joiners and the remaining format characters would be left alone,
since they carry meaning in Indic, Arabic and Persian text and in emoji
sequences.
Reporting only. A stripped description is still text the server chose, and
editing a name would break the calls that use it.
Open questions
Whether the character set stays fixed or becomes configurable. Fixed seems
safer to me, since a configurable blocklist invites someone to add the whole
Cfcategory, which would fire on Persian and Indic descriptions.Whether this belongs in the SDK at all, or sits better in the host above it.
Happy to drop it if you see it as a host concern.