fastmcp/tests/server
Jeremiah Lowin 717f3535f6
Add guard-mode multi-round-trip tools (SEP-2322) (#4544)
* 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
2026-07-19 16:42:06 -04:00
..
auth [codex] Add OAuthProxy RFC 9207 issuer responses (#4438) 2026-07-19 09:52:43 -04:00
http Add subject field to AccessToken initialization (#4267) 2026-07-18 21:15:13 -04:00
middleware Fix typos (#4498) 2026-07-18 21:18:39 -04:00
mount Apply ruff-format: drop now-unused imports and reflow 2026-07-07 07:53:11 -04:00
providers Migrate to MCP SDK v2.0.0b2 (httpx2) (#4503) 2026-07-18 15:12:47 -04:00
sampling Migrate to MCP Python SDK v2 (#4437) 2026-07-06 17:36:45 -04:00
tasks Clean up task sessions on connection exit (#4535) 2026-07-18 15:45:11 -04:00
telemetry Preserve telemetry attributes when a sampler does not forward them (#4539) 2026-07-19 09:00:04 -04:00
transforms Align server component docs (#4260) 2026-07-19 14:23:36 -04:00
versioning Migrate to MCP Python SDK v2 (#4437) 2026-07-06 17:36:45 -04:00
__init__.py restore 1.x code 2025-04-09 11:54:42 -04:00
test_app_state.py Update docs and test 2025-06-20 13:06:48 -04:00
test_auth_integration.py Migrate to MCP SDK v2.0.0b2 (httpx2) (#4503) 2026-07-18 15:12:47 -04:00
test_auth_integration_errors.py Migrate to MCP SDK v2.0.0b2 (httpx2) (#4503) 2026-07-18 15:12:47 -04:00
test_cache_hints.py Add server-level cache hints (SEP-2549) (#4464) 2026-07-08 09:10:41 -04:00
test_context.py Migrate to MCP Python SDK v2 (#4437) 2026-07-06 17:36:45 -04:00
test_dependencies.py Capture SharedContext for task-enabled Docket servers (#4443) 2026-07-07 07:48:49 -04:00
test_dependencies_advanced.py Migrate to MCP Python SDK v2 (#4437) 2026-07-06 17:36:45 -04:00
test_event_store.py Migrate to MCP Python SDK v2 (#4437) 2026-07-06 17:36:45 -04:00
test_fastapi_testclient_compat.py fix: FastAPI TestClient compatibility and lifespan re-initialization (#3736) 2026-04-06 19:53:27 -04:00
test_file_server.py Migrate to MCP Python SDK v2 (#4437) 2026-07-06 17:36:45 -04:00
test_icons.py Document icon theme support (#4537) 2026-07-18 20:57:36 -04:00
test_input_validation.py Migrate to MCP Python SDK v2 (#4437) 2026-07-06 17:36:45 -04:00
test_log_level.py Allow pre-bound HTTP sockets (#4222) 2026-05-23 10:08:49 -04:00
test_logging.py Refactor server.py into mixins (#2939) 2026-01-19 11:36:00 -05:00
test_mrtr_guards.py Add guard-mode multi-round-trip tools (SEP-2322) (#4544) 2026-07-19 16:42:06 -04:00
test_pagination.py Migrate to MCP Python SDK v2 (#4437) 2026-07-06 17:36:45 -04:00
test_protocol_eras.py Use a single fastmcp import style in protocol-era tests 2026-07-06 22:06:22 -04:00
test_providers.py Migrate to MCP Python SDK v2 (#4437) 2026-07-06 17:36:45 -04:00
test_server.py Repoint tests and examples off removed deprecations 2026-07-07 07:53:11 -04:00
test_server_docket.py Make pydocket optional and unify DI systems (#2835) 2026-01-10 16:23:32 -05:00
test_server_lifespan.py Update ty ignore comments for 0.0.25 compatibility (#3614) 2026-03-24 20:26:26 -04:00
test_server_safety.py fix: reject self-mount to prevent infinite recursion (#3925) 2026-04-14 12:10:19 -04:00
test_session_visibility.py Migrate to MCP Python SDK v2 (#4437) 2026-07-06 17:36:45 -04:00
test_streamable_http_no_redirect.py Migrate to MCP SDK v2.0.0b2 (httpx2) (#4503) 2026-07-18 15:12:47 -04:00
test_tool_annotations.py Migrate to MCP Python SDK v2 (#4437) 2026-07-06 17:36:45 -04:00
test_tool_transformation.py Migrate to MCP SDK v2.0.0b2 (httpx2) (#4503) 2026-07-18 15:12:47 -04:00
test_transport.py Forward-port HTTP host guard compatibility (#4474) 2026-07-08 20:55:56 -04:00