3131 - [ Prompts] ( #prompts )
3232 - [ Images] ( #images )
3333 - [ Context] ( #context )
34+ - [ Getting Context in Functions] ( #getting-context-in-functions )
35+ - [ Context Properties and Methods] ( #context-properties-and-methods )
3436 - [ Completions] ( #completions )
3537 - [ Elicitation] ( #elicitation )
3638 - [ Sampling] ( #sampling )
3739 - [ Logging and Notifications] ( #logging-and-notifications )
3840 - [ Authentication] ( #authentication )
3941 - [ FastMCP Properties] ( #fastmcp-properties )
40- - [ Session Properties] ( #session-properties-and-methods )
42+ - [ Session Properties and Methods ] ( #session-properties-and-methods )
4143 - [ Request Context Properties] ( #request-context-properties )
4244 - [ Running Your Server] ( #running-your-server )
4345 - [ Development Mode] ( #development-mode )
4446 - [ Claude Desktop Integration] ( #claude-desktop-integration )
4547 - [ Direct Execution] ( #direct-execution )
4648 - [ Streamable HTTP Transport] ( #streamable-http-transport )
49+ - [ CORS Configuration for Browser-Based Clients] ( #cors-configuration-for-browser-based-clients )
4750 - [ Mounting to an Existing ASGI Server] ( #mounting-to-an-existing-asgi-server )
51+ - [ StreamableHTTP servers] ( #streamablehttp-servers )
52+ - [ Basic mounting] ( #basic-mounting )
53+ - [ Host-based routing] ( #host-based-routing )
54+ - [ Multiple servers with path configuration] ( #multiple-servers-with-path-configuration )
55+ - [ Path configuration at initialization] ( #path-configuration-at-initialization )
56+ - [ SSE servers] ( #sse-servers )
4857 - [ Advanced Usage] ( #advanced-usage )
4958 - [ Low-Level Server] ( #low-level-server )
59+ - [ Structured Output Support] ( #structured-output-support )
5060 - [ Writing MCP Clients] ( #writing-mcp-clients )
5161 - [ Client Display Utilities] ( #client-display-utilities )
5262 - [ OAuth Authentication for Clients] ( #oauth-authentication-for-clients )
@@ -400,7 +410,7 @@ def get_weather(city: str) -> WeatherData:
400410 """ Get weather for a city - returns structured data."""
401411 # Simulated weather data
402412 return WeatherData(
403- temperature = 72 .5 ,
413+ temperature = 22 .5 ,
404414 humidity = 45.0 ,
405415 condition = " sunny" ,
406416 wind_speed = 5.2 ,
@@ -1143,6 +1153,11 @@ app = Starlette(
11431153 ],
11441154 lifespan = lifespan,
11451155)
1156+
1157+ # Note: Clients connect to http://localhost:8000/echo/mcp and http://localhost:8000/math/mcp
1158+ # To mount at the root of each path (e.g., /echo instead of /echo/mcp):
1159+ # echo_mcp.settings.streamable_http_path = "/"
1160+ # math_mcp.settings.streamable_http_path = "/"
11461161```
11471162
11481163_ Full example: [ examples/snippets/servers/streamable_starlette_mount.py] ( https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/streamable_starlette_mount.py ) _
@@ -1160,12 +1175,204 @@ The streamable HTTP transport supports:
11601175- JSON or SSE response formats
11611176- Better scalability for multi-node deployments
11621177
1178+ #### CORS Configuration for Browser-Based Clients
1179+
1180+ If you'd like your server to be accessible by browser-based MCP clients, you'll need to configure CORS headers. The ` Mcp-Session-Id ` header must be exposed for browser clients to access it:
1181+
1182+ ``` python
1183+ from starlette.applications import Starlette
1184+ from starlette.middleware.cors import CORSMiddleware
1185+
1186+ # Create your Starlette app first
1187+ starlette_app = Starlette(routes = [... ])
1188+
1189+ # Then wrap it with CORS middleware
1190+ starlette_app = CORSMiddleware(
1191+ starlette_app,
1192+ allow_origins = [" *" ], # Configure appropriately for production
1193+ allow_methods = [" GET" , " POST" , " DELETE" ], # MCP streamable HTTP methods
1194+ expose_headers = [" Mcp-Session-Id" ],
1195+ )
1196+ ```
1197+
1198+ This configuration is necessary because:
1199+
1200+ - The MCP streamable HTTP transport uses the ` Mcp-Session-Id ` header for session management
1201+ - Browsers restrict access to response headers unless explicitly exposed via CORS
1202+ - Without this configuration, browser-based clients won't be able to read the session ID from initialization responses
1203+
11631204### Mounting to an Existing ASGI Server
11641205
11651206By 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.
11661207
11671208For more information on mounting applications in Starlette, see the [ Starlette documentation] ( https://www.starlette.io/routing/#submounting-routes ) .
11681209
1210+ #### StreamableHTTP servers
1211+
1212+ 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.
1213+
1214+ ##### Basic mounting
1215+
1216+ <!-- snippet-source examples/snippets/servers/streamable_http_basic_mounting.py -->
1217+ ``` python
1218+ """
1219+ Basic example showing how to mount StreamableHTTP server in Starlette.
1220+
1221+ Run from the repository root:
1222+ uvicorn examples.snippets.servers.streamable_http_basic_mounting:app --reload
1223+ """
1224+
1225+ from starlette.applications import Starlette
1226+ from starlette.routing import Mount
1227+
1228+ from mcp.server.fastmcp import FastMCP
1229+
1230+ # Create MCP server
1231+ mcp = FastMCP(" My App" )
1232+
1233+
1234+ @mcp.tool ()
1235+ def hello () -> str :
1236+ """ A simple hello tool"""
1237+ return " Hello from MCP!"
1238+
1239+
1240+ # Mount the StreamableHTTP server to the existing ASGI server
1241+ app = Starlette(
1242+ routes = [
1243+ Mount(" /" , app = mcp.streamable_http_app()),
1244+ ]
1245+ )
1246+ ```
1247+
1248+ _ 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 ) _
1249+ <!-- /snippet-source -->
1250+
1251+ ##### Host-based routing
1252+
1253+ <!-- snippet-source examples/snippets/servers/streamable_http_host_mounting.py -->
1254+ ``` python
1255+ """
1256+ Example showing how to mount StreamableHTTP server using Host-based routing.
1257+
1258+ Run from the repository root:
1259+ uvicorn examples.snippets.servers.streamable_http_host_mounting:app --reload
1260+ """
1261+
1262+ from starlette.applications import Starlette
1263+ from starlette.routing import Host
1264+
1265+ from mcp.server.fastmcp import FastMCP
1266+
1267+ # Create MCP server
1268+ mcp = FastMCP(" MCP Host App" )
1269+
1270+
1271+ @mcp.tool ()
1272+ def domain_info () -> str :
1273+ """ Get domain-specific information"""
1274+ return " This is served from mcp.acme.corp"
1275+
1276+
1277+ # Mount using Host-based routing
1278+ app = Starlette(
1279+ routes = [
1280+ Host(" mcp.acme.corp" , app = mcp.streamable_http_app()),
1281+ ]
1282+ )
1283+ ```
1284+
1285+ _ 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 ) _
1286+ <!-- /snippet-source -->
1287+
1288+ ##### Multiple servers with path configuration
1289+
1290+ <!-- snippet-source examples/snippets/servers/streamable_http_multiple_servers.py -->
1291+ ``` python
1292+ """
1293+ Example showing how to mount multiple StreamableHTTP servers with path configuration.
1294+
1295+ Run from the repository root:
1296+ uvicorn examples.snippets.servers.streamable_http_multiple_servers:app --reload
1297+ """
1298+
1299+ from starlette.applications import Starlette
1300+ from starlette.routing import Mount
1301+
1302+ from mcp.server.fastmcp import FastMCP
1303+
1304+ # Create multiple MCP servers
1305+ api_mcp = FastMCP(" API Server" )
1306+ chat_mcp = FastMCP(" Chat Server" )
1307+
1308+
1309+ @api_mcp.tool ()
1310+ def api_status () -> str :
1311+ """ Get API status"""
1312+ return " API is running"
1313+
1314+
1315+ @chat_mcp.tool ()
1316+ def send_message (message : str ) -> str :
1317+ """ Send a chat message"""
1318+ return f " Message sent: { message} "
1319+
1320+
1321+ # Configure servers to mount at the root of each path
1322+ # This means endpoints will be at /api and /chat instead of /api/mcp and /chat/mcp
1323+ api_mcp.settings.streamable_http_path = " /"
1324+ chat_mcp.settings.streamable_http_path = " /"
1325+
1326+ # Mount the servers
1327+ app = Starlette(
1328+ routes = [
1329+ Mount(" /api" , app = api_mcp.streamable_http_app()),
1330+ Mount(" /chat" , app = chat_mcp.streamable_http_app()),
1331+ ]
1332+ )
1333+ ```
1334+
1335+ _ 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 ) _
1336+ <!-- /snippet-source -->
1337+
1338+ ##### Path configuration at initialization
1339+
1340+ <!-- snippet-source examples/snippets/servers/streamable_http_path_config.py -->
1341+ ``` python
1342+ """
1343+ Example showing path configuration during FastMCP initialization.
1344+
1345+ Run from the repository root:
1346+ uvicorn examples.snippets.servers.streamable_http_path_config:app --reload
1347+ """
1348+
1349+ from starlette.applications import Starlette
1350+ from starlette.routing import Mount
1351+
1352+ from mcp.server.fastmcp import FastMCP
1353+
1354+ # Configure streamable_http_path during initialization
1355+ # This server will mount at the root of wherever it's mounted
1356+ mcp_at_root = FastMCP(" My Server" , streamable_http_path = " /" )
1357+
1358+
1359+ @mcp_at_root.tool ()
1360+ def process_data (data : str ) -> str :
1361+ """ Process some data"""
1362+ return f " Processed: { data} "
1363+
1364+
1365+ # Mount at /process - endpoints will be at /process instead of /process/mcp
1366+ app = Starlette(
1367+ routes = [
1368+ Mount(" /process" , app = mcp_at_root.streamable_http_app()),
1369+ ]
1370+ )
1371+ ```
1372+
1373+ _ 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 ) _
1374+ <!-- /snippet-source -->
1375+
11691376#### SSE servers
11701377
11711378> ** Note** : SSE transport is being superseded by [ Streamable HTTP transport] ( https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http ) .
@@ -1940,6 +2147,7 @@ MCP servers declare capabilities during initialization:
19402147
19412148## Documentation
19422149
2150+ - [ API Reference] ( https://modelcontextprotocol.github.io/python-sdk/api/ )
19432151- [ Model Context Protocol documentation] ( https://modelcontextprotocol.io )
19442152- [ Model Context Protocol specification] ( https://spec.modelcontextprotocol.io )
19452153- [ Officially supported servers] ( https://github.com/modelcontextprotocol/servers )
0 commit comments