README - replace code snippets with examples - streamable http (#1155)

This commit is contained in:
Inna Harper 2025-07-16 21:45:40 +01:00 • committed by GitHub
commit e975d0550b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

143
README.md
View file

@ -532,9 +532,7 @@ Client usage:
<!-- snippet-source examples/snippets/clients/completion_client.py -->
```python
"""MCP client example showing completion usage.
This example demonstrates how to use the completion feature in MCP clients.
"""
cd to the `examples/snippets` directory and run:
uv run completion-client
"""
@ -863,72 +861,99 @@ Note that `uv run mcp run` or `uv run mcp dev` only supports server using FastMC
> **Note**: Streamable HTTP transport is superseding SSE transport for production deployments.
<!-- snippet-source examples/snippets/servers/streamable_config.py -->
```python
"""
Run from the repository root:
uv run examples/snippets/servers/streamable_config.py
"""
from mcp.server.fastmcp import FastMCP
# Stateful server (maintains session state)
mcp = FastMCP("StatefulServer")
# Other configuration options:
# Stateless server (no session persistence)
mcp = FastMCP("StatelessServer", stateless_http=True)
# mcp = FastMCP("StatelessServer", stateless_http=True)
# Stateless server (no session persistence, no sse stream with supported client)
mcp = FastMCP("StatelessServer", stateless_http=True, json_response=True)
# mcp = FastMCP("StatelessServer", stateless_http=True, json_response=True)
# Add a simple tool to demonstrate the server
@mcp.tool()
def greet(name: str = "World") -> str:
"""Greet someone by name."""
return f"Hello, {name}!"
# Run server with streamable_http transport
mcp.run(transport="streamable-http")
if __name__ == "__main__":
mcp.run(transport="streamable-http")
```
You can mount multiple FastMCP servers in a FastAPI application:
_Full example: [examples/snippets/servers/streamable_config.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/streamable_config.py)_
<!-- /snippet-source -->
You can mount multiple FastMCP servers in a Starlette application:
<!-- snippet-source examples/snippets/servers/streamable_starlette_mount.py -->
```python
# echo.py
"""
Run from the repository root:
uvicorn examples.snippets.servers.streamable_starlette_mount:app --reload
"""
import contextlib
from starlette.applications import Starlette
from starlette.routing import Mount
from mcp.server.fastmcp import FastMCP
mcp = FastMCP(name="EchoServer", stateless_http=True)
# Create the Echo server
echo_mcp = FastMCP(name="EchoServer", stateless_http=True)
@mcp.tool()
@echo_mcp.tool()
def echo(message: str) -> str:
"""A simple echo tool"""
return f"Echo: {message}"
```
```python
# math.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP(name="MathServer", stateless_http=True)
@mcp.tool()
# Create the Math server
math_mcp = FastMCP(name="MathServer", stateless_http=True)
@math_mcp.tool()
def add_two(n: int) -> int:
"""Tool to add two to the input"""
return n + 2
```
```python
# main.py
import contextlib
from fastapi import FastAPI
from mcp.echo import echo
from mcp.math import math
# Create a combined lifespan to manage both session managers
@contextlib.asynccontextmanager
async def lifespan(app: FastAPI):
async def lifespan(app: Starlette):
async with contextlib.AsyncExitStack() as stack:
await stack.enter_async_context(echo.mcp.session_manager.run())
await stack.enter_async_context(math.mcp.session_manager.run())
await stack.enter_async_context(echo_mcp.session_manager.run())
await stack.enter_async_context(math_mcp.session_manager.run())
yield
app = FastAPI(lifespan=lifespan)
app.mount("/echo", echo.mcp.streamable_http_app())
app.mount("/math", math.mcp.streamable_http_app())
# Create the Starlette app and mount the MCP servers
app = Starlette(
routes=[
Mount("/echo", echo_mcp.streamable_http_app()),
Mount("/math", math_mcp.streamable_http_app()),
],
lifespan=lifespan,
)
```
_Full example: [examples/snippets/servers/streamable_starlette_mount.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/streamable_starlette_mount.py)_
<!-- /snippet-source -->
For low level server with Streamable HTTP implementations, see:
- Stateful server: [`examples/servers/simple-streamablehttp/`](examples/servers/simple-streamablehttp/)
@ -945,26 +970,6 @@ The streamable HTTP transport supports:
By default, SSE servers are mounted at `/sse` and Streamable HTTP servers are mounted at `/mcp`. You can customize these paths using the methods described below.
#### Streamable HTTP servers
The following example shows how to use `streamable_http_app()`, a method that returns a `Starlette` application object.
You can then append additional routes to that application as needed.
```python
mcp = FastMCP("My App")
app = mcp.streamable_http_app()
# Additional non-MCP routes can be added like so:
# from starlette.routing import Route
# app.router.routes.append(Route("/", endpoint=other_route_function))
```
To customize the route from the default of "/mcp", either specify the `streamable_http_path` option for the `FastMCP` constructor,
or set `FASTMCP_STREAMABLE_HTTP_PATH` environment variable.
Note that in Starlette and FastAPI (which is based on Starlette), the "/mcp" route will redirect to "/mcp/",
so you may need to use "/mcp/" when pointing MCP clients at your servers.
For more information on mounting applications in Starlette, see the [Starlette documentation](https://www.starlette.io/routing/#submounting-routes).
#### SSE servers
@ -1336,9 +1341,7 @@ The SDK provides a high-level client interface for connecting to MCP servers usi
<!-- snippet-source examples/snippets/clients/stdio_client.py -->
```python
"""MCP client example using stdio transport.
This is a documentation example showing how to write an MCP client.
"""
cd to the `examples/snippets/clients` directory and run:
uv run client
"""
@ -1428,14 +1431,22 @@ _Full example: [examples/snippets/clients/stdio_client.py](https://github.com/mo
Clients can also connect using [Streamable HTTP transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http):
<!-- snippet-source examples/snippets/clients/streamable_basic.py -->
```python
from mcp.client.streamable_http import streamablehttp_client
"""
Run from the repository root:
uv run examples/snippets/clients/streamable_basic.py
"""
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def main():
# Connect to a streamable HTTP server
async with streamablehttp_client("example/mcp") as (
async with streamablehttp_client("http://localhost:8000/mcp") as (
read_stream,
write_stream,
_,
@ -1444,21 +1455,25 @@ async def main():
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"})
# List available tools
tools = await session.list_tools()
print(f"Available tools: {[tool.name for tool in tools.tools]}")
if __name__ == "__main__":
asyncio.run(main())
```
_Full example: [examples/snippets/clients/streamable_basic.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/clients/streamable_basic.py)_
<!-- /snippet-source -->
### Client Display Utilities
When building MCP clients, the SDK provides utilities to help display human-readable names for tools, resources, and prompts:
<!-- snippet-source examples/snippets/clients/display_utilities.py -->
```python
"""Client display utilities example.
This example shows how to use the SDK's display utilities to show
human-readable names for tools, resources, and prompts.
"""
cd to the `examples/snippets` directory and run:
uv run display-utilities-client
"""