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.
+