chore: import upstream snapshot with attribution
Deploy Docs / deploy-docs (push) Failing after 1s
Conformance Tests / client-conformance (push) Failing after 3s
Conformance Tests / server-conformance (push) Failing after 1s
GitHub Actions Security Analysis / zizmor (push) Failing after 1s
CI / checks (push) Failing after 59m20s
CI / all-green (push) Waiting to run
Deploy Docs / deploy-docs (push) Failing after 1s
Conformance Tests / client-conformance (push) Failing after 3s
Conformance Tests / server-conformance (push) Failing after 1s
GitHub Actions Security Analysis / zizmor (push) Failing after 1s
CI / checks (push) Failing after 59m20s
CI / all-green (push) Waiting to run
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
"""Request and result _meta round trips against the low-level Server, through the public Client API.
|
||||
|
||||
Meta is opaque pass-through data, so these tests assert identity against the value that was sent
|
||||
rather than snapshotting a literal: the expected value and the sent value are the same variable,
|
||||
which also proves the SDK injected nothing alongside it.
|
||||
"""
|
||||
|
||||
import mcp_types as types
|
||||
import pytest
|
||||
from mcp_types import CallToolResult, RequestParamsMeta, TextContent
|
||||
|
||||
from mcp.server import Server, ServerRequestContext
|
||||
from tests.interaction._connect import Connect
|
||||
from tests.interaction._requirements import requirement
|
||||
|
||||
pytestmark = pytest.mark.anyio
|
||||
|
||||
|
||||
@requirement("meta:request-to-handler")
|
||||
async def test_request_meta_reaches_handler(connect: Connect) -> None:
|
||||
"""The _meta object the client attaches to a request arrives at the tool handler unchanged."""
|
||||
request_meta: RequestParamsMeta = {"example.com/trace": "abc-123"}
|
||||
observed_metas: list[dict[str, object]] = []
|
||||
|
||||
async def list_tools(
|
||||
ctx: ServerRequestContext, params: types.PaginatedRequestParams | None
|
||||
) -> types.ListToolsResult:
|
||||
return types.ListToolsResult(tools=[types.Tool(name="traced", input_schema={"type": "object"})])
|
||||
|
||||
async def call_tool(ctx: ServerRequestContext, params: types.CallToolRequestParams) -> CallToolResult:
|
||||
assert params.name == "traced"
|
||||
assert ctx.meta is not None
|
||||
observed_metas.append(dict(ctx.meta))
|
||||
return CallToolResult(content=[TextContent(text="traced")])
|
||||
|
||||
server = Server("observability", on_list_tools=list_tools, on_call_tool=call_tool)
|
||||
|
||||
async with connect(server) as client:
|
||||
await client.call_tool("traced", {}, meta=request_meta)
|
||||
|
||||
assert observed_metas == [dict(request_meta)]
|
||||
|
||||
|
||||
@requirement("meta:result-to-client")
|
||||
async def test_result_meta_reaches_client(connect: Connect) -> None:
|
||||
"""The _meta object a handler attaches to its result is delivered to the client unchanged."""
|
||||
result_meta = {"example.com/cost": 3}
|
||||
|
||||
async def list_tools(
|
||||
ctx: ServerRequestContext, params: types.PaginatedRequestParams | None
|
||||
) -> types.ListToolsResult:
|
||||
return types.ListToolsResult(tools=[types.Tool(name="metered", input_schema={"type": "object"})])
|
||||
|
||||
async def call_tool(ctx: ServerRequestContext, params: types.CallToolRequestParams) -> CallToolResult:
|
||||
assert params.name == "metered"
|
||||
return CallToolResult(content=[TextContent(text="done")], _meta=result_meta)
|
||||
|
||||
server = Server("observability", on_list_tools=list_tools, on_call_tool=call_tool)
|
||||
|
||||
async with connect(server) as client:
|
||||
result = await client.call_tool("metered", {})
|
||||
|
||||
assert result == CallToolResult(content=[TextContent(text="done")], _meta=result_meta)
|
||||
Reference in New Issue
Block a user