diff --git a/docs/docs.json b/docs/docs.json index eafdfc2e2..b391766d9 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -754,6 +754,7 @@ "python-sdk/fastmcp-utilities-skills", "python-sdk/fastmcp-utilities-tests", "python-sdk/fastmcp-utilities-timeout", + "python-sdk/fastmcp-utilities-token_cache", "python-sdk/fastmcp-utilities-types", "python-sdk/fastmcp-utilities-ui", "python-sdk/fastmcp-utilities-version_check", diff --git a/docs/python-sdk/fastmcp-client-sampling-handlers-anthropic.mdx b/docs/python-sdk/fastmcp-client-sampling-handlers-anthropic.mdx index 976367c28..ff48e7a31 100644 --- a/docs/python-sdk/fastmcp-client-sampling-handlers-anthropic.mdx +++ b/docs/python-sdk/fastmcp-client-sampling-handlers-anthropic.mdx @@ -10,7 +10,7 @@ Anthropic sampling handler for FastMCP. ## Classes -### `AnthropicSamplingHandler` +### `AnthropicSamplingHandler` Sampling handler that uses the Anthropic API. diff --git a/docs/python-sdk/fastmcp-client-sampling-handlers-google_genai.mdx b/docs/python-sdk/fastmcp-client-sampling-handlers-google_genai.mdx index 9681c3a4a..d55619c72 100644 --- a/docs/python-sdk/fastmcp-client-sampling-handlers-google_genai.mdx +++ b/docs/python-sdk/fastmcp-client-sampling-handlers-google_genai.mdx @@ -10,7 +10,7 @@ Google GenAI sampling handler with tool support for FastMCP 3.0. ## Classes -### `GoogleGenaiSamplingHandler` +### `GoogleGenaiSamplingHandler` Sampling handler that uses the Google GenAI API with tool support. diff --git a/docs/python-sdk/fastmcp-client-sampling-handlers-openai.mdx b/docs/python-sdk/fastmcp-client-sampling-handlers-openai.mdx index b291bbaa5..2d7976e0f 100644 --- a/docs/python-sdk/fastmcp-client-sampling-handlers-openai.mdx +++ b/docs/python-sdk/fastmcp-client-sampling-handlers-openai.mdx @@ -10,7 +10,7 @@ OpenAI sampling handler for FastMCP. ## Classes -### `OpenAISamplingHandler` +### `OpenAISamplingHandler` Sampling handler that uses the OpenAI API. diff --git a/docs/python-sdk/fastmcp-client-transports-config.mdx b/docs/python-sdk/fastmcp-client-transports-config.mdx index 7ad10e0df..3881c69e1 100644 --- a/docs/python-sdk/fastmcp-client-transports-config.mdx +++ b/docs/python-sdk/fastmcp-client-transports-config.mdx @@ -7,7 +7,7 @@ sidebarTitle: config ## Classes -### `MCPConfigTransport` +### `MCPConfigTransport` Transport for connecting to one or more MCP servers defined in an MCPConfig. @@ -59,13 +59,13 @@ async with client: **Methods:** -#### `connect_session` +#### `connect_session` ```python connect_session(self, **session_kwargs: Unpack[SessionKwargs]) -> AsyncIterator[ClientSession] ``` -#### `close` +#### `close` ```python close(self) diff --git a/docs/python-sdk/fastmcp-server-auth-providers-github.mdx b/docs/python-sdk/fastmcp-server-auth-providers-github.mdx index 03bd4e4c3..48d8e24da 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-github.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-github.mdx @@ -29,7 +29,7 @@ Example: ## Classes -### `GitHubTokenVerifier` +### `GitHubTokenVerifier` Token verifier for GitHub OAuth tokens. @@ -37,10 +37,14 @@ Token verifier for GitHub OAuth tokens. GitHub OAuth tokens are opaque (not JWTs), so we verify them by calling GitHub's API to check if they're valid and get user info. +Caching is disabled by default. Set ``cache_ttl_seconds`` to a positive +integer to cache successful verification results and avoid repeated +GitHub API calls for the same token. + **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -49,7 +53,7 @@ verify_token(self, token: str) -> AccessToken | None Verify GitHub OAuth token by calling GitHub API. -### `GitHubProvider` +### `GitHubProvider` Complete GitHub OAuth provider for FastMCP. diff --git a/docs/python-sdk/fastmcp-server-auth-providers-introspection.mdx b/docs/python-sdk/fastmcp-server-auth-providers-introspection.mdx index 811737e34..8666cc726 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-introspection.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-introspection.mdx @@ -31,7 +31,7 @@ Example: ## Classes -### `IntrospectionTokenVerifier` +### `IntrospectionTokenVerifier` OAuth 2.0 Token Introspection verifier (RFC 7662). @@ -59,7 +59,7 @@ introspection endpoint (e.g., ``cache_ttl_seconds=300`` for 5 minutes). **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None diff --git a/docs/python-sdk/fastmcp-tools-function_parsing.mdx b/docs/python-sdk/fastmcp-tools-function_parsing.mdx index ed4f301a5..6264ef5d3 100644 --- a/docs/python-sdk/fastmcp-tools-function_parsing.mdx +++ b/docs/python-sdk/fastmcp-tools-function_parsing.mdx @@ -10,11 +10,11 @@ Function introspection and schema generation for FastMCP tools. ## Classes -### `ParsedFunction` +### `ParsedFunction` **Methods:** -#### `from_function` +#### `from_function` ```python from_function(cls, fn: Callable[..., Any], exclude_args: list[str] | None = None, validate: bool = True, wrap_non_object_output_schema: bool = True) -> ParsedFunction diff --git a/docs/python-sdk/fastmcp-tools-tool_transform.mdx b/docs/python-sdk/fastmcp-tools-tool_transform.mdx index 0417c1904..321818b27 100644 --- a/docs/python-sdk/fastmcp-tools-tool_transform.mdx +++ b/docs/python-sdk/fastmcp-tools-tool_transform.mdx @@ -7,7 +7,7 @@ sidebarTitle: tool_transform ## Functions -### `forward` +### `forward` ```python forward(**kwargs: Any) -> ToolResult @@ -36,7 +36,7 @@ tool has args `a` and `b`, and an `transform_args` was provided that maps `x` to - `TypeError`: If provided arguments don't match the transformed schema. -### `forward_raw` +### `forward_raw` ```python forward_raw(**kwargs: Any) -> ToolResult @@ -62,7 +62,7 @@ y=2)` will call the parent tool with `x=1` and `y=2`. - `RuntimeError`: If called outside a transformed tool context. -### `apply_transformations_to_tools` +### `apply_transformations_to_tools` ```python apply_transformations_to_tools(tools: dict[str, Tool], transformations: dict[str, ToolTransformConfig]) -> dict[str, Tool] @@ -78,7 +78,7 @@ but transformations are keyed by tool name (e.g., "my_tool"). ## Classes -### `ArgTransform` +### `ArgTransform` Configuration for transforming a parent tool's argument. @@ -150,7 +150,7 @@ ArgTransform(name="new_name", description="New desc", default=None, type=int) ``` -### `ArgTransformConfig` +### `ArgTransformConfig` A model for requesting a single argument transform. @@ -158,7 +158,7 @@ A model for requesting a single argument transform. **Methods:** -#### `to_arg_transform` +#### `to_arg_transform` ```python to_arg_transform(self) -> ArgTransform @@ -167,7 +167,7 @@ to_arg_transform(self) -> ArgTransform Convert the argument transform to a FastMCP argument transform. -### `TransformedTool` +### `TransformedTool` A tool that is transformed from another tool. @@ -191,7 +191,7 @@ validation when forward() is called from custom functions. **Methods:** -#### `run` +#### `run` ```python run(self, arguments: dict[str, Any]) -> ToolResult @@ -210,7 +210,7 @@ functions. - ToolResult object containing content and optional structured output. -#### `from_tool` +#### `from_tool` ```python from_tool(cls, tool: Tool | Callable[..., Any], name: str | None = None, version: str | NotSetT | None = NotSet, title: str | NotSetT | None = NotSet, description: str | NotSetT | None = NotSet, tags: set[str] | None = None, transform_fn: Callable[..., Any] | None = None, transform_args: dict[str, ArgTransform] | None = None, annotations: ToolAnnotations | NotSetT | None = NotSet, output_schema: dict[str, Any] | NotSetT | None = NotSet, serializer: Callable[[Any], str] | NotSetT | None = NotSet, meta: dict[str, Any] | NotSetT | None = NotSet) -> TransformedTool @@ -293,7 +293,7 @@ async def custom_output(**kwargs) -> ToolResult: ``` -### `ToolTransformConfig` +### `ToolTransformConfig` Provides a way to transform a tool. @@ -301,7 +301,7 @@ Provides a way to transform a tool. **Methods:** -#### `apply` +#### `apply` ```python apply(self, tool: Tool) -> TransformedTool diff --git a/docs/python-sdk/fastmcp-utilities-token_cache.mdx b/docs/python-sdk/fastmcp-utilities-token_cache.mdx new file mode 100644 index 000000000..af0a890f8 --- /dev/null +++ b/docs/python-sdk/fastmcp-utilities-token_cache.mdx @@ -0,0 +1,87 @@ +--- +title: token_cache +sidebarTitle: token_cache +--- + +# `fastmcp.utilities.token_cache` + + +In-memory cache for token verification results. + +Provides a generic TTL-based cache for ``AccessToken`` objects, designed to +reduce repeated network calls during opaque-token verification. Only +*successful* verifications should be cached; errors and failures must be +retried on every request. + +Example: + ```python + from fastmcp.utilities.token_cache import TokenCache + + cache = TokenCache(ttl_seconds=300, max_size=10000) + + # On cache miss, call the upstream verifier and store the result. + hit, token = cache.get(raw_token) + if not hit: + token = await _call_upstream(raw_token) + if token is not None: + cache.set(raw_token, token) + ``` + + +## Classes + +### `TokenCache` + + +TTL-based in-memory cache for ``AccessToken`` objects. + +Features: +- SHA-256 hashed cache keys (fixed size, regardless of token length). +- Per-entry TTL that respects both the configured ``ttl_seconds`` and the + token's own ``expires_at`` claim (whichever is sooner). +- Bounded size with FIFO eviction when the cache is full. +- Periodic cleanup of expired entries to prevent unbounded growth. +- Defensive deep copies on both store and retrieve to prevent + callers from mutating cached values. + +Caching is disabled when ``ttl_seconds`` is ``None`` or ``0``, or +when ``max_size`` is ``0``. Negative values raise ``ValueError``. + + +**Methods:** + +#### `enabled` + +```python +enabled(self) -> bool +``` + +Return whether caching is active. + + +#### `get` + +```python +get(self, token: str) -> tuple[bool, AccessToken | None] +``` + +Look up a cached verification result. + +**Returns:** +- ``(True, AccessToken)`` on a cache hit, ``(False, None)`` on a miss +- or when caching is disabled. The returned ``AccessToken`` is a deep +- copy that is safe to mutate. + + +#### `set` + +```python +set(self, token: str, result: AccessToken) -> None +``` + +Store a *successful* verification result. + +Only successful verifications should be cached. Failures (inactive +tokens, missing scopes, HTTP errors, timeouts) must **not** be cached +so that transient problems do not produce sticky false negatives. +