|
11 | 11 | from mcp.shared.version import SUPPORTED_PROTOCOL_VERSIONS |
12 | 12 | from mcp.types import ( |
13 | 13 | LATEST_PROTOCOL_VERSION, |
| 14 | + CallToolResult, |
14 | 15 | ClientNotification, |
15 | 16 | ClientRequest, |
16 | 17 | Implementation, |
|
23 | 24 | JSONRPCResponse, |
24 | 25 | ServerCapabilities, |
25 | 26 | ServerResult, |
| 27 | + TextContent, |
26 | 28 | ) |
27 | 29 |
|
28 | 30 |
|
@@ -492,8 +494,65 @@ async def mock_server(): |
492 | 494 |
|
493 | 495 | # Assert that capabilities are properly set with custom callbacks |
494 | 496 | 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 |
496 | 499 | 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 |
498 | 502 | 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