|
24 | 24 | ServerCapabilities, |
25 | 25 | ServerResult, |
26 | 26 | ) |
| 27 | +import inspect |
| 28 | +from mcp.client.session import ClientSession |
27 | 29 |
|
28 | 30 |
|
29 | 31 | @pytest.mark.anyio |
@@ -497,3 +499,86 @@ async def mock_server(): |
497 | 499 | assert received_capabilities.roots is not None # Custom list_roots callback provided |
498 | 500 | assert isinstance(received_capabilities.roots, types.RootsCapability) |
499 | 501 | assert received_capabilities.roots.listChanged is True # Should be True for custom callback |
| 502 | + |
| 503 | +def test_call_tool_method_signature(): |
| 504 | + """Test that call_tool method accepts meta parameter in its signature.""" |
| 505 | + |
| 506 | + signature = inspect.signature(ClientSession.call_tool) |
| 507 | + |
| 508 | + assert 'meta' in signature.parameters, "call_tool method should have 'meta' parameter" |
| 509 | + |
| 510 | + meta_param = signature.parameters['meta'] |
| 511 | + assert meta_param.default is None, "meta parameter should default to None" |
| 512 | + |
| 513 | + |
| 514 | +def test_call_tool_request_params_construction(): |
| 515 | + """Test that CallToolRequestParams can be constructed with metadata.""" |
| 516 | + from mcp.types import CallToolRequestParams, RequestParams |
| 517 | + |
| 518 | + params_no_meta = CallToolRequestParams( |
| 519 | + name="test_tool", |
| 520 | + arguments={"param": "value"} |
| 521 | + ) |
| 522 | + assert params_no_meta.name == "test_tool" |
| 523 | + assert params_no_meta.arguments == {"param": "value"} |
| 524 | + assert params_no_meta.meta is None |
| 525 | + |
| 526 | + meta_data = { |
| 527 | + "progressToken": None, |
| 528 | + "user_id": "test_user", |
| 529 | + "session_id": "test_session", |
| 530 | + "custom_field": "custom_value" |
| 531 | + } |
| 532 | + test_meta = RequestParams.Meta.model_validate(meta_data) |
| 533 | + |
| 534 | + params_with_meta = CallToolRequestParams( |
| 535 | + name="test_tool", |
| 536 | + arguments={"param": "value"}, |
| 537 | + **{"_meta": test_meta} # Using alias |
| 538 | + ) |
| 539 | + |
| 540 | + assert params_with_meta.name == "test_tool" |
| 541 | + assert params_with_meta.arguments == {"param": "value"} |
| 542 | + assert params_with_meta.meta is not None |
| 543 | + |
| 544 | + dumped = params_with_meta.meta.model_dump() |
| 545 | + assert dumped["user_id"] == "test_user" |
| 546 | + assert dumped["session_id"] == "test_session" |
| 547 | + assert dumped["custom_field"] == "custom_value" |
| 548 | + |
| 549 | + |
| 550 | +def test_metadata_serialization(): |
| 551 | + """Test that metadata is properly serialized with _meta alias.""" |
| 552 | + from mcp.types import CallToolRequest, CallToolRequestParams, RequestParams |
| 553 | + |
| 554 | + meta_data = { |
| 555 | + "progressToken": None, |
| 556 | + "user_id": "alice", |
| 557 | + "api_key": "secret_123", |
| 558 | + "permissions": ["read", "write"] |
| 559 | + } |
| 560 | + test_meta = RequestParams.Meta.model_validate(meta_data) |
| 561 | + |
| 562 | + request = CallToolRequest( |
| 563 | + method="tools/call", |
| 564 | + params=CallToolRequestParams( |
| 565 | + name="secure_tool", |
| 566 | + arguments={"query": "sensitive_data"}, |
| 567 | + **{"_meta": test_meta} |
| 568 | + ) |
| 569 | + ) |
| 570 | + |
| 571 | + serialized = request.model_dump(by_alias=True) |
| 572 | + |
| 573 | + assert serialized["method"] == "tools/call" |
| 574 | + assert serialized["params"]["name"] == "secure_tool" |
| 575 | + assert serialized["params"]["arguments"]["query"] == "sensitive_data" |
| 576 | + |
| 577 | + assert "_meta" in serialized["params"] |
| 578 | + meta_data_serialized = serialized["params"]["_meta"] |
| 579 | + assert meta_data_serialized["user_id"] == "alice" |
| 580 | + assert meta_data_serialized["api_key"] == "secret_123" |
| 581 | + assert meta_data_serialized["permissions"] == ["read", "write"] |
| 582 | + assert meta_data["user_id"] == "alice" |
| 583 | + assert meta_data["api_key"] == "secret_123" |
| 584 | + assert meta_data["permissions"] == ["read", "write"] |
0 commit comments