Detect concealed characters in server metadata - #1122
Open
Adeniyikayodee wants to merge 1 commit into
Open
Conversation
A server advertises tools through tools/list with a name, a description and a schema. A host renders that once for approval and then feeds the same bytes to the model on every later turn. Nothing in MCP requires the rendered view and the delivered bytes to agree, so a code point with no glyph is absent from what a person approves while reaching the model intact. Report two classes of character on the client listing paths: the Unicode TAG block, which no mainstream renderer draws, and bidirectional overrides and isolates, which reorder displayed text. Zero-width joiners and other format characters are left alone, since they carry meaning in Indic, Arabic and Persian text and in emoji sequences. Nothing is rewritten. A stripped description is still text the server chose, and editing a name would break calls that use it. Warn only by default; set io.modelcontextprotocol.strictMetadataValidation to fail the listing instead. Signed-off-by: mkbadeniyi <adeniyikayode22@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1121
Summary
Adds a check on the client listing paths for characters in server metadata
that stay invisible to a reviewer while still reaching the model.
Motivation
A server advertises a tool through
tools/listwith a name, a descriptionand a schema. A host typically renders this once for approval, then supplies
the same bytes to the model on every later turn. MCP allows the rendered view
and the delivered bytes to differ, so a code point that lacks a glyph is
absent from what a person approves and arrives at the model intact.
Approach
Two classes of character are reported:
U+E0000toU+E007F. Mainstream terminals, chatclients and IDEs leave it unrendered, and it lacks a legitimate use in tool
metadata.
U+202AtoU+202EandU+2066toU+2069, which reorder how the surrounding text is displayed.Zero width joiners and the remaining format characters are left alone, since
they carry meaning in Indic, Arabic and Persian text and in emoji sequences.
A test covers שלום, مرحبا, नमस्ते and a joined family emoji.
Metadata is reported and left as it arrived. A stripped description is still
text the server chose, and rewriting a name would break the calls that use
it.
The shape follows
ToolNameValidator, which already runs on the same listingpath: a public final class in
util, static methods, one system property.Configuration
Warn by default, so current behaviour is preserved. Set
io.modelcontextprotocol.strictMetadataValidation=trueto fail the listinginstead.
Tests
11 unit tests and 3 client level tests. A payload is encoded into the TAG
block and confirmed in a description, inside a nested JSON schema, and in map
keys. The client tests cover the default path and the strict path.
Verification
./mvnw clean testpasses across all 11 modules, 1496 tests, conformanceincluded.
Open question
Whether the character set stays fixed as written or becomes configurable.
Fixed seems safer to me... a configurable blocklist invites someone to add
the whole
Cfcategory, which would fire on Persian and Indic descriptions.