Skip to content

Commit fb323a3

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 acd0121 commit fb323a3

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
@@ -1011,21 +1011,23 @@ For more information on mounting applications in Starlette, see the [Starlette d
10111011

10121012
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.
10131013

1014-
<!-- snippet-source examples/snippets/servers/streamable_http_mounting.py -->
1014+
##### Basic mounting
1015+
1016+
<!-- snippet-source examples/snippets/servers/streamable_http_basic_mounting.py -->
10151017
```python
10161018
"""
1017-
Example showing how to mount StreamableHTTP servers in Starlette applications.
1019+
Basic example showing how to mount StreamableHTTP server in Starlette.
10181020
10191021
Run from the repository root:
1020-
uvicorn examples.snippets.servers.streamable_http_mounting:app --reload
1022+
uvicorn examples.snippets.servers.streamable_http_basic_mounting:app --reload
10211023
"""
10221024

10231025
from starlette.applications import Starlette
1024-
from starlette.routing import Host, Mount
1026+
from starlette.routing import Mount
10251027

10261028
from mcp.server.fastmcp import FastMCP
10271029

1028-
# Basic example - mounting at root
1030+
# Create MCP server
10291031
mcp = FastMCP("My App")
10301032

10311033

@@ -1041,11 +1043,64 @@ app = Starlette(
10411043
Mount("/", app=mcp.streamable_http_app()),
10421044
]
10431045
)
1046+
```
10441047

1045-
# or dynamically mount as host
1046-
app.router.routes.append(Host("mcp.acme.corp", app=mcp.streamable_http_app()))
1048+
_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)_
1049+
<!-- /snippet-source -->
1050+
1051+
##### Host-based routing
1052+
1053+
<!-- snippet-source examples/snippets/servers/streamable_http_host_mounting.py -->
1054+
```python
1055+
"""
1056+
Example showing how to mount StreamableHTTP server using Host-based routing.
1057+
1058+
Run from the repository root:
1059+
uvicorn examples.snippets.servers.streamable_http_host_mounting:app --reload
1060+
"""
1061+
1062+
from starlette.applications import Starlette
1063+
from starlette.routing import Host
1064+
1065+
from mcp.server.fastmcp import FastMCP
1066+
1067+
# Create MCP server
1068+
mcp = FastMCP("MCP Host App")
1069+
1070+
1071+
@mcp.tool()
1072+
def domain_info() -> str:
1073+
"""Get domain-specific information"""
1074+
return "This is served from mcp.acme.corp"
1075+
1076+
1077+
# Mount using Host-based routing
1078+
app = Starlette(
1079+
routes=[
1080+
Host("mcp.acme.corp", app=mcp.streamable_http_app()),
1081+
]
1082+
)
1083+
```
1084+
1085+
_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)_
1086+
<!-- /snippet-source -->
1087+
1088+
##### Multiple servers with path configuration
1089+
1090+
<!-- snippet-source examples/snippets/servers/streamable_http_multiple_servers.py -->
1091+
```python
1092+
"""
1093+
Example showing how to mount multiple StreamableHTTP servers with path configuration.
1094+
1095+
Run from the repository root:
1096+
uvicorn examples.snippets.servers.streamable_http_multiple_servers:app --reload
1097+
"""
1098+
1099+
from starlette.applications import Starlette
1100+
from starlette.routing import Mount
1101+
1102+
from mcp.server.fastmcp import FastMCP
10471103

1048-
# Advanced example - multiple servers with path configuration
10491104
# Create multiple MCP servers
10501105
api_mcp = FastMCP("API Server")
10511106
chat_mcp = FastMCP("Chat Server")
@@ -1063,31 +1118,59 @@ def send_message(message: str) -> str:
10631118
return f"Message sent: {message}"
10641119

10651120

1066-
# Default behavior: endpoints will be at /api/mcp and /chat/mcp
1067-
default_app = Starlette(
1068-
routes=[
1069-
Mount("/api", app=api_mcp.streamable_http_app()),
1070-
Mount("/chat", app=chat_mcp.streamable_http_app()),
1071-
]
1072-
)
1073-
1074-
# To mount at the root of each path (e.g., /api instead of /api/mcp):
1075-
# Configure streamable_http_path before mounting
1121+
# Configure servers to mount at the root of each path
1122+
# This means endpoints will be at /api and /chat instead of /api/mcp and /chat/mcp
10761123
api_mcp.settings.streamable_http_path = "/"
10771124
chat_mcp.settings.streamable_http_path = "/"
10781125

1079-
configured_app = Starlette(
1126+
# Mount the servers
1127+
app = Starlette(
10801128
routes=[
10811129
Mount("/api", app=api_mcp.streamable_http_app()),
10821130
Mount("/chat", app=chat_mcp.streamable_http_app()),
10831131
]
10841132
)
1133+
```
1134+
1135+
_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)_
1136+
<!-- /snippet-source -->
1137+
1138+
##### Path configuration at initialization
1139+
1140+
<!-- snippet-source examples/snippets/servers/streamable_http_path_config.py -->
1141+
```python
1142+
"""
1143+
Example showing path configuration during FastMCP initialization.
1144+
1145+
Run from the repository root:
1146+
uvicorn examples.snippets.servers.streamable_http_path_config:app --reload
1147+
"""
1148+
1149+
from starlette.applications import Starlette
1150+
from starlette.routing import Mount
1151+
1152+
from mcp.server.fastmcp import FastMCP
10851153

1086-
# Or configure during initialization
1154+
# Configure streamable_http_path during initialization
1155+
# This server will mount at the root of wherever it's mounted
10871156
mcp_at_root = FastMCP("My Server", streamable_http_path="/")
1157+
1158+
1159+
@mcp_at_root.tool()
1160+
def process_data(data: str) -> str:
1161+
"""Process some data"""
1162+
return f"Processed: {data}"
1163+
1164+
1165+
# Mount at /process - endpoints will be at /process instead of /process/mcp
1166+
app = Starlette(
1167+
routes=[
1168+
Mount("/process", app=mcp_at_root.streamable_http_app()),
1169+
]
1170+
)
10881171
```
10891172

1090-
_Full example: [examples/snippets/servers/streamable_http_mounting.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/streamable_http_mounting.py)_
1173+
_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)_
10911174
<!-- /snippet-source -->
10921175

10931176
#### 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)