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) Has been cancelled

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
+58
View File
@@ -0,0 +1,58 @@
# dual-era
One server factory, both protocol eras. A `mode="legacy"` client runs the
`initialize` handshake; a `mode="auto"` client probes `server/discover` and
adopts the 2026 stateless era — the same `greet` tool answers both and reports
which era served it via `ctx.request_context.protocol_version`. **Start here**
when migrating a v1 server: the entry owns the era decision, the server body
stays era-agnostic.
## Run it
```bash
# over HTTP — the same /mcp endpoint serves both eras; the client self-hosts
# the server on a free port, runs, then tears it down
uv run python -m stories.dual_era.client --http
# same, against the lowlevel-API server variant
uv run python -m stories.dual_era.client --http --server server_lowlevel
```
The bare stdio invocation (`uv run python -m stories.dual_era.client`) is
legacy-only until the SDK's stdio entry can negotiate the era, so the modern
leg fails there today — run over `--http`.
## What to look at
- `client.py` — both connections are visible, against the same `targets()`
factory: `Client(targets(), mode=mode)` (default `"auto"`, the
discover-then-fallback ladder) and `Client(targets(), mode="legacy")` (forces
the `initialize` handshake). The era decision is one explicit `mode=` argument
at construction; no date strings appear in the body.
- `client.py``client.protocol_version` / `client.server_info` /
`client.server_capabilities` are era-neutral: populated by `initialize` *or*
`server/discover`, whichever ran.
- `server.py``ctx.request_context.protocol_version` is the era branch key
(lowlevel: `ctx.protocol_version` directly). Compare against
`MODERN_PROTOCOL_VERSIONS`, never a date literal.
- **Where to read the negotiated version.** One value, three read paths:
`client.protocol_version` on the client after connect; `ctx.protocol_version`
inside a lowlevel handler; `ctx.request_context.protocol_version` inside an
`MCPServer` handler.
## Caveats
- `ctx.request_context.protocol_version` is the current way to read the
negotiated version; a later release will shorten it to `ctx.transport.*`.
- Over HTTP the built-in era branch is currently header-only — a 2026 client
that omits the `MCP-Protocol-Version` header is mis-routed to the legacy
path. The body-primary classifier lands in a later release.
## Spec
- [Versioning — backward compatibility](https://modelcontextprotocol.io/specification/draft/basic/versioning)
- [`server/discover`](https://modelcontextprotocol.io/specification/draft/server/discover)
## See also
`legacy_routing/` (route eras yourself), `reconnect/` (persist `DiscoverResult`
for zero-RTT reconnect).
+41
View File
@@ -0,0 +1,41 @@
"""Connect to the same server factory twice — once per era, so `main` takes `targets` — and assert both are served."""
import mcp_types as types
from mcp_types.version import LATEST_HANDSHAKE_VERSION, LATEST_MODERN_VERSION
from mcp.client import Client
from stories._harness import TargetFactory, run_client
async def main(targets: TargetFactory, *, mode: str = "auto") -> None:
# ── modern arm: the caller's mode (the real-user "auto" default) probes
# ``server/discover`` and adopts the result — no ``initialize`` handshake runs.
# The version/info/capabilities accessors are era-neutral.
async with Client(targets(), mode=mode) as modern:
assert modern.protocol_version == LATEST_MODERN_VERSION
assert modern.server_info.name == "dual-era-example"
assert modern.server_capabilities.tools is not None
listed = await modern.list_tools()
assert [t.name for t in listed.tools] == ["greet"]
result = await modern.call_tool("greet", {"name": "2026 client"})
first = result.content[0]
assert isinstance(first, types.TextContent)
assert first.text == f"Hello, 2026 client! (served on the modern era at {LATEST_MODERN_VERSION})"
# ── legacy arm: a fresh connection to the SAME server, pinned to the handshake era.
# The same accessors are populated identically — here by ``initialize``.
async with Client(targets(), mode="legacy") as legacy:
assert legacy.protocol_version == LATEST_HANDSHAKE_VERSION
assert legacy.server_info.name == "dual-era-example"
assert legacy.server_capabilities.tools is not None
result = await legacy.call_tool("greet", {"name": "2025 client"})
first = result.content[0]
assert isinstance(first, types.TextContent)
assert first.text == f"Hello, 2025 client! (served on the legacy era at {LATEST_HANDSHAKE_VERSION})"
if __name__ == "__main__":
run_client(main)
+25
View File
@@ -0,0 +1,25 @@
"""One MCPServer factory that serves both the 2025 handshake era and the 2026 stateless era."""
from mcp_types.version import MODERN_PROTOCOL_VERSIONS
from mcp.server.mcpserver import Context, MCPServer
from stories._hosting import run_server_from_args
def build_server() -> MCPServer:
# The same factory serves both eras with no configuration. Which era a request is
# on is decided by the entry point / transport, never by the server.
mcp = MCPServer("dual-era-example", instructions="A small dual-era demo server.")
@mcp.tool()
async def greet(name: str, ctx: Context) -> str:
"""Greet the caller and report which protocol era served the request."""
pv = ctx.request_context.protocol_version
era = "modern" if pv in MODERN_PROTOCOL_VERSIONS else "legacy"
return f"Hello, {name}! (served on the {era} era at {pv})"
return mcp
if __name__ == "__main__":
run_server_from_args(build_server)
@@ -0,0 +1,50 @@
"""One lowlevel Server factory that serves both the 2025 handshake era and the 2026 stateless era."""
from typing import Any
import mcp_types as types
from mcp_types.version import MODERN_PROTOCOL_VERSIONS
from mcp.server.context import ServerRequestContext
from mcp.server.lowlevel import Server
from stories._hosting import run_server_from_args
GREET_INPUT_SCHEMA: dict[str, Any] = {
"type": "object",
"properties": {"name": {"type": "string"}},
"required": ["name"],
}
def build_server() -> Server[Any]:
async def list_tools(
ctx: ServerRequestContext[Any], params: types.PaginatedRequestParams | None
) -> types.ListToolsResult:
return types.ListToolsResult(
tools=[
types.Tool(
name="greet",
description="Greet the caller and report which protocol era served the request.",
input_schema=GREET_INPUT_SCHEMA,
),
]
)
async def call_tool(ctx: ServerRequestContext[Any], params: types.CallToolRequestParams) -> types.CallToolResult:
assert params.name == "greet" and params.arguments is not None
era = "modern" if ctx.protocol_version in MODERN_PROTOCOL_VERSIONS else "legacy"
text = f"Hello, {params.arguments['name']}! (served on the {era} era at {ctx.protocol_version})"
return types.CallToolResult(content=[types.TextContent(text=text)])
# The same factory serves both eras with no configuration. Which era a request is
# on is decided by the entry point / transport, never by the server.
return Server(
"dual-era-example",
instructions="A small dual-era demo server.",
on_list_tools=list_tools,
on_call_tool=call_tool,
)
if __name__ == "__main__":
run_server_from_args(build_server)