examples/stories/dual_era/README.md
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.
# 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.
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.client.protocol_version on the client after connect; ctx.protocol_version
inside a lowlevel handler; ctx.request_context.protocol_version inside an
MCPServer handler.ctx.request_context.protocol_version is the current way to read the
negotiated version; a later release will shorten it to ctx.transport.*.MCP-Protocol-Version header is mis-routed to the legacy
path. The body-primary classifier lands in a later release.legacy_routing/ (route eras yourself), reconnect/ (persist DiscoverResult
for zero-RTT reconnect).