Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
fbc0a3b
Consolidate tool transformation logic into TransformingProvider
jlowin Jan 10, 2026
e31e3fd
Fix: reject tool lookups by pre-transform name
jlowin Jan 10, 2026
4739415
Add collision validation for tool_transforms and fix docstring examples
jlowin Jan 10, 2026
317d1b5
Merge branch 'main' into consolidate-tool-transforms
jlowin Jan 10, 2026
9a46ef4
Add server-level tool transform APIs and fix task registration
jlowin Jan 11, 2026
c353e94
Add graceful degradation for provider errors in AggregateProvider
jlowin Jan 11, 2026
4fbd5ed
Match original behavior: parallel queries with DEBUG logging
jlowin Jan 11, 2026
ea1a67a
Refactor transforms to middleware-style call_next pattern
jlowin Jan 12, 2026
185b4f8
Add comprehensive transforms and visibility documentation
jlowin Jan 12, 2026
81adcdc
Restructure transforms docs and delete tool-transformation pattern
jlowin Jan 12, 2026
0e9e0ff
Cleanup: simplify get_tasks and remove unused Provider.get_component
jlowin Jan 12, 2026
cefd7e5
Merge branch 'main' into consolidate-tool-transforms
jlowin Jan 12, 2026
6e3d975
Update loq
jlowin Jan 12, 2026
0fddc85
Update loq limits and add loq note to AGENTS.md
jlowin Jan 12, 2026
e52eb82
Deprecate add_tool_transformation and tool_transformations param
jlowin Jan 13, 2026
3721dde
Merge branch 'main' into consolidate-tool-transforms
jlowin Jan 13, 2026
fe630a2
Address PR review feedback: remove redundant imports, fix path reference
jlowin Jan 13, 2026
7489684
Merge branch 'main' into consolidate-tool-transforms
jlowin Jan 13, 2026
19cbff3
Add missing imports to code examples in v3-features.mdx
jlowin Jan 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,6 @@ When modifying MCP functionality, changes typically need to be applied across al
## Critical Patterns

