Skip to content

Commit fed3c3f

Browse files
refactor: split StreamableHTTP mounting examples into separate files
- Split single streamable_http_mounting.py into four focused examples: - Basic mounting example - Host-based routing example - Multiple servers with path configuration - Path configuration at initialization - Removed manual route append approach, now using proper Host() in routes - Updated README with clearer structure and subsections for each example This addresses review feedback to improve clarity and organization of the StreamableHTTP mounting documentation. Reported-by:Kludex
1 parent 5edc93e commit fed3c3f

File tree

6 files changed

+230
-93
lines changed

6 files changed

+230
-93
lines changed

README.md

Lines changed: 104 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,21 +1175,23 @@ For more information on mounting applications in Starlette, see the [Starlette d
11751175

11761176
You can mount the StreamableHTTP server to an existing ASGI server using the `streamable_http_app` method. This allows you to integrate the StreamableHTTP server with other ASGI applications.
11771177

1178-
<!-- snippet-source examples/snippets/servers/streamable_http_mounting.py -->
1178+
##### Basic mounting
1179+
1180+
<!-- snippet-source examples/snippets/servers/streamable_http_basic_mounting.py -->
11791181
```python
11801182
"""
1181-
Example showing how to mount StreamableHTTP servers in Starlette applications.
1183+
Basic example showing how to mount StreamableHTTP server in Starlette.
11821184
11831185
Run from the repository root:
1184-
uvicorn examples.snippets.servers.streamable_http_mounting:app --reload
1186+
uvicorn examples.snippets.servers.streamable_http_basic_mounting:app --reload
11851187
"""
11861188

11871189
from starlette.applications import Starlette
1188-
from starlette.routing import Host, Mount
1190+
from starlette.routing import Mount
11891191

11901192
from mcp.server.fastmcp import FastMCP
11911193

1192-
# Basic example - mounting at root
1194+
# Create MCP server
11931195
mcp = FastMCP("My App")
11941196

11951197

@@ -1205,11 +1207,64 @@ app = Starlette(
12051207
Mount("/", app=mcp.streamable_http_app()),
12061208
]
12071209
)
1210+
```
12081211

1209-
# or dynamically mount as host
1210-
app.router.routes.append(Host("mcp.acme.corp", app=mcp.streamable_http_app()))
1212+
_Full example: [examples/snippets/servers/streamable_http_basic_mounting.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/streamable_http_basic_mounting.py)_
1213+
<!-- /snippet-source -->
1214+
1215+
##### Host-based routing
1216+
1217+
<!-- snippet-source examples/snippets/servers/streamable_http_host_mounting.py -->
1218+
```python
1219+
"""
1220+
Example showing how to mount StreamableHTTP server using Host-based routing.
1221+
1222+
Run from the repository root:
1223+
uvicorn examples.snippets.servers.streamable_http_host_mounting:app --reload
1224+
"""
1225+
1226+
from starlette.applications import Starlette
1227+
from starlette.routing import Host
1228+
1229+
from mcp.server.fastmcp import FastMCP
1230+
1231+
# Create MCP server
1232+
mcp = FastMCP("MCP Host App")
1233+
1234+
1235+
@mcp.tool()
1236+
def domain_info() -> str:
1237+
"""Get domain-specific information"""
1238+
return "This is served from mcp.acme.corp"
1239+
1240+
1241+
# Mount using Host-based routing
1242+
app = Starlette(
1243+
routes=[
1244+
Host("mcp.acme.corp", app=mcp.streamable_http_app()),
1245+
]
1246+
)
1247+
```
1248+
1249+
_Full example: [examples/snippets/servers/streamable_http_host_mounting.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/streamable_http_host_mounting.py)_
1250+
<!-- /snippet-source -->
1251+
1252+
##### Multiple servers with path configuration
1253+
1254+
<!-- snippet-source examples/snippets/servers/streamable_http_multiple_servers.py -->
1255+
```python
1256+
"""
1257+
Example showing how to mount multiple StreamableHTTP servers with path configuration.
1258+
1259+
Run from the repository root:
1260+
uvicorn examples.snippets.servers.streamable_http_multiple_servers:app --reload
1261+
"""
1262+
1263+
from starlette.applications import Starlette
1264+
from starlette.routing import Mount
1265+
1266+
from mcp.server.fastmcp import FastMCP
12111267

1212-
# Advanced example - multiple servers with path configuration
12131268
# Create multiple MCP servers
12141269
api_mcp = FastMCP("API Server")
12151270
chat_mcp = FastMCP("Chat Server")
@@ -1227,31 +1282,59 @@ def send_message(message: str) -> str:
12271282
return f"Message sent: {message}"
12281283

12291284

1230-
# Default behavior: endpoints will be at /api/mcp and /chat/mcp
1231-
default_app = Starlette(
1232-
routes=[
1233-
Mount("/api", app=api_mcp.streamable_http_app()),
1234-
Mount("/chat", app=chat_mcp.streamable_http_app()),
1235-
]
1236-
)
1237-
1238-
# To mount at the root of each path (e.g., /api instead of /api/mcp):
1239-
# Configure streamable_http_path before mounting
1285+
# Configure servers to mount at the root of each path
1286+
# This means endpoints will be at /api and /chat instead of /api/mcp and /chat/mcp
12401287
api_mcp.settings.streamable_http_path = "/"
12411288
chat_mcp.settings.streamable_http_path = "/"
12421289

1243-
configured_app = Starlette(
1290+
# Mount the servers
1291+
app = Starlette(
12441292
routes=[
12451293
Mount("/api", app=api_mcp.streamable_http_app()),
12461294
Mount("/chat", app=chat_mcp.streamable_http_app()),
12471295
]
12481296
)
1297+
```
1298+
1299+
_Full example: [examples/snippets/servers/streamable_http_multiple_servers.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/streamable_http_multiple_servers.py)_
1300+
<!-- /snippet-source -->
1301+
1302+
##### Path configuration at initialization
1303+
1304+
<!-- snippet-source examples/snippets/servers/streamable_http_path_config.py -->
1305+
```python
1306+
"""
1307+
Example showing path configuration during FastMCP initialization.
1308+
1309+
Run from the repository root:
1310+
uvicorn examples.snippets.servers.streamable_http_path_config:app --reload
1311+
"""
1312+
1313+
from starlette.applications import Starlette
1314+
from starlette.routing import Mount
1315+
1316+
from mcp.server.fastmcp import FastMCP
12491317

1250-
# Or configure during initialization
1318+
# Configure streamable_http_path during initialization
1319+
# This server will mount at the root of wherever it's mounted
12511320
mcp_at_root = FastMCP("My Server", streamable_http_path="/")
1321+
1322+
1323+
@mcp_at_root.tool()
1324+
def process_data(data: str) -> str:
1325+
"""Process some data"""
1326+
return f"Processed: {data}"
1327+
1328+
1329+
# Mount at /process - endpoints will be at /process instead of /process/mcp
1330+
app = Starlette(
1331+
routes=[
1332+
Mount("/process", app=mcp_at_root.streamable_http_app()),
1333+
]
1334+
)
12521335
```
12531336

1254-
_Full example: [examples/snippets/servers/streamable_http_mounting.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/streamable_http_mounting.py)_
1337+
_Full example: [examples/snippets/servers/streamable_http_path_config.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/streamable_http_path_config.py)_
12551338
<!-- /snippet-source -->
12561339

12571340
#### SSE servers
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""
2+
Basic example showing how to mount StreamableHTTP server in Starlette.
3+
4+
Run from the repository root:
5+
uvicorn examples.snippets.servers.streamable_http_basic_mounting:app --reload
6+
"""
7+
8+
from starlette.applications import Starlette
9+
from starlette.routing import Mount
10+
11+
from mcp.server.fastmcp import FastMCP
12+
13+
# Create MCP server
14+
mcp = FastMCP("My App")
15+
16+
17+
@mcp.tool()
18+
def hello() -> str:
19+
"""A simple hello tool"""
20+
return "Hello from MCP!"
21+
22+
23+
# Mount the StreamableHTTP server to the existing ASGI server
24+
app = Starlette(
25+
routes=[
26+
Mount("/", app=mcp.streamable_http_app()),
27+
]
28+
)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""
2+
Example showing how to mount StreamableHTTP server using Host-based routing.
3+
4+
Run from the repository root:
5+
uvicorn examples.snippets.servers.streamable_http_host_mounting:app --reload
6+
"""
7+
8+
from starlette.applications import Starlette
9+
from starlette.routing import Host
10+
11+
from mcp.server.fastmcp import FastMCP
12+
13+
# Create MCP server
14+
mcp = FastMCP("MCP Host App")
15+
16+
17+
@mcp.tool()
18+
def domain_info() -> str:
19+
"""Get domain-specific information"""
20+
return "This is served from mcp.acme.corp"
21+
22+
23+
# Mount using Host-based routing
24+
app = Starlette(
25+
routes=[
26+
Host("mcp.acme.corp", app=mcp.streamable_http_app()),
27+
]
28+
)

examples/snippets/servers/streamable_http_mounting.py

Lines changed: 0 additions & 72 deletions
This file was deleted.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""
2+
Example showing how to mount multiple StreamableHTTP servers with path configuration.
3+
4+
Run from the repository root:
5+
uvicorn examples.snippets.servers.streamable_http_multiple_servers:app --reload
6+
"""
7+
8+
from starlette.applications import Starlette
9+
from starlette.routing import Mount
10+
11+
from mcp.server.fastmcp import FastMCP
12+
13+
# Create multiple MCP servers
14+
api_mcp = FastMCP("API Server")
15+
chat_mcp = FastMCP("Chat Server")
16+
17+
18+
@api_mcp.tool()
19+
def api_status() -> str:
20+
"""Get API status"""
21+
return "API is running"
22+
23+
24+
@chat_mcp.tool()
25+
def send_message(message: str) -> str:
26+
"""Send a chat message"""
27+
return f"Message sent: {message}"
28+
29+
30+
# Configure servers to mount at the root of each path
31+
# This means endpoints will be at /api and /chat instead of /api/mcp and /chat/mcp
32+
api_mcp.settings.streamable_http_path = "/"
33+
chat_mcp.settings.streamable_http_path = "/"
34+
35+
# Mount the servers
36+
app = Starlette(
37+
routes=[
38+
Mount("/api", app=api_mcp.streamable_http_app()),
39+
Mount("/chat", app=chat_mcp.streamable_http_app()),
40+
]
41+
)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""
2+
Example showing path configuration during FastMCP initialization.
3+
4+
Run from the repository root:
5+
uvicorn examples.snippets.servers.streamable_http_path_config:app --reload
6+
"""
7+
8+
from starlette.applications import Starlette
9+
from starlette.routing import Mount
10+
11+
from mcp.server.fastmcp import FastMCP
12+
13+
# Configure streamable_http_path during initialization
14+
# This server will mount at the root of wherever it's mounted
15+
mcp_at_root = FastMCP("My Server", streamable_http_path="/")
16+
17+
18+
@mcp_at_root.tool()
19+
def process_data(data: str) -> str:
20+
"""Process some data"""
21+
return f"Processed: {data}"
22+
23+
24+
# Mount at /process - endpoints will be at /process instead of /process/mcp
25+
app = Starlette(
26+
routes=[
27+
Mount("/process", app=mcp_at_root.streamable_http_app()),
28+
]
29+
)

0 commit comments

Comments
 (0)