diff --git a/README.md b/README.md index 8f19aea1a..a63cb4056 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ The Model Context Protocol allows applications to provide context for LLMs in a - Build MCP clients that can connect to any MCP server - Create MCP servers that expose resources, prompts and tools -- Use standard transports like stdio and SSE +- Use standard transports like stdio, SSE, and Streamable HTTP - Handle all MCP protocol messages and lifecycle events ## Installation @@ -387,8 +387,81 @@ python server.py mcp run server.py ``` +### Streamable HTTP Transport + +> **Note**: Streamable HTTP transport is superseding SSE transport for production deployments. + +```python +from mcp.server.fastmcp import FastMCP + +# Stateful server (maintains session state) +mcp = FastMCP("StatefulServer") + +# Stateless server (no session persistence) +mcp = FastMCP("StatelessServer", stateless_http=True) + +# Run server with streamable_http transport +mcp.run(transport="streamable-http") +``` + +You can mount multiple FastMCP servers in a FastAPI application: + +```python +# echo.py +from mcp.server.fastmcp import FastMCP + +mcp = FastMCP(name="EchoServer", stateless_http=True) + + +@mcp.tool(description="A simple echo tool") +def echo(message: str) -> str: + return f"Echo: {message}" +``` + +```python +# math.py +from mcp.server.fastmcp import FastMCP + +mcp = FastMCP(name="MathServer", stateless_http=True) + + +@mcp.tool(description="A simple add tool") +def add_two(n: int) -> str: + return n + 2 +``` + +```python +# main.py +from fastapi import FastAPI +from mcp.echo import echo +from mcp.math import math + + +app = FastAPI() + +# Use the session manager's lifespan +app = FastAPI(lifespan=lambda app: echo.mcp.session_manager.run()) +app.mount("/echo", echo.mcp.streamable_http_app()) +app.mount("/math", math.mcp.streamable_http_app()) +``` + +For low level server with Streamable HTTP implementations, see: +- Stateful server: [`examples/servers/simple-streamablehttp/`](examples/servers/simple-streamablehttp/) +- Stateless server: [`examples/servers/simple-streamablehttp-stateless/`](examples/servers/simple-streamablehttp-stateless/) + + + +The streamable HTTP transport supports: +- Stateful and stateless operation modes +- Resumability with event stores +- JSON or SSE response formats +- Better scalability for multi-node deployments + + ### Mounting to an Existing ASGI Server +> **Note**: SSE transport is being superseded by [Streamable HTTP transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http). + You can mount the SSE server to an existing ASGI server using the `sse_app` method. This allows you to integrate the SSE server with other ASGI applications. ```python @@ -621,7 +694,7 @@ if __name__ == "__main__": ### Writing MCP Clients -The SDK provides a high-level client interface for connecting to MCP servers: +The SDK provides a high-level client interface for connecting to MCP servers using various [transports](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports): ```python from mcp import ClientSession, StdioServerParameters, types @@ -685,6 +758,28 @@ if __name__ == "__main__": asyncio.run(run()) ``` +Clients can also connect using [Streamable HTTP transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http): + +```python +from mcp.client.streamable_http import streamablehttp_client +from mcp import ClientSession + + +async def main(): + # Connect to a streamable HTTP server + async with streamablehttp_client("example/mcp") as ( + read_stream, + write_stream, + _, + ): + # Create a session using the client streams + async with ClientSession(read_stream, write_stream) as session: + # Initialize the connection + await session.initialize() + # Call a tool + tool_result = await session.call_tool("echo", {"message": "hello"}) +``` + ### MCP Primitives The MCP protocol defines three core primitives that servers can implement: