Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions docs/development/upgrade-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ tool.enable()
```

```python After
server.disable(keys=["tool:my_tool"])
server.enable(keys=["tool:my_tool"])
server.disable(keys=["tool:my_tool@"])
server.enable(keys=["tool:my_tool@"])
```
</CodeGroup>

Expand Down
89 changes: 85 additions & 4 deletions docs/development/v3-notes/v3-features.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ Transforms modify components (tools, resources, prompts) as they flow from provi
- `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)
- `VersionFilter` - filters components by version range (`version_gte`, `version_lt`)

```python
from fastmcp.server.transforms import Namespace, ToolTransform
Expand Down Expand Up @@ -188,14 +189,14 @@ Components can be dynamically enabled/disabled at runtime using the visibility s
```python
mcp = FastMCP("Server")

# Disable specific components
mcp.disable(keys=["tool:dangerous_tool"])
# Disable specific components (keys include @ version suffix)
mcp.disable(keys=["tool:dangerous_tool@"])

# Disable by tag
mcp.disable(tags={"admin"})

# Allowlist mode - only show these
mcp.enable(keys=["tool:safe_tool"], only=True)
mcp.enable(keys=["tool:safe_tool@"], only=True)
```

Works at both server and provider level. Supports:
Expand All @@ -205,6 +206,86 @@ Works at both server and provider level. Supports:

---

## Component Versioning

v3.0 introduces versioning support for tools, resources, and prompts. Components can declare a version, and when multiple versions of the same component exist, the highest version is automatically exposed to clients.

**Declaring versions:**

```python
@mcp.tool(version="1.0")
def add(x: int, y: int) -> int:
return x + y

@mcp.tool(version="2.0")
def add(x: int, y: int, z: int = 0) -> int:
return x + y + z

# Only v2.0 is exposed to clients via list_tools()
# Calling "add" invokes the v2.0 implementation
```

**Version comparison:**
- Uses PEP 440 semantic versioning (1.10 > 1.9 > 1.2)
- Falls back to string comparison for non-PEP 440 versions (dates like `2025-01-15` work)
- Unversioned components sort lower than any versioned component
- The `v` prefix is normalized (`v1.0` equals `1.0`)

**Retrieving specific versions:**

```python
# Get the highest version (default)
tool = await server.get_tool("add")

# Get a specific version
tool_v1 = await server.get_tool("add", version="1.0")

# Get all versions
all_versions = await server.get_tool_versions("add")
```

**VersionFilter transform:**

The `VersionFilter` transform enables serving different API versions from a single codebase:

```python
from fastmcp import FastMCP
from fastmcp.server.providers import LocalProvider
from fastmcp.server.transforms import VersionFilter

# Define components on a shared provider
components = LocalProvider()

@components.tool(version="1.0")
def calculate(x: int, y: int) -> int:
return x + y

@components.tool(version="2.0")
def calculate(x: int, y: int, z: int = 0) -> int:
return x + y + z

# Create servers that share the provider with different filters
api_v1 = FastMCP("API v1", providers=[components])
api_v1.add_transform(VersionFilter(version_lt="2.0"))

api_v2 = FastMCP("API v2", providers=[components])
api_v2.add_transform(VersionFilter(version_gte="2.0"))
```

Parameters mirror comparison operators:
- `version_gte`: Versions >= this value pass through
- `version_lt`: Versions < this value pass through

**Key format:**

Component keys now include a version suffix using `@` as a delimiter:
- Versioned: `tool:add@1.0`, `resource:data://config@2.0`
- Unversioned: `tool:add@`, `resource:data://config@`

The `@` is always present (even for unversioned components) to enable unambiguous parsing of URIs that may contain `@`.

---
Comment thread
jlowin marked this conversation as resolved.

## Type-Safe Canonical Results

