From a6fe65bbc177d8a0f0918feebce4eacdbdc1c4aa Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Thu, 8 May 2025 17:52:36 -0400 Subject: [PATCH] Update transport docs --- README.md | 62 ++++++++--------- docs/clients/transports.mdx | 129 ++++++++++++++++++------------------ 2 files changed, 90 insertions(+), 101 deletions(-) diff --git a/README.md b/README.md index 6b74ad960..d391bbcbb 100644 --- a/README.md +++ b/README.md @@ -273,50 +273,40 @@ Learn more: [**OpenAPI Integration**](https://gofastmcp.com/patterns/openapi) | ## Running Your Server -You can run your FastMCP server in several ways: +The main way to run a FastMCP server is by calling the `run()` method on your server instance: -1. **Development (`fastmcp dev`)**: Recommended for building and testing. Provides an interactive testing environment with the MCP Inspector. - ```bash - fastmcp dev server.py - # Optionally add temporary dependencies - fastmcp dev server.py --with pandas numpy - ``` +```python +# server.py +from fastmcp import FastMCP -2. **FastMCP CLI**: Run your server with the FastMCP CLI. This can autodetect and load your server object and run it with any transport configuration you want. - ```bash - fastmcp run path/to/server.py:server_object +mcp = FastMCP("Demo 🚀") - # Run as SSE on port 4200 - fastmcp run path/to/server.py:server_object --transport sse --port 4200 - ``` - FastMCP will auto-detect the server object if it's named `mcp`, `app`, or `server`. In these cases, you can omit the `:server_object` part unless you need to select a specific object. +@mcp.tool() +def hello(name: str) -> str: + return f"Hello, {name}!" -3. **Direct Execution**: For maximum compatibility with the MCP ecosystem, you can run your server directly as part of a Python script. You will typically do this within an `if __name__ == "__main__":` block in your script: - ```python - # Add this to server.py - if __name__ == "__main__": - # Default: runs stdio transport - mcp.run() +if __name__ == "__main__": + mcp.run() # Default: uses STDIO transport +``` - # Example: Run with SSE transport on a specific port - mcp.run(transport="sse", host="127.0.0.1", port=9000) - ``` - Run your script: - ```bash - python server.py - # or using uv to manage the environment - uv run python server.py - ``` -4. **Claude Desktop Integration (`fastmcp install`)**: The easiest way to make your server persistently available in the Claude Desktop app. It handles creating an isolated environment using `uv`. - ```bash - fastmcp install server.py --name "My Analysis Tool" - # Optionally add dependencies and environment variables - fastmcp install server.py --with requests -v API_KEY=123 -f .env - ``` +FastMCP supports three transport protocols: +**STDIO (Default)**: Best for local tools and command-line scripts. +```python +mcp.run(transport="stdio") # Default, so transport argument is optional +``` -See the [**Server Documentation**](https://gofastmcp.com/servers/fastmcp#running-the-server) for more details on transports and configuration. +**Streamable HTTP**: Recommended for web deployments. +```python +mcp.run(transport="streamable-http", host="127.0.0.1", port=8000, path="/mcp") +``` +**SSE**: For compatibility with existing SSE clients. +```python +mcp.run(transport="sse", host="127.0.0.1", port=8000) +``` + +See the [**Running Server Documentation**](https://gofastmcp.com/deployment/running-server) for more details. ## Contributing diff --git a/docs/clients/transports.mdx b/docs/clients/transports.mdx index 67a70b5b2..5b0a6935d 100644 --- a/docs/clients/transports.mdx +++ b/docs/clients/transports.mdx @@ -14,6 +14,69 @@ The FastMCP `Client` relies on a `ClientTransport` object to handle the specific While the `Client` often infers the correct transport automatically (see [Client Overview](/clients/client#transport-inference)), you can also instantiate transports explicitly for more control. +## Network Transports + +These transports connect to servers running over a network, typically long-running services accessible via URLs. + +### Streamable HTTP + + + +* **Class:** `fastmcp.client.transports.StreamableHttpTransport` +* **Inferred From:** `http://` or `https://` URLs (default for HTTP URLs as of v2.3.0) +* **Use Case:** Connecting to persistent MCP servers exposed over HTTP/S using FastMCP's `mcp.run(transport="streamable-http")` mode. + +Streamable HTTP is the recommended transport for web-based deployments, providing efficient bidirectional communication over HTTP. + +```python +from fastmcp import Client +from fastmcp.client.transports import StreamableHttpTransport + +http_url = "http://localhost:8000/mcp" + +# Option 1: Inferred transport (default for HTTP URLs) +client_inferred = Client(http_url) + +# Option 2: Explicit transport (e.g., to add custom headers) +headers = {"Authorization": "Bearer mytoken"} +transport_explicit = StreamableHttpTransport(url=http_url, headers=headers) +client_explicit = Client(transport_explicit) + +async def use_streamable_http_client(client): + async with client: + tools = await client.list_tools() + print(f"Connected via Streamable HTTP, found tools: {tools}") + +# asyncio.run(use_streamable_http_client(client_inferred)) +# asyncio.run(use_streamable_http_client(client_explicit)) +``` + +### SSE (Server-Sent Events) + +* **Class:** `fastmcp.client.transports.SSETransport` +* **Inferred From:** Not automatically inferred for most HTTP URLs (as of v2.3.0) +* **Use Case:** Connecting to MCP servers using Server-Sent Events, often using FastMCP's `mcp.run(transport="sse")` mode. + +While SSE is still supported, Streamable HTTP is the recommended transport for new web-based deployments. + +```python +from fastmcp import Client +from fastmcp.client.transports import SSETransport + +sse_url = "http://localhost:8000/sse" + +# Since v2.3.0, HTTP URLs default to StreamableHttpTransport, +# so you must explicitly use SSETransport for SSE connections +transport_explicit = SSETransport(url=sse_url) +client_explicit = Client(transport_explicit) + +async def use_sse_client(client): + async with client: + tools = await client.list_tools() + print(f"Connected via SSE, found tools: {tools}") + +# asyncio.run(use_sse_client(client_explicit)) +``` ## Stdio Transports These transports manage an MCP server running as a subprocess, communicating with it via standard input (stdin) and standard output (stdout). This is the standard mechanism used by clients like Claude Desktop. @@ -133,70 +196,6 @@ client = Client(transport) # async with client: # response = await client.call_tool("get_npm_data", {}) ``` -## Network Transports - -These transports connect to servers running over a network, typically long-running services accessible via URLs. - -### SSE (Server-Sent Events) - -* **Class:** `fastmcp.client.transports.SSETransport` -* **Inferred From:** `http://` or `https://` URLs -* **Use Case:** Connecting to persistent MCP servers exposed over HTTP/S, often using FastMCP's `mcp.run(transport="sse")` mode. - -SSE is a simple, unidirectional protocol where the server pushes messages to the client over a standard HTTP connection. - -```python -from fastmcp import Client -from fastmcp.client.transports import SSETransport - -sse_url = "http://localhost:8000/sse" - -# Option 1: Inferred transport -client_inferred = Client(sse_url) - -# Option 2: Explicit transport (e.g., to add custom headers) -headers = {"Authorization": "Bearer mytoken"} -transport_explicit = SSETransport(url=sse_url, headers=headers) -client_explicit = Client(transport_explicit) - -async def use_sse_client(client): - async with client: - tools = await client.list_tools() - print(f"Connected via SSE, found tools: {tools}") - -# asyncio.run(use_sse_client(client_inferred)) -# asyncio.run(use_sse_client(client_explicit)) -``` - -### WebSocket - -* **Class:** `fastmcp.client.transports.WSTransport` -* **Inferred From:** `ws://` or `wss://` URLs -* **Use Case:** Connecting to MCP servers using the WebSocket protocol for bidirectional communication. - -WebSockets provide a persistent, full-duplex connection between client and server. - -```python -from fastmcp import Client -from fastmcp.client.transports import WSTransport - -ws_url = "ws://localhost:9000" - -# Option 1: Inferred transport -client_inferred = Client(ws_url) - -# Option 2: Explicit transport -transport_explicit = WSTransport(url=ws_url) -client_explicit = Client(transport_explicit) - -async def use_ws_client(client): - async with client: - tools = await client.list_tools() - print(f"Connected via WebSocket, found tools: {tools}") - -# asyncio.run(use_ws_client(client_inferred)) -# asyncio.run(use_ws_client(client_explicit)) -``` ## In-Memory Transports @@ -240,6 +239,6 @@ Communication happens through efficient in-memory queues, making it very fast. ## Choosing a Transport * **Local Development/Testing:** Use `PythonStdioTransport` (inferred from `.py` files) or `FastMCPTransport` (for same-process testing). -* **Connecting to Remote/Persistent Servers:** Use `SSETransport` (for `http/s`) or `WSTransport` (for `ws/s`). +* **Connecting to Remote/Persistent Servers:** Use `StreamableHttpTransport` (recommended, default for HTTP URLs) or `SSETransport` (legacy option). * **Running Packaged Tools:** Use `UvxStdioTransport` (Python/uv) or `NpxStdioTransport` (Node/npm) if you need to run MCP servers without local installation. * **Integrating with Claude Desktop (or similar):** These tools typically expect to run a Python script, so your server should be runnable via `python your_server.py`, making `PythonStdioTransport` the relevant mechanism on the client side. \ No newline at end of file