You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Should a client declare the same capabilities on tools/list as on tools/call (2026-07-28)?
#3836
Title: Should a client declare the same capabilities on tools/list as on tools/call (2026-07-28)?
Question
In 2026-07-28, client capabilities travel on every request in params._meta["io.modelcontextprotocol/clientCapabilities"] rather than once at initialize. That lets a server shape its responses per request, including tools/list.
But the spec doesn't seem to say anything about consistency between requests. In particular, can a client list tools while declaring one set of capabilities, then call those tools declaring a different set? If it can, a server has no reliable way to give the model a tool schema that matches how the call will actually be handled.
Is there a requirement or recommendation here, or should there be?
Why it matters
Take a server with a tool that needs user confirmation before it acts:
The client declares elicitation: the server confirms through an elicitation dialog, so the tool's schema needs nothing extra.
The client doesn't declare it: the server needs some other approach, for example an extra argument or different instructions in the tool description for the model to follow.
A server that does this returns a different tools/list depending on whether that request declares elicitation. That seems to be exactly the kind of per-request adaptation the envelope makes possible. It only works if what the client declares when listing matches what it declares when calling.
What we observed from one client (Claude.ai, 2026-11-13)
We connected the same MCP server from a Claude.ai Team plan account and a Free plan account, and logged what each request declared:
Request
clientInfo
Team plan
Free plan
tools/list on connect
Anthropic/Toolbox 1.0.0
{}
{}
tools/list from the chat
Anthropic/ClaudeAI 1.0.0
ui extension only
ui extension only
tools/call from the same chat
Anthropic/ClaudeAI 1.0.0
elicitation + ui
elicitation + ui
tools/list from "Refresh tools list"
claude-ai 0.1.0
elicitation + ui
ui extension only
Two inconsistencies stand out:
Listing vs calling, on both plans. Every tools/list from connect or chat omits elicitation, while every tools/call declares it.
Team vs Free, on refresh. The same "Refresh tools list" action declares elicitation on Team but not on Free. So a server that adapts its tool list shows different schemas on the two plans after a refresh, while the tool calls on both plans declare the same capabilities. The schema a user sees, and possibly the one the model works from, depends on the plan and on whether they've clicked refresh, not on how the calls are actually handled.
These are trimmed captures from the same connection (_meta only):
The result is that the model can hold a schema and instructions written for a client without elicitation, while every call it makes declares elicitation and is handled that way. A server that validates strictly against the schema for the capabilities declared on the call may then reject arguments the model was told to send.
Possible directions
Client guidance: within one connection, a client SHOULD declare the same capabilities on tools/list as on any tools/call that may follow, or at least a superset of what a later call will declare.
Server guidance: servers SHOULD NOT vary tool schemas by declared capabilities. They should keep one schema and branch only at call time. That's safe, but it gives up much of what per-request capabilities seem to enable.
An explicit statement that capabilities may legitimately differ per request, so servers know not to rely on tools/list.
Has anyone else hit this? Is there existing guidance we've missed?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Title: Should a client declare the same capabilities on tools/list as on tools/call (2026-07-28)?
Question
In 2026-07-28, client capabilities travel on every request in
params._meta["io.modelcontextprotocol/clientCapabilities"]rather than once atinitialize. That lets a server shape its responses per request, includingtools/list.But the spec doesn't seem to say anything about consistency between requests. In particular, can a client list tools while declaring one set of capabilities, then call those tools declaring a different set? If it can, a server has no reliable way to give the model a tool schema that matches how the call will actually be handled.
Is there a requirement or recommendation here, or should there be?
Why it matters
Take a server with a tool that needs user confirmation before it acts:
elicitation: the server confirms through an elicitation dialog, so the tool's schema needs nothing extra.A server that does this returns a different
tools/listdepending on whether that request declareselicitation. That seems to be exactly the kind of per-request adaptation the envelope makes possible. It only works if what the client declares when listing matches what it declares when calling.What we observed from one client (Claude.ai, 2026-11-13)
We connected the same MCP server from a Claude.ai Team plan account and a Free plan account, and logged what each request declared:
tools/liston connectAnthropic/Toolbox1.0.0{}{}tools/listfrom the chatAnthropic/ClaudeAI1.0.0uiextension onlyuiextension onlytools/callfrom the same chatAnthropic/ClaudeAI1.0.0elicitation+uielicitation+uitools/listfrom "Refresh tools list"claude-ai0.1.0elicitation+uiuiextension onlyTwo inconsistencies stand out:
tools/listfrom connect or chat omitselicitation, while everytools/calldeclares it.elicitationon Team but not on Free. So a server that adapts its tool list shows different schemas on the two plans after a refresh, while the tool calls on both plans declare the same capabilities. The schema a user sees, and possibly the one the model works from, depends on the plan and on whether they've clicked refresh, not on how the calls are actually handled.These are trimmed captures from the same connection (
_metaonly):{"method":"tools/list","params":{"_meta":{ "io.modelcontextprotocol/protocolVersion":"2026-07-28", "io.modelcontextprotocol/clientInfo":{"name":"Anthropic/ClaudeAI","version":"1.0.0"}, "io.modelcontextprotocol/clientCapabilities":{"extensions":{"io.modelcontextprotocol/ui":{}}}}}}{"method":"tools/call","params":{"_meta":{ "io.modelcontextprotocol/protocolVersion":"2026-07-28", "io.modelcontextprotocol/clientInfo":{"name":"Anthropic/ClaudeAI","version":"1.0.0"}, "io.modelcontextprotocol/clientCapabilities":{"elicitation":{"form":{},"url":{}}, "extensions":{"io.modelcontextprotocol/ui":{}}}}}}The result is that the model can hold a schema and instructions written for a client without elicitation, while every call it makes declares elicitation and is handled that way. A server that validates strictly against the schema for the capabilities declared on the call may then reject arguments the model was told to send.
Possible directions
tools/listas on anytools/callthat may follow, or at least a superset of what a later call will declare.tools/list.Has anyone else hit this? Is there existing guidance we've missed?
All reactions