* OTEL: Fix attribute compliance and improve telemetry helpers
Attribute compliance:
- Remove rpc.system/service/method (MCP is not traditional RPC)
- Add gen_ai.tool.name on tools/call spans
- Add gen_ai.prompt.name on prompts/get spans
- Fix session_id check (truthy -> is not None)
Telemetry helper improvements:
- Add is_recording() guards to skip work on non-recording spans
- Add error.type attribute with __qualname__ on error spans
- Use isinstance check for ToolError to set "tool_error" error type
- Include exception message in span status description
- Add tool_name/prompt_name params to server_span and client_span
Client call_tool enrichment:
- Reflect tool-level errors (result.isError) on client span status
so callers see ERROR even though the MCP protocol call succeeded
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove resource URI from span names to avoid high-cardinality
Per MCP semantic conventions, resource URIs SHOULD NOT be included in
span names by default since they can be unbounded (especially with
templates like users://{id}/profile). The URI remains available via
the mcp.resource.uri attribute.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add missing gen_ai/mcp attributes to proxy and delegate spans
- Proxy tool spans: add gen_ai.tool.name
- Proxy prompt spans: add gen_ai.prompt.name
- All delegate spans: add mcp.method.name
- Docs: remove rpc.* references, update span names and attributes table
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Hoist ToolError imports to module level, add rpc.* migration note
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix broken code examples in docs
- Tag error output blocks as ```text instead of ```python (anthropic,
openai integration docs + v2 mirrors)
- Quote unquoted URL in Descope config example (+ v2 mirror)
- Fix GoogleGenAISamplingHandler → GoogleGenaiSamplingHandler casing
in sampling docs
- Fix import path: handlers.GoogleGenaiSamplingHandler →
handlers.google_genai.GoogleGenaiSamplingHandler in v3-features
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix remaining broken doc examples and add skip tags for false positives
- BearerTokenAuth → StaticTokenVerifier in deployment/http.mdx
- providers.oauth → server.auth import in authentication.mdx
- ListToolsNext → updated list_tools API in v3-features.mdx
- OAuthClientProvider → OAuth in v2/storage-backends.mdx
- Add test="skip" for upgrade guides, contrib placeholders, f-string backticks
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Ratchet doc example baselines to zero
All 1444 examples now pass syntax and import checks.
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add pytest-examples dev dep, fix client_id in StaticTokenVerifier example, commit missed openapi fixes
- Add pytest-examples to dev dependencies (fixes CI ModuleNotFoundError)
- Include required client_id in StaticTokenVerifier token payload
- Commit previously unstaged HTTPRoute import fixes in openapi.mdx
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Update deprecated import paths across docs
- fastmcp.server.openapi → fastmcp.server.providers.openapi
- fastmcp.server.proxy → fastmcp.server.providers.proxy
- fastmcp.server.apps → fastmcp.apps
- Tag upgrade guide "Before" examples with test="skip"
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: Add encoding parameter to FileResource
- Add optional encoding field (str | None, default None) to FileResource.
- Pass encoding through to read_text() for cross-platform text file reading.
- Preserve backward compatibility by defaulting to system encoding.
* test: Add tests for FileResource encoding parameter
- Test UTF-8 reading with explicit encoding for non-ASCII content.
- Test backward compatibility when no encoding is specified.
- Test that encoding is ignored for binary file reads.
- Test Latin-1 reading with matching encoding.
* docs: Document FileResource encoding parameter
- Add encoding="utf-8" to FileResource example in resource classes guide.
- Update FileResource description to mention encoding support.
* feat: Change FileResource encoding default from None to utf-8
- Default to utf-8 instead of system encoding to prevent cross-platform footgun.
- Update field description to reflect new default.
- Update test to verify default encoding is utf-8 with non-ASCII content.
- Remove redundant encoding="utf-8" from docs example since it is now the default.
* fix: enforce auth/visibility in ResourcesAsTools and PromptsAsTools for non-FastMCP providers
🤖 Co-authored-by: Claude <noreply@anthropic.com>
* fix: honor stdio auth bypass and correct transform ordering in provider wrappers
Co-authored-by: Claude <noreply@anthropic.com>
* fix: move context/dependencies imports into function to break circular import
* fix: route ResourcesAsTools/PromptsAsTools through ctx.fastmcp
Instead of manually reimplementing auth, visibility, and session
transforms in the transform layer, tool functions now call
ctx.fastmcp.read_resource() / ctx.fastmcp.render_prompt() which
routes through the server's full middleware chain. This matches
the pattern CodeMode uses with ctx.fastmcp.call_tool().
The isinstance(provider, FastMCP) branching is removed entirely.
* feat: add _scope parameter for provider-scoped listing
AggregateProvider can now filter which child providers to query when
listing components. ResourcesAsTools and PromptsAsTools use this to
scope listings to their configured provider while still routing
through ctx.fastmcp for full middleware coverage.
The scope matching walks wrapped providers, so a
WrappedProvider(Namespace, inner=MyProvider) matches if MyProvider
is in the scope list.
* test: add coverage for ResourcesAsTools scoped to a sub-server
* fix: delegate to super() when _scope is None, add AggregateProvider to scope matching
* simplify: remove _scope machinery, route everything through ctx.fastmcp
Reverts the _scope parameter from Provider/AggregateProvider/Server.
ResourcesAsTools and PromptsAsTools now simply route through
ctx.fastmcp for all operations. Apply to a FastMCP server instance
for proper auth/visibility/middleware coverage.
Tests rewritten to use FastMCP server directly instead of raw providers.
* warn when ResourcesAsTools/PromptsAsTools is applied to a non-FastMCP provider
* docs: explain that ResourcesAsTools/PromptsAsTools should wrap a FastMCP server
* raise TypeError instead of warning when applied to non-FastMCP provider
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat: make upstream_client_secret optional in OAuthProxy
Extract _create_upstream_oauth_client() factory method for subclass
override. Cookie signing falls back to JWT key material when no secret.
* fix: include client_id in revocation requests for public clients
* fix: use factory method for revocation auth
* fix: cache component lists in ProxyProvider to avoid redundant backend connections
Every call_tool through a proxy was triggering _list_tools() to resolve
the tool by name, opening a full MCP session just for the lookup, then
opening a second session for the actual execution. This caches component
lists on the ProxyProvider with a configurable TTL (default 300s),
cutting backend handshakes in half for repeated calls.
* docs: document component caching and session reuse for proxy providers
* fix: add sleep in cache TTL test for Windows clock resolution
* docs: clarify cache scope and dynamic backend guidance
* Add tests for two-stage pattern, empty full-detail results, empty inputs
* Add ListTools, search limit, catalog size annotation; split tests
Co-authored-by: Claude <noreply@anthropic.com>
* Remove BM25 internal cap so Search.limit is the sole truncation point
* Pass default_limit to BM25 instead of arbitrary high cap
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Decompose CodeMode into composable discovery tools
CodeMode now owns only the execute sandbox. Discovery tools (search,
get_schema, etc.) are composable via the discovery_tools parameter.
Each is a Callable[[GetToolCatalog], Tool] factory.
Ships SearchTool (lightweight name+description results) and SchemaTool
(brief markdown or full JSON schemas by tool name) as built-in defaults.
* Rename to Search/GetSchemas/Tags, add tag filtering, fix bugs
- Rename SearchTool→Search, SchemaTool→GetSchemas, Categories→Tags
- Add tags parameter to Search for LLM-side tag filtering
- Add Tags discovery tool for browsing tools by tag
- Fix shared singleton default factories (now per-instance)
- Fix get_schema full mode returning invalid JSON on partial matches
- Fix "untagged" filter inconsistency between Tags and Search
- Split serialization tests to comply with loq line limit
- Rewrite docs for conceptual clarity
* Add three-tier detail levels, remove default_arguments, rename Tags→GetTags, rewrite docs
* Clean up __all__ exports, return valid JSON for empty full-detail results
* Replace vendored DI with uncalled-for
FastMCP vendored a minimal DI engine extracted from Docket (~164 lines)
with try/except fallback patterns everywhere. The `uncalled-for` package
is a clean, typed extraction of this same system, and since Docket will
also depend on it (chrisguidry/docket#353), `uncalled_for.Dependency`
becomes the single canonical base class.
This deletes the `_vendor/docket_di/` directory, replaces all the
try/except import patterns with direct `uncalled_for` imports, and
updates the `Dependency.execution` → `current_execution` ContextVar
references to match the Docket branch. The `Progress` class now
delegates to an internal impl and returns `self` from `__aenter__`
(matching Docket's pattern) so that ty's generic resolution works
without `type: ignore` suppressions.
Temporarily points pydocket at the `use-uncalled-for` branch so both
sides can be validated together in CI.
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Re-export Dependency from fastmcp.dependencies
Internal code like azure.py should import from the fastmcp namespace
rather than reaching into uncalled_for directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Import Dependency from fastmcp namespace in tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add generic type parameters to Dependency subclasses
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Mention uncalled-for in DI docs
The DI engine now comes from uncalled-for, so the docs should credit
it alongside Docket. Also updates the Docket docs link to docket.lol.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Point docket dependency at main
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Bump uncalled-for pin to >=0.2.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix uncalled-for imports for 0.2.0 API changes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Support Shared() dependencies without docket
Enters a SharedContext at server lifetime so that Shared() dependencies
from uncalled-for resolve once and are cached across tool/resource/prompt
calls. When running with docket, the Worker already handles this; this
covers the non-docket path and direct call_tool() usage.
Also re-exports Shared from fastmcp.dependencies.
Closes#3251
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Bump docket lockfile to latest main
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Remove duplicate test classes from rebase conflict resolution
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Point docket dependency at pydocket>=0.18.0 release
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Pair SharedContext __aenter__ with __aexit__ in Context lifecycle
The old `_ensure_shared_context` on the server called `__aenter__()` on a
lazy `SharedContext` but never `__aexit__()`, leaking the exit stack and
its resources. Moved the SharedContext management into Context's own
enter/exit so it's properly paired: when docket is available the lifespan
handles it, otherwise Context creates and cleans up a per-request one.
Updated Shared() tests to use Client (which runs the lifespan) rather
than calling server methods directly, since cross-request sharing
requires a lifespan.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Hoist SharedContext import to module level
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add MultiAuth for composing multiple token verification sources
🤖 Generated with Claude Code
https://claude.ai/code/session_01WwKYDCqjM2FqYwY5ZNVvjb
* Fix ruff lint/format in MultiAuth tests
🤖 Generated with Claude Code
https://claude.ai/code/session_01WwKYDCqjM2FqYwY5ZNVvjb
* Fix MultiAuth well-known route delegation and empty scopes handling
🤖 Generated with Claude Code
https://claude.ai/code/session_01WwKYDCqjM2FqYwY5ZNVvjb
* Harden MultiAuth: exception resilience, mcp_path propagation, test coverage
- verify_token now catches exceptions from individual sources and
continues to the next, so one broken verifier can't take down the
whole chain
- set_mcp_path propagates to verifiers, not just the server
- Fix jwks_url→jwks_uri typo in class docstring
- Add tests for raising verifiers, valid-token HTTP acceptance,
and set_mcp_path propagation
* Clean up MultiAuth: precompute sources, deduplicate test helpers
* Fix version badges to 3.1.0
---------
Co-authored-by: Claude <noreply@anthropic.com>