annotations.readOnlyHint is dropped at registration, so bridged MCP tools are always exclusive #3905
ezzaldeeen
started this conversation in
General
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.
what I observed
dsh-toolsdocuments the classification rule:dsh-tool-fsdeclaresisConcurrencySafe.@deepseek-ai/dsh-mcp-clientneverdoes — the string doesn't appear in its published
lib/index.js. So everybridged MCP tool is classified exclusive by construction, and
maxParallelToolCallscan never apply to any of them.MCP already carries the needed signal:
tools/listreturnsannotations.readOnlyHint, which means "no side effects". It appears to be readoff the wire and then discarded when the tool is registered on
ctx.tools.how I confirmed it
Our MCP server marks its read tools
readOnlyHint: trueand deliberately leaveswrite tools unhinted (they do read-modify-write on one JSON file, so
serialising them is correct).
Asking the agent for three independent reads, I never saw more than one call in
flight — measured from
session/updateframes over ACP, countingtool_callagainst terminal
tool_call_update. Same result on models that batch tool callsnatively, so it isn't the provider.
suggested mapping
annotations.readOnlyHint === true → isConcurrencySafe: () => true
Everything else stays exclusive, matching the registry's fail-closed default.
readOnlyHintis advisory in the MCP spec, so this trusts the server — butmounting a server is already an act of trust, and the blast radius is
concurrency rather than permission.
I'd expect this to be a small change in the executor/registration path
(
createExecutor, and thectx.tools.register(definition)call near it).version
@deepseek-ai/dsh-mcp-client@0.1.0-rc.7. Read from compiled output, not source.All reactions