- Never use bare `except` - be specific with exception types
- File sizes enforced by [loq](https://github.com/jlowin/loq). Edit `loq.toml` to raise limits; `loq baseline` to ratchet down.
- Always `uv sync` first when debugging build issues
- Default test timeout is 5s - optimize or mark as integration tests
29 changes: 27 additions & 2 deletions docs/development/upgrade-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,34 @@ FastMCP v3 introduces a unified provider architecture for sourcing components. A
- **LocalProvider** stores decorator-registered components (`@mcp.tool`, etc.)
- **FastMCPProvider** wraps another FastMCP server for composition
- **ProxyProvider** connects to remote MCP servers
- **TransformingProvider** adds namespacing and renaming
- **Transforms** modify components as they flow through using a middleware `call_next` pattern

See [Providers](/servers/providers/overview) for the complete documentation.
See [Providers](/servers/providers/overview) and [Transforms](/servers/providers/transforms) for documentation.

### Tool Transformation API

`FastMCP.add_tool_transformation()` and the `tool_transformations` constructor parameter are deprecated. Use `add_transform()` with `ToolTransform` instead:

<CodeGroup>
```python Before
mcp = FastMCP("server", tool_transformations={
"verbose_name": ToolTransformConfig(name="short")
})
mcp.add_tool_transformation("verbose_name", ToolTransformConfig(name="short"))
```

```python After
from fastmcp.server.transforms import ToolTransform
from fastmcp.tools.tool_transform import ToolTransformConfig

mcp = FastMCP("server")
mcp.add_transform(ToolTransform({
"verbose_name": ToolTransformConfig(name="short")
}))
```
</CodeGroup>

`remove_tool_transformation()` is deprecated with no replacement - transforms are immutable once added. Use `server.disable(keys=[...])` to hide tools dynamically.

### Mount Namespace Parameter

Expand Down
77 changes: 62 additions & 15 deletions docs/development/v3-notes/v3-features.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Provider:
Providers support:
- **Lifecycle management**: `async def lifespan()` for setup/teardown
- **Visibility control**: `enable()` / `disable()` with keys, tags, and allowlist mode
- **Transformation chaining**: `provider.with_transforms(namespace=..., tool_renames=...)`
- **Transform stacking**: `provider.add_transform(Namespace(...))`, `provider.add_transform(ToolTransform(...))`

### LocalProvider

Expand Down Expand Up @@ -82,6 +82,7 @@ Features:
```python
from fastmcp import FastMCP
from fastmcp.server.providers import FastMCPProvider
from fastmcp.server.transforms import Namespace

main = FastMCP("Main")
sub = FastMCP("Sub")
Expand All @@ -91,34 +92,67 @@ def greet(name: str) -> str:
return f"Hello, {name}!"

# Mount with namespace
main.add_provider(FastMCPProvider(sub).with_namespace("sub"))
provider = FastMCPProvider(sub)
provider.add_transform(Namespace("sub"))
main.add_provider(provider)
# Tool accessible as "sub_greet"
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.

### TransformingProvider
### Transforms

`TransformingProvider` (`src/fastmcp/server/providers/transforming.py`) wraps any provider to apply namespace prefixes and tool renames. Usually accessed via `provider.with_transforms()`.
Transforms modify components (tools, resources, prompts) as they flow from providers to clients. They use a middleware pattern where each transform receives a `call_next` callable to continue the chain.

**Built-in transforms** (`src/fastmcp/server/transforms/`):

- `Namespace` - adds prefixes to names (`tool` → `api_tool`) and path segments to URIs (`data://x` → `data://api/x`)
- `ToolTransform` - modifies tool schemas (rename, description, tags, argument transforms)
- `Visibility` - filters components by key or tag (backs `enable()`/`disable()` API)

```python
provider = SomeProvider().with_transforms(
namespace="api",
tool_renames={"verbose_tool_name": "short"}
)
from fastmcp.server.transforms import Namespace, ToolTransform
from fastmcp.tools.tool_transform import ToolTransformConfig

provider = SomeProvider()
provider.add_transform(Namespace("api"))
provider.add_transform(ToolTransform({
"api_verbose_tool_name": ToolTransformConfig(name="short")
}))

# Stacking composes transformations
provider = (
SomeProvider()
.with_transforms(namespace="api")
.with_transforms(tool_renames={"api_foo": "bar"})
)
# "foo" → "api_foo" → "bar"
# "foo" → "api_foo" (namespace) → "short" (rename)
```

**Custom transforms** subclass `Transform` and override needed methods:

```python
from collections.abc import Sequence
from fastmcp.server.transforms import Transform, ListToolsNext, GetToolNext
from fastmcp.tools import Tool

class TagFilter(Transform):
def __init__(self, required_tags: set[str]):
self.required_tags = required_tags

async def list_tools(self, call_next: ListToolsNext) -> Sequence[Tool]:
tools = await call_next() # Get tools from downstream
return [t for t in tools if t.tags & self.required_tags]

async def get_tool(self, name: str, call_next: GetToolNext) -> Tool | None:
tool = await call_next(name)
return tool if tool and tool.tags & self.required_tags else None
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Transforms apply at two levels:
- **Provider-level**: `provider.add_transform()` - affects only that provider's components
- **Server-level**: `server.add_transform()` - affects all components from all providers

Documentation: `docs/servers/providers/transforms.mdx`, `docs/servers/visibility.mdx`

---

## Visibility System

Components can be dynamically enabled/disabled at runtime using the visibility system (`src/fastmcp/utilities/visibility.py`).
Components can be dynamically enabled/disabled at runtime using the visibility system (`src/fastmcp/server/transforms/visibility.py`).

```python
mcp = FastMCP("Server")
Expand Down Expand Up @@ -385,6 +419,19 @@ mcp.disable(tags={"internal"})

The `tool_serializer` parameter on `FastMCP` is deprecated. Return `ToolResult` for explicit serialization control.

### Tool Transformation Methods

`add_tool_transformation()`, `remove_tool_transformation()`, and `tool_transformations` constructor parameter are deprecated. Use `add_transform(ToolTransform({...}))` instead:

```python
# Deprecated
mcp.add_tool_transformation("name", config)

# New
from fastmcp.server.transforms import ToolTransform
mcp.add_transform(ToolTransform({"name": config}))
```

---

## Breaking Changes
Expand Down
35 changes: 16 additions & 19 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@
"primary": "#2d00f7"
},
"contextual": {
"options": [
"copy",
"view"
]
"options": ["copy", "view"]
},
"description": "The fast, Pythonic way to build MCP servers and clients.",
"errors": {
Expand Down Expand Up @@ -108,10 +105,10 @@
"icon": "layer-group",
"pages": [
"servers/providers/overview",
"servers/providers/transforms",
"servers/providers/local",
"servers/providers/filesystem",
"servers/providers/mounting",
"servers/providers/namespacing",
"servers/providers/proxy",
"servers/providers/custom"
]
Expand All @@ -130,7 +127,8 @@
"servers/progress",
"servers/sampling",
"servers/storage-backends",
"servers/tasks"
"servers/tasks",
"servers/visibility"
]
},
{
Expand Down Expand Up @@ -163,10 +161,7 @@
{
"group": "Essentials",
"icon": "cube",
"pages": [
"clients/client",
"clients/transports"
]
"pages": ["clients/client", "clients/transports"]
},
{
"group": "Core Operations",
Expand All @@ -193,10 +188,7 @@
{
"group": "Authentication",
"icon": "user-shield",
"pages": [
"clients/auth/oauth",
"clients/auth/bearer"
]
"pages": ["clients/auth/oauth", "clients/auth/bearer"]
}
]
},
Expand All @@ -206,10 +198,7 @@
{
"group": "Providers",
"icon": "globe",
"pages": [
"integrations/fastapi",
"integrations/openapi"
]
"pages": ["integrations/fastapi", "integrations/openapi"]
},
{
"group": "Authentication",
Expand Down Expand Up @@ -263,7 +252,7 @@
{
"group": "Patterns",
"pages": [
"patterns/tool-transformation",
"patterns/decorating-methods",
"patterns/cli",
"patterns/contrib",
"patterns/testing"
Expand Down Expand Up @@ -571,6 +560,14 @@
{
"destination": "/servers/providers/mounting",
"source": "/servers/composition"
},
{
"destination": "/servers/providers/transforms",
"source": "/servers/providers/namespacing"
},
{
"destination": "/servers/providers/transforms",
"source": "/patterns/tool-transformation"
}
],
"search": {
Expand Down
Loading
Loading