v3.0 introduces type-safe result classes that provide explicit control over component responses while supporting MCP runtime metadata: `ToolResult` ([#2736](https://github.com/jlowin/fastmcp/pull/2736)), `ResourceResult` ([#2734](https://github.com/jlowin/fastmcp/pull/2734)), and `PromptResult` ([#2738](https://github.com/jlowin/fastmcp/pull/2738)).
Expand Down Expand Up @@ -695,7 +776,7 @@ tool = await server.get_tool("my_tool")
tool.disable()

# v3.0
server.disable(keys=["tool:my_tool"])
server.disable(keys=["tool:my_tool@"])
```

### Component Lookup Methods
Expand Down
1 change: 1 addition & 0 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
"servers/storage-backends",
"servers/tasks",
"servers/telemetry",
"servers/versioning",
"servers/visibility"
]
},
Expand Down
14 changes: 13 additions & 1 deletion docs/servers/prompts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ def data_analysis_prompt(

Optional meta information about the prompt. This data is passed through to the MCP client as the `meta` field of the client-side prompt object and can be used for custom metadata, versioning, or other application-specific purposes.
</ParamField>

<ParamField body="version" type="str | int | None">
<VersionBadge version="3.0.0" />

Optional version identifier for this prompt. See [Versioning](/servers/versioning) for details.
</ParamField>
</Card>

#### Using with Methods
Expand Down Expand Up @@ -444,4 +450,10 @@ The duplicate behavior options are:
- `"warn"` (default): Logs a warning, and the new prompt replaces the old one.
- `"error"`: Raises a `ValueError`, preventing the duplicate registration.
- `"replace"`: Silently replaces the existing prompt with the new one.
- `"ignore"`: Keeps the original prompt and ignores the new registration attempt.
- `"ignore"`: Keeps the original prompt and ignores the new registration attempt.

## Versioning

<VersionBadge version="3.0.0" />

Prompts support versioning, allowing you to maintain multiple implementations under the same name while clients automatically receive the highest version. See [Versioning](/servers/versioning) for complete documentation on version comparison, retrieval, and migration patterns.
16 changes: 14 additions & 2 deletions docs/servers/resources.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,15 @@ def get_application_status() -> str:

<ParamField body="meta" type="dict[str, Any] | None">
<VersionBadge version="2.11.0" />

Optional meta information about the resource. This data is passed through to the MCP client as the `meta` field of the client-side resource object and can be used for custom metadata, versioning, or other application-specific purposes.
</ParamField>

<ParamField body="version" type="str | int | None">
<VersionBadge version="3.0.0" />

Optional version identifier for this resource. See [Versioning](/servers/versioning) for details.
</ParamField>
</Card>

#### Using with Methods
Expand Down Expand Up @@ -730,4 +736,10 @@ The duplicate behavior options are:
- `"warn"` (default): Logs a warning, and the new resource/template replaces the old one.
- `"error"`: Raises a `ValueError`, preventing the duplicate registration.
- `"replace"`: Silently replaces the existing resource/template with the new one.
- `"ignore"`: Keeps the original resource/template and ignores the new registration attempt.
- `"ignore"`: Keeps the original resource/template and ignores the new registration attempt.

## Versioning

<VersionBadge version="3.0.0" />

Resources and resource templates support versioning, allowing you to maintain multiple implementations under the same URI while clients automatically receive the highest version. See [Versioning](/servers/versioning) for complete documentation on version comparison, retrieval, and migration patterns.
Comment thread
jlowin marked this conversation as resolved.
12 changes: 12 additions & 0 deletions docs/servers/tools.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ def search_products_implementation(query: str, category: str | None = None) -> l

Execution timeout in seconds. If the tool takes longer than this to complete, an MCP error is returned to the client. See [Timeouts](#timeouts) for details.
</ParamField>

<ParamField body="version" type="str | int | None">
<VersionBadge version="3.0.0" />

Optional version identifier for this tool. See [Versioning](/servers/versioning) for details.
</ParamField>
</Card>

### Using with Methods
Expand Down Expand Up @@ -1062,3 +1068,9 @@ def calculate_sum(a: int, b: int) -> int:

mcp.remove_tool("calculate_sum")
```

## Versioning

<VersionBadge version="3.0.0" />

Tools support versioning, allowing you to maintain multiple implementations under the same name while clients automatically receive the highest version. See [Versioning](/servers/versioning) for complete documentation on version comparison, retrieval, and migration patterns.
Comment thread
jlowin marked this conversation as resolved.
Loading