modelcontextprotocol / modelcontextprotocol/python-sdk
`ClientSessionGroup` attempts to use capabilities that were not advertised
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 24.3k
- Forks
- 4k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 31
Description
Initial Checks
- I confirm that I'm using the latest version of MCP Python SDK
- I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this issue
Description
ClientSessionGroup calls session.list_tools, session.list_prompts(), and session.list_resources() unconditionally on every connect. It never consults the ServerCapabilities returned by initialize.
For a server that doesn't implement tools, prompts, or resources, the corresponding calls return a JSON-RPC Method not found error. The MCPError is squashed and a WARNING is emitted, e.g.,
WARNING:root:Could not fetch prompts: Method not found
This seems to contradict the MCP lifecycle spec (2025-11-25, Capability Negotiation / Operation):
Both parties MUST: ... Only use capabilities that were successfully negotiated.
ClientSessionGroup should inspect session.initialize_result.capabilities and only interrogate capabilities that the server advertised, e.g.,
caps = session.initialize_result.capabilities if session.initialize_result else None
if caps and caps.prompts is not None:
prompts = (await session.list_prompts()).prompts
...
if caps and caps.resources is not None:
resources = (await session.list_resources()).resources
...
if caps and caps.tools is not None:
tools = (await session.list_tools()).tools
...
Example Code
"""Repro: tools-only server + ClientSessionGroup emits WARNINGs."""
from __future__ import annotations
import anyio
from mcp import Client, types
from mcp.client.session_group import ClientSessionGroup
from mcp.server import Server, ServerRequestContext
async def handle_list_tools(
ctx: ServerRequestContext, params: types.PaginatedRequestParams | None
) -> types.ListToolsResult:
return types.ListToolsResult(
tools=[
types.Tool(
name="ping",
description="Ping",
input_schema={"type": "object", "properties": {}},
)
]
)
async def handle_call_tool(
ctx: ServerRequestContext, params: types.CallToolRequestParams
) -> types.CallToolResult:
return types.CallToolResult(content=[types.TextContent(type="text", text="pong")])
async def main() -> None:
server = Server(
"tools-only-server",
on_list_tools=handle_list_tools,
on_call_tool=handle_call_tool,
)
async with Client(server) as client:
# Server omits prompts/resources capabilities:
assert client.initialize_result.capabilities.prompts is None
assert client.initialize_result.capabilities.resources is None
group = ClientSessionGroup()
await group.connect_with_session(client.initialize_result.server_info, client.session)
if __name__ == "__main__":
anyio.run(main)
Python & MCP Python SDK
Python: 3.14.4
MCP Python SDK: main @ da4c118 (also reproducible on v1.27.1)
OS: Linux 6.6.87.2-microsoft-standard-WSL2 x86_64
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at mcp.client.session_group.ClientSessionGroup.connect_with_session and inspect how it uses the session's initialize_result capabilities. Run the supplied tools-only server reproduction and confirm that unadvertised prompts and resources are not queried, while advertised tools remain available without Method not found warnings.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100