support streamable http mcp (#1245)

Co-authored-by: luhualin
This commit is contained in:
Betula-L 2025-05-22 05:34:50 +08:00 committed by GitHub
parent 38261fd31c
commit 9fd680c366
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 36 additions and 4 deletions

View File

@ -4,7 +4,7 @@
![PyPI - Downloads](https://img.shields.io/pypi/dd/markitdown-mcp)
[![Built by AutoGen Team](https://img.shields.io/badge/Built%20by-AutoGen%20Team-blue)](https://github.com/microsoft/autogen)
The `markitdown-mcp` package provides a lightweight STDIO and SSE MCP server for calling MarkItDown.
The `markitdown-mcp` package provides a lightweight STDIO, SSE and Streamable HTTP MCP server for calling MarkItDown.
It exposes one tool: `convert_to_markdown(uri)`, where uri can be any `http:`, `https:`, `file:`, or `data:` URI.
@ -25,7 +25,7 @@ To run the MCP server, ussing STDIO (default) use the following command:
markitdown-mcp
```
To run the MCP server, using SSE use the following command:
To run the MCP server, using SSE or Streamable HTTP use the following command:
```bash
markitdown-mcp --sse --host 127.0.0.1 --port 3001
@ -114,6 +114,11 @@ If using SSE:
* input `http://127.0.0.1:3001/sse` as the URL, and
* click `Connect`
If using Streamable HTTP:
* select `Streamable HTTP` as the transport type,
* input `http://127.0.0.1:3001/mcp` as the URL, and
* click `Connect`
Finally:
* click the `Tools` tab,
* click `List Tools`,
@ -122,7 +127,7 @@ Finally:
## Security Considerations
The server does not support authentication, and runs with the privileges if the user running it. For this reason, when running in SSE mode, it is recommended to run the server bound to `localhost` (default).
The server does not support authentication, and runs with the privileges if the user running it. For this reason, when running in SSE or Streamable HTTP mode, it is recommended to run the server bound to `localhost` (default).
## Trademarks

View File

@ -24,7 +24,7 @@ classifiers = [
"Programming Language :: Python :: Implementation :: PyPy",
]
dependencies = [
"mcp~=1.5.0",
"mcp~=1.8.0",
"markitdown[all]>=0.1.1,<0.2.0",
]

View File

@ -1,10 +1,14 @@
import contextlib
import sys
from collections.abc import AsyncIterator
from mcp.server.fastmcp import FastMCP
from starlette.applications import Starlette
from mcp.server.sse import SseServerTransport
from starlette.requests import Request
from starlette.routing import Mount, Route
from starlette.types import Receive, Scope, Send
from mcp.server import Server
from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
from markitdown import MarkItDown
import uvicorn
@ -20,6 +24,12 @@ async def convert_to_markdown(uri: str) -> str:
def create_starlette_app(mcp_server: Server, *, debug: bool = False) -> Starlette:
sse = SseServerTransport("/messages/")
session_manager = StreamableHTTPSessionManager(
app=mcp_server,
event_store=None,
json_response=True,
stateless=True,
)
async def handle_sse(request: Request) -> None:
async with sse.connect_sse(
@ -33,12 +43,29 @@ def create_starlette_app(mcp_server: Server, *, debug: bool = False) -> Starlett
mcp_server.create_initialization_options(),
)
async def handle_streamable_http(
scope: Scope, receive: Receive, send: Send
) -> None:
await session_manager.handle_request(scope, receive, send)
@contextlib.asynccontextmanager
async def lifespan(app: Starlette) -> AsyncIterator[None]:
"""Context manager for session manager."""
async with session_manager.run():
print("Application started with StreamableHTTP session manager!")
try:
yield
finally:
print("Application shutting down...")
return Starlette(
debug=debug,
routes=[
Route("/sse", endpoint=handle_sse),
Mount("/mcp", app=handle_streamable_http),
Mount("/messages/", app=sse.handle_post_message),
],
lifespan=lifespan,
)