* Mirror front protocol era onto proxy backend connection
A proxy created from a non-Client target now negotiates, on its backend,
whatever era its front client negotiated, instead of pinning one era.
Explicit create_proxy(mode=...) still overrides. Guards the eager backend
initialize() so an explicit modern pin behind a handshake front no longer
crashes.
* Carry the mirrored proxy era into multi-server config backends
A multi-server MCPConfig target mounts one proxy per configured server on a
composite router, so setting the era on the outer client stopped at the router
and every real backend stayed on its default era. TransportOptions.backend_mode
carries it down, resolved per request alongside the outer mirroring.
The router is also sealed under a policy held on the transport rather than a
fresh per-router ephemeral key, so a guard tool's request_state survives the
router being rebuilt between rounds.
* Add guard-mode MRTR server support (SEP-2322)
* Add server-side MRTR guard tests
* Add MRTR guard docs, exports, and output-schema handling
* Apply formatting to MRTR guard changes
* Fix MRTR review round 1: middleware-safe suspend, Annotated strip, stable audience
- ToolInputRequired subclasses BaseException (CancelledError precedent) so
error middleware's broad except Exception cannot swallow a suspension
- Strip InputRequiredResult arms inside Annotated return types
- Reject a custom RequestStateSecurity without a stable audience (random
per-replica server names would break shared-key verification)
* Fix static analysis: rewrite tuple([...]) as tuple literal (C409)
* Recognize InputRequiredResult inside Annotated union arms
_is_input_required_type now peels Annotated first, so a metadata-carrying
guard arm (str | Annotated[InputRequiredResult, Field(...)]) is stripped
and the data arm's output schema survives.
* docs: frame multi-round tools as elicitation on the modern protocol
Fold multi-round-tools.mdx into elicitation.mdx as two eras of one
capability; drop pause/suspend framing for the stateless per-round model.
* Transport MRTR asks as InputRequiredToolResult, not a raised signal
An input-required result is the full result of a stateless MRTR leg, so it
flows through the middleware chain as an ordinary ToolResult subclass instead
of a raised ToolInputRequired(BaseException). Middleware observes it, caching
skips it, and response-limiting leaves it untouched.
* Document MRTR middleware interaction and the isinstance pattern
* Update MRTR change-register verify note to InputRequiredToolResult
* Align test module docstring with result-cycle framing
* Fix MRTR review: bypass cache on continuation legs; soften audience guard
- ResponseCachingMiddleware skips read AND write on continuation legs:
the cache key is name+arguments only, so a continuation's final result
would be served to later fresh calls, which would never be asked
- The stable-audience check is a warning, not an error: a policy object
cannot reveal whether its keys are shared, and single-process
customization (ephemeral ttl, custom codec) is legitimate unnamed
* Treat state-only rounds as continuations in the response cache
A round carrying request_state but no questions retries with
input_responses=None; request_state alone must bypass the cache or its
terminal result is stored under the fresh-call key.
* Fix MRTR review round: preserve asks through transforms, empty-name audience, docs predicate
- TransformedTool.run returns an InputRequiredToolResult intact instead of
reshaping it into an empty ToolResult for non-object output schemas
- audience warning uses a falsy-name check (empty string also autogenerates
a per-replica name)
- the elicitation docs continuation predicate checks request_state too
* Add create_proxy(mode=) opt-in for guard round-tripping through proxies
An auto-created proxy client stays handshake-era by default (a dual-era
backend serves both, and one proxy session is one era; handshake preserves
server-initiated push forwarding). Pass create_proxy(target, mode="auto")
to negotiate modern so an upstream guard's InputRequiredResult round-trips —
the two are mutually exclusive per session.
* Wrap raw InputRequiredResult returned by a transform_fn
A custom transform function may return the raw ask directly, like any tool
body — wrap it into InputRequiredToolResult so it survives output
normalization and reaches the wire, not only pre-wrapped forwarded guards.
* Reject input-required results from background tasks
* Unwrap type aliases before stripping guard arms
* Apply ruff format
* Recursively strip guard arms through nested and composed aliases
* Reflect MRTR continuation fields on the middleware message
* Suppress output schema for InputRequiredResult subclasses
* Forward progress on modern proxy tool calls
* Suppress output schema for bare aliased guard returns
* Suppress output schema for any surviving guard return wrapping