Replace FastMCP.as_proxy() with create_proxy() function (#2829)

This commit is contained in:
Jeremiah Lowin 2026-01-10 11:39:06 -05:00 committed by GitHub
commit 3163e61ee4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 341 additions and 124 deletions

View file

@ -46,13 +46,13 @@ server2 = FastMCP("Server2", providers=[provider])
### ProxyProvider
`ProxyProvider` (`src/fastmcp/server/providers/proxy.py`) proxies components from remote MCP servers via a client factory. Used by `FastMCP.as_proxy()` and `FastMCP.mount()` for remote server integration.
`ProxyProvider` (`src/fastmcp/server/providers/proxy.py`) proxies components from remote MCP servers via a client factory. Used by `create_proxy()` and `FastMCP.mount()` for remote server integration.
```python
from fastmcp import FastMCP
from fastmcp.server import create_proxy
# Create proxy to remote server
server = FastMCP.as_proxy("http://remote-server/mcp")
server = create_proxy("http://remote-server/mcp")
```
### OpenAPIProvider

View file

@ -263,11 +263,11 @@ Users on Claude Pro, Max, Team, and Enterprise plans have first-class remote ser
Create a proxy server that connects to a remote HTTP server:
```python proxy_server.py
from fastmcp import FastMCP
from fastmcp.server import create_proxy
# Create a proxy to a remote server
proxy = FastMCP.as_proxy(
"https://example.com/mcp/sse",
proxy = create_proxy(
"https://example.com/mcp/sse",
name="Remote Server Proxy"
)
@ -280,8 +280,9 @@ if __name__ == "__main__":
For authenticated remote servers, create an authenticated client following the guidance in the [client auth documentation](/clients/auth/bearer) and pass it to the proxy:
```python auth_proxy_server.py {7}
from fastmcp import FastMCP, Client
from fastmcp import Client
from fastmcp.client.auth import BearerAuth
from fastmcp.server import create_proxy
# Create authenticated client
client = Client(
@ -290,7 +291,7 @@ client = Client(
)
# Create proxy using the authenticated client
proxy = FastMCP.as_proxy(client, name="Authenticated Proxy")
proxy = create_proxy(client, name="Authenticated Proxy")
if __name__ == "__main__":
proxy.run()

View file

@ -47,6 +47,77 @@ main.mount(weather_server)
# Now main has access to get_forecast and data://cities
```
## Mounting External Servers
Mount remote HTTP servers or subprocess-based MCP servers using `create_proxy()`:
```python
from fastmcp import FastMCP
from fastmcp.server import create_proxy
mcp = FastMCP("Orchestrator")
# Mount a remote HTTP server (URLs work directly)
mcp.mount(create_proxy("http://api.example.com/mcp"), namespace="api")
# Mount local Python scripts (file paths work directly)
mcp.mount(create_proxy("./my_server.py"), namespace="local")
```
### Mounting npm/uvx Packages
For npm packages or Python tools, use the config dict format:
```python
from fastmcp import FastMCP
from fastmcp.server import create_proxy
mcp = FastMCP("Orchestrator")
# Mount npm package via config
github_config = {
"mcpServers": {
"default": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"]
}
}
}
mcp.mount(create_proxy(github_config), namespace="github")
# Mount Python tool via config
sqlite_config = {
"mcpServers": {
"default": {
"command": "uvx",
"args": ["mcp-server-sqlite", "--db", "data.db"]
}
}
}
mcp.mount(create_proxy(sqlite_config), namespace="db")
```
Or use explicit transport classes:
```python
from fastmcp import FastMCP
from fastmcp.server import create_proxy
from fastmcp.client.transports import NpxStdioTransport, UvxStdioTransport
mcp = FastMCP("Orchestrator")
mcp.mount(
create_proxy(NpxStdioTransport(package="@modelcontextprotocol/server-github")),
namespace="github"
)
mcp.mount(
create_proxy(UvxStdioTransport(tool_name="mcp-server-sqlite", tool_args=["--db", "data.db"])),
namespace="db"
)
```
For advanced configuration, see [Proxying](/servers/providers/proxy).
## Namespacing
<VersionBadge version="3.0.0" />
@ -145,18 +216,16 @@ main.mount(subserver, namespace="api")
### Proxy Mounting
The parent server treats the mounted server as a separate entity:
<Warning>
The `as_proxy` parameter is deprecated. Mounted servers now always have their lifespan and middleware invoked. To create a proxy server explicitly, use `create_proxy()` from `fastmcp.server`.
</Warning>
```python
main.mount(subserver, namespace="api", as_proxy=True)
```
Previously, the parent server could treat the mounted server as a separate entity with its own lifecycle. This behavior is now the default for all mounted servers:
- Full client lifecycle events on mounted server
- Mounted server's lifespan is executed
- Communication via in-memory Client transport
FastMCP automatically uses proxy mounting when the mounted server has a custom lifespan. Override with `as_proxy=True` or `as_proxy=False`.
## Tag Filtering
<VersionBadge version="3.0.0" />

View file

@ -37,7 +37,7 @@ FastMCP includes providers for common patterns:
|----------|--------------|----------------|
| `LocalProvider` | Stores components you define in code | `@mcp.tool`, `mcp.add_tool()` |
| `FastMCPProvider` | Wraps another FastMCP server | `mcp.mount(server)` |
| `ProxyProvider` | Connects to remote MCP servers | `FastMCP.as_proxy(client)` |
| `ProxyProvider` | Connects to remote MCP servers | `create_proxy(client)` |
| `TransformingProvider` | Adds prefixes to avoid name collisions | `mcp.mount(server, namespace="api")` |
Most users only interact with `LocalProvider` (through decorators) and occasionally mount or proxy other servers. The provider abstraction stays invisible until you need it.

View file

@ -36,17 +36,13 @@ sequenceDiagram
<VersionBadge version="2.10.3" />
Create a proxy using `FastMCP.as_proxy()`:
Create a proxy using `create_proxy()`:
```python
from fastmcp import FastMCP
from fastmcp.server.proxy import ProxyClient
from fastmcp.server import create_proxy
# Create a proxy to a remote server
proxy = FastMCP.as_proxy(
ProxyClient("http://example.com/mcp"),
name="MyProxy"
)
# create_proxy() accepts URLs, file paths, and transports directly
proxy = create_proxy("http://example.com/mcp", name="MyProxy")
if __name__ == "__main__":
proxy.run()
@ -57,19 +53,19 @@ This gives you:
- Automatic forwarding of MCP features (sampling, elicitation, etc.)
- Session isolation to prevent context mixing
<Tip>
To mount a proxy inside another FastMCP server, see [Mounting External Servers](/servers/providers/mounting#mounting-external-servers).
</Tip>
## Transport Bridging
A common use case is bridging transports - making a remote server available locally:
```python
from fastmcp import FastMCP
from fastmcp.server.proxy import ProxyClient
from fastmcp.server import create_proxy
# Bridge remote HTTP to local stdio
remote_proxy = FastMCP.as_proxy(
ProxyClient("http://example.com/mcp/sse"),
name="Remote-to-Local"
)
remote_proxy = create_proxy("http://example.com/mcp/sse", name="Remote-to-Local")
# Run locally via stdio for Claude Desktop
if __name__ == "__main__":
@ -79,11 +75,10 @@ if __name__ == "__main__":
Or expose a local server via HTTP:
```python
from fastmcp.server import create_proxy
# Bridge local server to HTTP
local_proxy = FastMCP.as_proxy(
ProxyClient("local_server.py"),
name="Local-to-HTTP"
)
local_proxy = create_proxy("local_server.py", name="Local-to-HTTP")
if __name__ == "__main__":
local_proxy.run(transport="http", host="0.0.0.0", port=8080)
@ -93,13 +88,13 @@ if __name__ == "__main__":
<VersionBadge version="2.10.3" />
ProxyClient provides session isolation - each request gets its own isolated backend session:
`create_proxy()` provides session isolation - each request gets its own isolated backend session:
```python
from fastmcp.server.proxy import ProxyClient
from fastmcp.server import create_proxy
# Each request creates a fresh backend session (recommended)
proxy = FastMCP.as_proxy(ProxyClient("backend_server.py"))
proxy = create_proxy("backend_server.py")
# Multiple clients can use this proxy simultaneously:
# - Client A calls a tool → gets isolated session
@ -113,10 +108,11 @@ If you pass an already-connected client, the proxy reuses that session:
```python
from fastmcp import Client
from fastmcp.server import create_proxy
async with Client("backend_server.py") as connected_client:
# This proxy reuses the connected session
proxy = FastMCP.as_proxy(connected_client)
proxy = create_proxy(connected_client)
# ⚠️ Warning: All requests share the same session
```
@ -129,7 +125,7 @@ Shared sessions may cause context mixing in concurrent scenarios. Use only in si
<VersionBadge version="2.10.3" />
ProxyClient automatically forwards MCP protocol features:
Proxies automatically forward MCP protocol features:
| Feature | Description |
|---------|-------------|
@ -140,11 +136,10 @@ ProxyClient automatically forwards MCP protocol features:
| Progress | Progress notifications |
```python
from fastmcp.server.proxy import ProxyClient
from fastmcp.server import create_proxy
# All features forwarded automatically
backend = ProxyClient("advanced_backend.py")
proxy = FastMCP.as_proxy(backend)
proxy = create_proxy("advanced_backend.py")
# When the backend:
# - Requests LLM sampling → forwarded to your client
@ -157,6 +152,8 @@ proxy = FastMCP.as_proxy(backend)
Selectively disable forwarding:
```python
from fastmcp.server.providers.proxy import ProxyClient
backend = ProxyClient(
"backend_server.py",
sampling_handler=None, # Disable LLM sampling
@ -171,7 +168,7 @@ backend = ProxyClient(
Create proxies from configuration dictionaries:
```python
from fastmcp import FastMCP
from fastmcp.server import create_proxy
config = {
"mcpServers": {
@ -182,7 +179,7 @@ config = {
}
}
proxy = FastMCP.as_proxy(config, name="Config-Based Proxy")
proxy = create_proxy(config, name="Config-Based Proxy")
```
### Multi-Server Proxies
@ -190,6 +187,8 @@ proxy = FastMCP.as_proxy(config, name="Config-Based Proxy")
Combine multiple servers with automatic namespacing:
```python
from fastmcp.server import create_proxy
config = {
"mcpServers": {
"weather": {
@ -206,7 +205,7 @@ config = {
# Creates unified proxy with prefixed components:
# - weather_get_forecast
# - calendar_add_event
composite = FastMCP.as_proxy(config, name="Composite")
composite = create_proxy(config, name="Composite")
```
## Component Prefixing
@ -229,7 +228,10 @@ Components from a proxy server are "mirrored" - they reflect the remote server's
To modify a proxied component (like disabling it), create a local copy:
```python
proxy = FastMCP.as_proxy("backend_server.py")
from fastmcp import FastMCP
from fastmcp.server import create_proxy
proxy = create_proxy("backend_server.py")
# Get mirrored tool
mirrored_tool = await proxy.get_tool("useful_tool")
@ -258,12 +260,14 @@ When mounting proxy servers, this latency affects all operations on the parent s
For low-latency requirements, consider using [`import_server()`](/servers/providers/mounting#static-importing) to copy tools at startup.
## Advanced: FastMCPProxy Class
## Advanced Usage
### FastMCPProxy Class
For explicit session control, use `FastMCPProxy` directly:
```python
from fastmcp.server.proxy import FastMCPProxy, ProxyClient
from fastmcp.server.providers.proxy import FastMCPProxy, ProxyClient
# Custom session factory
def create_client():
@ -273,3 +277,25 @@ proxy = FastMCPProxy(client_factory=create_client)
```
This gives you full control over session creation and reuse strategies.
### Adding Proxied Components to Existing Server
Mount a proxy to add remote components to an existing server:
```python
from fastmcp import FastMCP
from fastmcp.server import create_proxy
server = FastMCP("My Server")
# Add local tools
@server.tool
def local_tool() -> str:
return "Local result"
# Mount proxied tools from remote server
remote = create_proxy("http://remote-server/mcp")
server.mount(remote)
# Now server has both local and proxied tools
```

View file

@ -288,17 +288,18 @@ main.mount(sub, namespace="sub")
<VersionBadge version="2.0.0" />
FastMCP can act as a proxy for any MCP server (local or remote) using `FastMCP.as_proxy`, letting you bridge transports or add a frontend to existing servers. For example, you can expose a remote SSE server locally via stdio, or vice versa.
FastMCP can act as a proxy for any MCP server (local or remote) using `create_proxy`, letting you bridge transports or add a frontend to existing servers. For example, you can expose a remote SSE server locally via stdio, or vice versa.
Proxies automatically handle concurrent operations safely by creating fresh sessions for each request when using disconnected clients.
See the [Remote Proxies](/servers/providers/proxy) guide for details and advanced usage.
```python
from fastmcp import FastMCP, Client
from fastmcp import Client
from fastmcp.server import create_proxy
backend = Client("http://example.com/mcp/sse")
proxy = FastMCP.as_proxy(backend, name="ProxyServer")
proxy = create_proxy(backend, name="ProxyServer")
# Now use the proxy like any FastMCP server
```