Skip to content

Commit 05e6b27

Browse files
committed
Implement test to assert _meta behavior in tool call
1 parent 8f2ebb6 commit 05e6b27

File tree

1 file changed

+62
-3
lines changed

1 file changed

+62
-3
lines changed

tests/client/test_session.py

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from mcp.shared.version import SUPPORTED_PROTOCOL_VERSIONS
1212
from mcp.types import (
1313
LATEST_PROTOCOL_VERSION,
14+
CallToolResult,
1415
ClientNotification,
1516
ClientRequest,
1617
Implementation,
@@ -23,6 +24,7 @@
2324
JSONRPCResponse,
2425
ServerCapabilities,
2526
ServerResult,
27+
TextContent,
2628
)
2729

2830

@@ -492,8 +494,65 @@ async def mock_server():
492494

493495
# Assert that capabilities are properly set with custom callbacks
494496
assert received_capabilities is not None
495-
assert received_capabilities.sampling is not None # Custom sampling callback provided
497+
# Custom sampling callback provided
498+
assert received_capabilities.sampling is not None
496499
assert isinstance(received_capabilities.sampling, types.SamplingCapability)
497-
assert received_capabilities.roots is not None # Custom list_roots callback provided
500+
# Custom list_roots callback provided
501+
assert received_capabilities.roots is not None
498502
assert isinstance(received_capabilities.roots, types.RootsCapability)
499-
assert received_capabilities.roots.listChanged is True # Should be True for custom callback
503+
# Should be True for custom callback
504+
assert received_capabilities.roots.listChanged is True
505+
506+
507+
@pytest.mark.anyio
508+
@pytest.mark.parametrize(argnames="meta", argvalues=[{"toolMeta": "value"}])
509+
async def test_client_tool_call_with_meta(meta: dict[str, Any] | None):
510+
"""Test that client tool call requests can include metadata."""
511+
client_to_server_send, client_to_server_receive = anyio.create_memory_object_stream[SessionMessage](1)
512+
server_to_client_send, server_to_client_receive = anyio.create_memory_object_stream[SessionMessage](1)
513+
514+
async def mock_server():
515+
session_message = await client_to_server_receive.receive()
516+
jsonrpc_request = session_message.message
517+
assert isinstance(jsonrpc_request.root, JSONRPCRequest)
518+
519+
assert jsonrpc_request.root.method == "tools/call"
520+
521+
if meta is not None:
522+
assert jsonrpc_request.root.params
523+
assert "_meta" in jsonrpc_request.root.params
524+
assert jsonrpc_request.root.params["_meta"] == meta
525+
526+
result = ServerResult(
527+
CallToolResult(content=[TextContent(type="text", text="Called successfully")], isError=False)
528+
)
529+
530+
async with server_to_client_send:
531+
await server_to_client_send.send(
532+
SessionMessage(
533+
JSONRPCMessage(
534+
JSONRPCResponse(
535+
jsonrpc="2.0",
536+
id=jsonrpc_request.root.id,
537+
result=result.model_dump(by_alias=True, mode="json", exclude_none=True),
538+
)
539+
)
540+
)
541+
)
542+
543+
async with (
544+
ClientSession(
545+
server_to_client_receive,
546+
client_to_server_send,
547+
) as session,
548+
anyio.create_task_group() as tg,
549+
client_to_server_send,
550+
client_to_server_receive,
551+
server_to_client_send,
552+
server_to_client_receive,
553+
):
554+
tg.start_soon(mock_server)
555+
556+
session._tool_output_schemas["sample_tool"] = None
557+
558+
await session.call_tool(name="sample_tool", arguments={"foo": "bar"}, meta=meta)

0 commit comments

Comments
 (0)