New in version 2.0.0The Proxy Provider sources components from another MCP server through a client connection. This lets you expose any MCP server’s tools, resources, and prompts through your own server, whether the source is local or accessed over the network.
FastMCP proxies are lazy bridges. Creating the proxy object and starting the local server do not contact the upstream server. The upstream connection begins when an MCP client sends an initialize request to the proxy.During initialization, the proxy initializes the upstream server before responding locally. If the upstream server is unavailable, the URL does not point to an MCP endpoint, or upstream authentication cannot complete, the proxy initialization fails. This keeps the local proxy’s connection status aligned with the upstream server it represents.After initialization, the proxy forwards MCP requests such as ping, tools/list, resources/list, prompts/list, tool calls, resource reads, sampling, elicitation, logging, and progress through the upstream client.
A common use case is bridging transports between servers:
from fastmcp.server import create_proxy# Bridge HTTP server to local stdiohttp_proxy = create_proxy("http://example.com/mcp/sse", name="HTTP-to-stdio")# Run locally via stdio for Claude Desktopif __name__ == "__main__": http_proxy.run() # Defaults to stdio
Or expose a local server via HTTP:
from fastmcp.server import create_proxy# Bridge local server to HTTPlocal_proxy = create_proxy("local_server.py", name="stdio-to-HTTP")if __name__ == "__main__": local_proxy.run(transport="http", host="0.0.0.0", port=8080)
New in version 2.10.3create_proxy() provides session isolation - each request gets its own isolated backend session:
from fastmcp.server import create_proxy# Each request creates a fresh backend session (recommended)proxy = create_proxy("backend_server.py")# Multiple clients can use this proxy simultaneously:# - Client A calls a tool → gets isolated session# - Client B calls a tool → gets different session# - No context mixing
If you pass an already-connected client, the proxy reuses that session:
from fastmcp import Clientfrom fastmcp.server import create_proxyasync with Client("backend_server.py") as connected_client: # This proxy reuses the connected session proxy = create_proxy(connected_client) # ⚠️ Warning: All requests share the same session
Shared sessions may cause context mixing in concurrent scenarios. Use only in single-threaded situations or with explicit synchronization.
New in version 2.10.3Proxies automatically forward MCP protocol features:
Feature
Description
Roots
Filesystem root access requests
Sampling
LLM completion requests
Elicitation
User input requests
Logging
Log messages from backend
Progress
Progress notifications
from fastmcp.server import create_proxy# All features forwarded automaticallyproxy = create_proxy("advanced_backend.py")# When the backend:# - Requests LLM sampling → forwarded to your client# - Logs messages → appear in your client# - Reports progress → shown in your client
New in version 2.10.5Components from a proxy server are “mirrored” - they reflect the remote server’s state and cannot be modified directly.To modify a proxied component (like disabling it), create a local copy:
from fastmcp import FastMCPfrom fastmcp.server import create_proxyproxy = create_proxy("backend_server.py")# Get mirrored toolmirrored_tool = await proxy.get_tool("useful_tool")# Create modifiable local copylocal_tool = mirrored_tool.copy()# Add to your own servermy_server = FastMCP("MyServer")my_server.add_tool(local_tool)# Now you can control enabled statemy_server.disable(keys={local_tool.key})
New in version 3.2.0ProxyProvider caches the backend’s component lists (tools, resources, templates, prompts) so that individual lookups — like resolving a tool by name during call_tool — don’t require a separate backend connection. The cache stores raw component metadata and is shared across all proxy sessions; per-session visibility, auth, and transforms are still applied after cache lookup by the server layer. The cache refreshes whenever an explicit list_* call is made, and entries expire after a configurable TTL (default 300 seconds).For backends whose component lists change dynamically, disable caching by setting cache_ttl=0.
By default, each tool call opens a fresh MCP session to the backend. This is the safe default because it prevents state from leaking between requests. However, for stateless HTTP backends where there’s no session state to protect, this overhead is unnecessary.You can reuse a single backend session by providing a client factory that returns the same client instance:
This eliminates the MCP initialization handshake on every call, which can dramatically reduce latency under load. The Client uses reference counting for its session lifecycle, so concurrent callers sharing the same instance is safe.
Only reuse sessions when you know the backend is stateless (e.g. stateless HTTP). For stateful backends (stdio processes, servers that track session state), use the default fresh-session behavior to avoid context mixing.
Mount a proxy to add components from another server:
from fastmcp import FastMCPfrom fastmcp.server import create_proxyserver = FastMCP("My Server")# Add local tools@server.tooldef local_tool() -> str: return "Local result"# Mount proxied tools from another serverexternal = create_proxy("http://external-server/mcp")server.mount(external)# Now server has both local and proxied tools