Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 56 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1262,13 +1262,15 @@ Run from the repository root:
uvicorn examples.snippets.servers.streamable_http_basic_mounting:app --reload
"""

import contextlib

from starlette.applications import Starlette
from starlette.routing import Mount

from mcp.server.fastmcp import FastMCP

# Create MCP server
mcp = FastMCP("My App")
mcp = FastMCP("My App", stateless_http=True)


@mcp.tool()
Expand All @@ -1277,11 +1279,20 @@ def hello() -> str:
return "Hello from MCP!"


# Create lifespan context manager to initialize the session manager
@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
"""Context manager for managing MCP session manager lifecycle."""
async with mcp.session_manager.run():
yield


# Mount the StreamableHTTP server to the existing ASGI server
app = Starlette(
routes=[
Mount("/", app=mcp.streamable_http_app()),
]
],
lifespan=lifespan,
)
```

Expand All @@ -1299,13 +1310,15 @@ Run from the repository root:
uvicorn examples.snippets.servers.streamable_http_host_mounting:app --reload
"""

import contextlib

from starlette.applications import Starlette
from starlette.routing import Host

from mcp.server.fastmcp import FastMCP

# Create MCP server
mcp = FastMCP("MCP Host App")
mcp = FastMCP("MCP Host App", stateless_http=True)


@mcp.tool()
Expand All @@ -1314,11 +1327,20 @@ def domain_info() -> str:
return "This is served from mcp.acme.corp"


# Create lifespan context manager to initialize the session manager
@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
"""Context manager for managing MCP session manager lifecycle."""
async with mcp.session_manager.run():
yield


# Mount using Host-based routing
app = Starlette(
routes=[
Host("mcp.acme.corp", app=mcp.streamable_http_app()),
]
],
lifespan=lifespan,
)
```

Expand All @@ -1336,14 +1358,16 @@ Run from the repository root:
uvicorn examples.snippets.servers.streamable_http_multiple_servers:app --reload
"""

import contextlib

from starlette.applications import Starlette
from starlette.routing import Mount

from mcp.server.fastmcp import FastMCP

# Create multiple MCP servers
api_mcp = FastMCP("API Server")
chat_mcp = FastMCP("Chat Server")
api_mcp = FastMCP("API Server", stateless_http=True)
chat_mcp = FastMCP("Chat Server", stateless_http=True)


@api_mcp.tool()
Expand All @@ -1363,12 +1387,24 @@ def send_message(message: str) -> str:
api_mcp.settings.streamable_http_path = "/"
chat_mcp.settings.streamable_http_path = "/"


# Create lifespan context manager to initialize both session managers
@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
"""Context manager for managing multiple MCP session managers."""
async with contextlib.AsyncExitStack() as stack:
await stack.enter_async_context(api_mcp.session_manager.run())
await stack.enter_async_context(chat_mcp.session_manager.run())
yield


# Mount the servers
app = Starlette(
routes=[
Mount("/api", app=api_mcp.streamable_http_app()),
Mount("/chat", app=chat_mcp.streamable_http_app()),
]
],
lifespan=lifespan,
)
```

Expand All @@ -1386,14 +1422,16 @@ Run from the repository root:
uvicorn examples.snippets.servers.streamable_http_path_config:app --reload
"""

import contextlib

from starlette.applications import Starlette
from starlette.routing import Mount

from mcp.server.fastmcp import FastMCP

# Configure streamable_http_path during initialization
# This server will mount at the root of wherever it's mounted
mcp_at_root = FastMCP("My Server", streamable_http_path="/")
mcp_at_root = FastMCP("My Server", streamable_http_path="/", stateless_http=True)


@mcp_at_root.tool()
Expand All @@ -1402,11 +1440,20 @@ def process_data(data: str) -> str:
return f"Processed: {data}"


# Create lifespan context manager to initialize the session manager
@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
"""Context manager for managing MCP session manager lifecycle."""
async with mcp_at_root.session_manager.run():
yield


# Mount at /process - endpoints will be at /process instead of /process/mcp
app = Starlette(
routes=[
Mount("/process", app=mcp_at_root.streamable_http_app()),
]
],
lifespan=lifespan,
)
```

Expand Down
15 changes: 13 additions & 2 deletions examples/snippets/servers/streamable_http_basic_mounting.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
uvicorn examples.snippets.servers.streamable_http_basic_mounting:app --reload
"""

