Skip to content

Commit e673406

Browse files
author
Jianke LIN
committed
test(client): cover unadvertised capability branches
1 parent 0ac1c6e commit e673406

2 files changed

Lines changed: 41 additions & 8 deletions

File tree

src/mcp/client/session_group.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from collections.abc import Callable
1212
from dataclasses import dataclass
1313
from types import TracebackType
14-
from typing import Any, Literal, TypeAlias, overload
14+
from typing import Any, Literal, TypeAlias, cast, overload
1515

1616
import anyio
1717
import httpx
@@ -371,7 +371,7 @@ async def _establish_session(
371371
async def _aggregate_components(self, server_info: types.Implementation, session: mcp.ClientSession) -> None:
372372
"""Aggregates prompts, resources, and tools from a given session."""
373373

374-
capabilities = session.initialize_result.capabilities if session.initialize_result else None
374+
capabilities = cast(types.ServerCapabilities, session.server_capabilities)
375375

376376
# Create a reverse index so we can find all prompts, resources, and
377377
# tools belonging to this session. Used for removing components from
@@ -386,7 +386,7 @@ async def _aggregate_components(self, server_info: types.Implementation, session
386386
tool_to_session_temp: dict[str, mcp.ClientSession] = {}
387387

388388
# Query the server for its prompts and aggregate to list.
389-
if capabilities is None or capabilities.prompts is not None:
389+
if capabilities.prompts is not None:
390390
try:
391391
prompts = (await session.list_prompts()).prompts
392392
for prompt in prompts:
@@ -397,7 +397,7 @@ async def _aggregate_components(self, server_info: types.Implementation, session
397397
logging.warning(f"Could not fetch prompts: {err}")
398398

399399
# Query the server for its resources and aggregate to list.
400-
if capabilities is None or capabilities.resources is not None:
400+
if capabilities.resources is not None:
401401
try:
402402
resources = (await session.list_resources()).resources
403403
for resource in resources:
@@ -408,7 +408,7 @@ async def _aggregate_components(self, server_info: types.Implementation, session
408408
logging.warning(f"Could not fetch resources: {err}")
409409

410410
# Query the server for its tools and aggregate to list.
411-
if capabilities is None or capabilities.tools is not None:
411+
if capabilities.tools is not None:
412412
try:
413413
tools = (await session.list_tools()).tools
414414
for tool in tools:

tests/client/test_session_group.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,46 @@ async def handle_call_tool(ctx: ServerRequestContext, params: types.CallToolRequ
176176

177177
with caplog.at_level(logging.WARNING):
178178
async with Client(server) as client:
179-
assert client.initialize_result.capabilities.prompts is None
180-
assert client.initialize_result.capabilities.resources is None
179+
assert client.server_capabilities.prompts is None
180+
assert client.server_capabilities.resources is None
181181

182182
client.session.list_prompts = mock.AsyncMock(side_effect=AssertionError("list_prompts() was called"))
183183
client.session.list_resources = mock.AsyncMock(side_effect=AssertionError("list_resources() was called"))
184184

185-
await group.connect_with_session(client.initialize_result.server_info, client.session)
185+
await group.connect_with_session(client.server_info, client.session)
186+
await group.call_tool("ping")
187+
188+
assert not caplog.records
189+
190+
191+
@pytest.mark.anyio
192+
async def test_client_session_group_skips_unadvertised_tools_and_resources(
193+
caplog: pytest.LogCaptureFixture,
194+
):
195+
from mcp import Client
196+
from mcp.server import Server, ServerRequestContext
197+
198+
async def handle_list_prompts(
199+
ctx: ServerRequestContext, params: types.PaginatedRequestParams | None
200+
) -> types.ListPromptsResult:
201+
return types.ListPromptsResult(prompts=[types.Prompt(name="hello", description="Hello", arguments=[])])
202+
203+
server = Server(
204+
"prompts-only-server",
205+
on_list_prompts=handle_list_prompts,
206+
)
207+
208+
group = ClientSessionGroup()
209+
210+
with caplog.at_level(logging.WARNING):
211+
async with Client(server) as client:
212+
assert client.server_capabilities.tools is None
213+
assert client.server_capabilities.resources is None
214+
215+
client.session.list_tools = mock.AsyncMock(side_effect=AssertionError("list_tools() was called"))
216+
client.session.list_resources = mock.AsyncMock(side_effect=AssertionError("list_resources() was called"))
217+
218+
await group.connect_with_session(client.server_info, client.session)
186219

187220
assert not caplog.records
188221

0 commit comments

Comments
 (0)