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

This commit is contained in:
wehub-resource-sync
2026-07-13 12:10:27 +08:00
commit 49b9bb6724
992 changed files with 161690 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
# reconnect
Probe `server/discover` once, persist the `DiscoverResult`, and reconnect with
**zero round-trips**. The first client connects at `mode="auto"` (one
`server/discover` request inside `__aenter__`); a second client at
`mode=LATEST_MODERN_VERSION, prior_discover=<cached>` enters with no wire
traffic and has `server_info` / `server_capabilities` available immediately.
## Run it
```bash
# over HTTP — Streamable HTTP only; in-memory has no "round-trip" to skip.
# The client self-hosts the server on a free port, runs, then tears it down.
uv run python -m stories.reconnect.client --http
# same, against the lowlevel-API server variant
uv run python -m stories.reconnect.client --http --server server_lowlevel
```
## What to look at
- `client.py` — the first `Client(targets(), mode="auto")`. The `mode="auto"`
connect ladder runs `server/discover` inside `__aenter__`;
`client.session.discover_result` is the cached result. Round-trip it through
`model_dump_json()` / `DiscoverResult.model_validate_json()` to model an
on-disk cache.
- `client.py` — `Client(targets(), mode=LATEST_MODERN_VERSION,
prior_discover=rehydrated)`. A version pin plus a prior `DiscoverResult`
installs the cached state via `ClientSession.adopt()` with no `initialize`
and no `server/discover` on the wire — the era-neutral `client.server_info` /
`.server_capabilities` accessors are populated before the first request.
- `client.py` — `targets()`. A `Client` cannot be re-entered after exit; each
call yields a fresh target against the same server, so the reconnect is a
genuinely new connection.
## Caveats
- `mode=<version-pin>` *without* `prior_discover=` synthesizes a placeholder
whose `server_info` is `Implementation(name="", version="")`. Pass the cached
result to get real identity on reconnect. Whether `Client` should expose a
public synthesizer (or refuse the bare pin) is open.
- `client.session.discover_result` is a one-hop reach into the mechanics layer;
`Client` does not yet surface the cached result directly.
- The wire-level proof that the second entry sends zero requests lives in the
interaction suite (`test_prior_discover_populates_state_with_zero_connect_time_traffic`);
this story asserts only what's observable through the public `Client`
surface.
## Spec
- [`server/discover`](https://modelcontextprotocol.io/specification/draft/server/discover)
- [Versioning — backward compatibility](https://modelcontextprotocol.io/specification/draft/basic/versioning)
## See also
`dual_era/` (auto-discover + era-neutral accessors), `parallel_calls/` (the
other multi-connection client).
+44
View File
@@ -0,0 +1,44 @@
"""Probe server/discover once, persist the result, reconnect with zero round-trips — a fresh `Client` via `targets`."""
from mcp_types import DiscoverResult
from mcp_types.version import LATEST_MODERN_VERSION
from mcp.client import Client
from stories._harness import TargetFactory, run_client
async def main(targets: TargetFactory, *, mode: str = "auto") -> None:
# The caller's mode (the real-user "auto" default) probes server/discover inside
# __aenter__ and caches the result; a hard version pin would skip the probe and
# never see the server's real DiscoverResult.
async with Client(targets(), mode=mode) as client:
discovered = client.session.discover_result
assert discovered is not None, "mode='auto' against a modern server populates discover_result"
assert client.protocol_version == LATEST_MODERN_VERSION
assert client.server_info.name == "reconnect-example"
assert LATEST_MODERN_VERSION in discovered.supported_versions
result = await client.call_tool("add", {"a": 2, "b": 3})
assert result.structured_content == {"result": 5}, result
# Round-trip through JSON to model loading the result from an on-disk cache.
saved = discovered.model_dump_json(by_alias=True)
rehydrated = DiscoverResult.model_validate_json(saved)
assert rehydrated == discovered
# Reconnect: a version pin plus the cached DiscoverResult adopts the prior state with
# zero round-trips on entry. A Client cannot be re-entered after exit, so targets()
# yields a fresh one. Without prior_discover= a bare pin would synthesize a blank
# server_info — the cache is what makes the era-neutral accessors useful here.
async with Client(targets(), mode=LATEST_MODERN_VERSION, prior_discover=rehydrated) as second:
assert second.protocol_version == LATEST_MODERN_VERSION
assert second.server_info.name == "reconnect-example"
assert second.server_capabilities.tools is not None
assert second.session.discover_result == rehydrated
result = await second.call_tool("add", {"a": 1, "b": 1})
assert result.structured_content == {"result": 2}, result
if __name__ == "__main__":
run_client(main)
+23
View File
@@ -0,0 +1,23 @@
"""A small modern server whose DiscoverResult a client persists for zero-RTT reconnect."""
from mcp.server.mcpserver import MCPServer
from stories._hosting import run_server_from_args
def build_server() -> MCPServer:
mcp = MCPServer(
"reconnect-example",
version="1.0.0",
instructions="Call add(a, b) to sum two integers.",
)
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two integers."""
return a + b
return mcp
if __name__ == "__main__":
run_server_from_args(build_server)
@@ -0,0 +1,48 @@
"""A small modern server whose DiscoverResult a client persists for zero-RTT reconnect (lowlevel API)."""
from typing import Any
import mcp_types as types
from mcp.server.context import ServerRequestContext
from mcp.server.lowlevel import Server
from stories._hosting import run_server_from_args
ADD = types.Tool(
name="add",
description="Add two integers.",
input_schema={
"type": "object",
"properties": {"a": {"type": "integer"}, "b": {"type": "integer"}},
"required": ["a", "b"],
},
)
def build_server() -> Server[Any]:
async def list_tools(
ctx: ServerRequestContext[Any], params: types.PaginatedRequestParams | None
) -> types.ListToolsResult:
return types.ListToolsResult(tools=[ADD])
async def call_tool(ctx: ServerRequestContext[Any], params: types.CallToolRequestParams) -> types.CallToolResult:
assert params.arguments is not None
if params.name == "add":
total = int(params.arguments["a"]) + int(params.arguments["b"])
return types.CallToolResult(
content=[types.TextContent(text=str(total))],
structured_content={"result": total},
)
raise NotImplementedError
return Server(
"reconnect-example",
version="1.0.0",
instructions="Call add(a, b) to sum two integers.",
on_list_tools=list_tools,
on_call_tool=call_tool,
)
if __name__ == "__main__":
run_server_from_args(build_server)