import contextlib

from starlette.applications import Starlette
from starlette.routing import Mount

from mcp.server.fastmcp import FastMCP

# Create MCP server
mcp = FastMCP("My App")
mcp = FastMCP("My App", stateless_http=True)


@mcp.tool()
Expand All @@ -20,9 +22,18 @@ def hello() -> str:
return "Hello from MCP!"


# Create lifespan context manager to initialize the session manager
@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
"""Context manager for managing MCP session manager lifecycle."""
async with mcp.session_manager.run():
yield


# Mount the StreamableHTTP server to the existing ASGI server
app = Starlette(
routes=[
Mount("/", app=mcp.streamable_http_app()),
]
],
lifespan=lifespan,
)
15 changes: 13 additions & 2 deletions examples/snippets/servers/streamable_http_host_mounting.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
uvicorn examples.snippets.servers.streamable_http_host_mounting:app --reload
"""

import contextlib

from starlette.applications import Starlette
from starlette.routing import Host

from mcp.server.fastmcp import FastMCP

# Create MCP server
mcp = FastMCP("MCP Host App")
mcp = FastMCP("MCP Host App", stateless_http=True)


@mcp.tool()
Expand All @@ -20,9 +22,18 @@ def domain_info() -> str:
return "This is served from mcp.acme.corp"


# Create lifespan context manager to initialize the session manager
@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
"""Context manager for managing MCP session manager lifecycle."""
async with mcp.session_manager.run():
yield


# Mount using Host-based routing
app = Starlette(
routes=[
Host("mcp.acme.corp", app=mcp.streamable_http_app()),
]
],
lifespan=lifespan,
)
20 changes: 17 additions & 3 deletions examples/snippets/servers/streamable_http_multiple_servers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
uvicorn examples.snippets.servers.streamable_http_multiple_servers:app --reload
"""

import contextlib

from starlette.applications import Starlette
from starlette.routing import Mount

from mcp.server.fastmcp import FastMCP

# Create multiple MCP servers
api_mcp = FastMCP("API Server")
chat_mcp = FastMCP("Chat Server")
api_mcp = FastMCP("API Server", stateless_http=True)
chat_mcp = FastMCP("Chat Server", stateless_http=True)


@api_mcp.tool()
Expand All @@ -32,10 +34,22 @@ def send_message(message: str) -> str:
api_mcp.settings.streamable_http_path = "/"
chat_mcp.settings.streamable_http_path = "/"


# Create lifespan context manager to initialize both session managers
@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
"""Context manager for managing multiple MCP session managers."""
async with contextlib.AsyncExitStack() as stack:
await stack.enter_async_context(api_mcp.session_manager.run())
await stack.enter_async_context(chat_mcp.session_manager.run())
yield


# Mount the servers
app = Starlette(
routes=[
Mount("/api", app=api_mcp.streamable_http_app()),
Mount("/chat", app=chat_mcp.streamable_http_app()),
]
],
lifespan=lifespan,
)
15 changes: 13 additions & 2 deletions examples/snippets/servers/streamable_http_path_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
uvicorn examples.snippets.servers.streamable_http_path_config:app --reload
"""

import contextlib

from starlette.applications import Starlette
from starlette.routing import Mount

from mcp.server.fastmcp import FastMCP

# Configure streamable_http_path during initialization
# This server will mount at the root of wherever it's mounted
mcp_at_root = FastMCP("My Server", streamable_http_path="/")
mcp_at_root = FastMCP("My Server", streamable_http_path="/", stateless_http=True)


@mcp_at_root.tool()
Expand All @@ -21,9 +23,18 @@ def process_data(data: str) -> str:
return f"Processed: {data}"


# Create lifespan context manager to initialize the session manager
@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
"""Context manager for managing MCP session manager lifecycle."""
async with mcp_at_root.session_manager.run():
yield


# Mount at /process - endpoints will be at /process instead of /process/mcp
app = Starlette(
routes=[
Mount("/process", app=mcp_at_root.streamable_http_app()),
]
],
lifespan=lifespan,
)
Loading