Repository navigation
instructions from the MCP handshake never reaches the model
#5003
CNSeniorious000
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
dsh-mcp-clientconsumes exactly one thing from an MCP connection: the tool list. The server'sinstructions— the field the spec designates for telling the model how to use that server — is never read.The whole bridge is
tools/list→ctx.tools.register:instructionsdoes not appear anywhere in the published package. This isn't a transport gap — the vendored SDK already captured the value during the handshake and exposes it asclient.getInstructions(). Nothing calls it.Why it can't be recovered later
The value is only ever delivered in the connect-time response, and the field is the same across protocol eras:
2025-11-25and earlier, what@modelcontextprotocol/sdk@1.30.0speaks):InitializeResult.instructions2026-07-28):DiscoverResult.instructionsUnder the legacy handshake this is strictly one-shot:
initializehappens once per connection and no notification re-delivers it. Modernserver/discoveris re-callable, but nothing pushes changes either. A client that ignores the connect-time response has no second source.Why the loss is silent
Per the spec,
instructions"should focus on information that helps the model use the server effectively and should not duplicate information already in tool descriptions." A well-written server therefore keeps cross-tool guidance — call ordering, when not to reach for a tool, id and pagination conventions — out of the per-tool descriptions and puts it here.Under dsh that guidance is dropped with no diagnostic on either side. From the server author's view it is indistinguishable from a server that never sent it. The only workaround is to inline the guidance into every tool description, which is precisely what the spec tells servers not to do.
Minimal proposal
After a generation connects, register the value as one prompt section, next to the existing tool registration:
Three details make it fit the shape already there:
serverNameis reserved per live instance, somcp:<serverName>cannot collide — the same invariant that keepsmcp__<serverName>__*unique, and section names throw on duplicates.syncToolsdisposer map: a reconnect re-reads it, and a disposed generation cannot leave behind a section describing a server that is gone.ctx.get("systemPrompt")reads the service without the inject requirement, soinject = ["tools"]stays as it is and profiles assembled without a system prompt are unaffected.Backward compatible: a server that sends no
instructionscontributes nothing, and no existing section moves.Same shape as #3905 (
annotations.readOnlyHintdropped at registration) and #3821 (noroots/rootUrisent): the parts of the handshake outsidetools/*aren't consumed yet.Happy to send a PR if the shape looks right.
@deepseek-ai/dsh-mcp-client@0.1.1-rc.2, read from compiled output.All reactions