49b9bb6724
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
41 lines
1.7 KiB
Python
41 lines
1.7 KiB
Python
"""Two concurrent `Client`s, so `main` takes `targets`; their rendezvous in one tool proves concurrent dispatch."""
|
|
|
|
import anyio
|
|
from mcp_types import TextContent
|
|
|
|
from mcp.client import Client
|
|
from stories._harness import TargetFactory, run_client
|
|
|
|
|
|
async def main(targets: TargetFactory, *, mode: str = "auto") -> None:
|
|
party = ["a", "b"]
|
|
results: dict[str, str] = {}
|
|
received: dict[str, list[str | None]] = {tag: [] for tag in party}
|
|
|
|
async def attend(tag: str) -> None:
|
|
async def on_progress(progress: float, total: float | None, message: str | None) -> None:
|
|
received[tag].append(message)
|
|
|
|
# targets() yields a fresh connection target on every call; both land on the SAME
|
|
# server instance, so the two `meet` handlers can observe each other's arrival.
|
|
async with Client(targets(), mode=mode) as client:
|
|
result = await client.call_tool("meet", {"tag": tag, "party": party}, progress_callback=on_progress)
|
|
assert not result.is_error, result
|
|
assert isinstance(result.content[0], TextContent)
|
|
results[tag] = result.content[0].text
|
|
|
|
# Neither call can return until both handlers are running at once; a server that processed
|
|
# requests one-at-a-time would never set the second event and we'd time out here.
|
|
with anyio.fail_after(5):
|
|
async with anyio.create_task_group() as tg:
|
|
tg.start_soon(attend, "a")
|
|
tg.start_soon(attend, "b")
|
|
|
|
assert results == {"a": "a", "b": "b"}, results
|
|
# Progress is routed by progress token: each callback saw only its own tag, never the sibling's.
|
|
assert received == {"a": ["a"], "b": ["b"]}, received
|
|
|
|
|
|
if __name__ == "__main__":
|
|
run_client(main)
|