Spaces:
Running
Running
zzstoatzz commited on
Commit ·
6a43ff3
1
Parent(s): fc7e104
rm randomly truncated file
Browse files
docs/deployment/running-server.mdx
CHANGED
|
@@ -170,4 +170,117 @@ New applications should use Streamable HTTP transport instead.
|
|
| 170 |
|
| 171 |
Server-Sent Events (SSE) is an HTTP-based protocol for server-to-client streaming. While FastMCP still supports SSE, it is deprecated and Streamable HTTP is preferred for new projects.
|
| 172 |
|
| 173 |
-
To run a server using SSE, you can use the `run()` method with the `transport` argument set to `"sse"`. This will start a Uvicorn server on the default host (`127.0.0.1`), port (`8000`), and with default SSE path (`/sse`) and message path (`/messages/`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 170 |
|
| 171 |
Server-Sent Events (SSE) is an HTTP-based protocol for server-to-client streaming. While FastMCP still supports SSE, it is deprecated and Streamable HTTP is preferred for new projects.
|
| 172 |
|
| 173 |
+
To run a server using SSE, you can use the `run()` method with the `transport` argument set to `"sse"`. This will start a Uvicorn server on the default host (`127.0.0.1`), port (`8000`), and with default SSE path (`/sse`) and message path (`/messages/`).
|
| 174 |
+
|
| 175 |
+
<CodeGroup>
|
| 176 |
+
```python {6} server.py
|
| 177 |
+
from fastmcp import FastMCP
|
| 178 |
+
|
| 179 |
+
mcp = FastMCP()
|
| 180 |
+
|
| 181 |
+
if __name__ == "__main__":
|
| 182 |
+
mcp.run(transport="sse")
|
| 183 |
+
```
|
| 184 |
+
```python {3,7} client.py
|
| 185 |
+
import asyncio
|
| 186 |
+
from fastmcp import Client
|
| 187 |
+
from fastmcp.client.transports import SSETransport
|
| 188 |
+
|
| 189 |
+
async def example():
|
| 190 |
+
async with Client(
|
| 191 |
+
transport=SSETransport("http://127.0.0.1:8000/sse")
|
| 192 |
+
) as client:
|
| 193 |
+
await client.ping()
|
| 194 |
+
|
| 195 |
+
if __name__ == "__main__":
|
| 196 |
+
asyncio.run(example())
|
| 197 |
+
```
|
| 198 |
+
</CodeGroup>
|
| 199 |
+
|
| 200 |
+
<Tip>
|
| 201 |
+
Notice that the client in the above example uses an explicit `SSETransport` to connect to the server. FastMCP will attempt to infer the appropriate transport from the provided configuration, but HTTP URLs are assumed to be Streamable HTTP (as of FastMCP 2.3.0).
|
| 202 |
+
</Tip>
|
| 203 |
+
|
| 204 |
+
To customize the host, port, or log level, provide appropriate keyword arguments to the `run()` method. You can also adjust the SSE path (which clients should connect to) and the message POST endpoint (which clients use to send subsequent messages).
|
| 205 |
+
|
| 206 |
+
<CodeGroup>
|
| 207 |
+
```python {8-12} server.py
|
| 208 |
+
from fastmcp import FastMCP
|
| 209 |
+
|
| 210 |
+
mcp = FastMCP()
|
| 211 |
+
|
| 212 |
+
if __name__ == "__main__":
|
| 213 |
+
mcp.run(
|
| 214 |
+
transport="sse",
|
| 215 |
+
host="127.0.0.1",
|
| 216 |
+
port=4200,
|
| 217 |
+
log_level="debug",
|
| 218 |
+
path="/my-custom-sse-path",
|
| 219 |
+
)
|
| 220 |
+
```
|
| 221 |
+
```python {7} client.py
|
| 222 |
+
import asyncio
|
| 223 |
+
from fastmcp import Client
|
| 224 |
+
from fastmcp.client.transports import SSETransport
|
| 225 |
+
|
| 226 |
+
async def example():
|
| 227 |
+
async with Client(
|
| 228 |
+
transport=SSETransport("http://127.0.0.1:4200/my-custom-sse-path")
|
| 229 |
+
) as client:
|
| 230 |
+
await client.ping()
|
| 231 |
+
|
| 232 |
+
if __name__ == "__main__":
|
| 233 |
+
asyncio.run(example())
|
| 234 |
+
```
|
| 235 |
+
</CodeGroup>
|
| 236 |
+
|
| 237 |
+
|
| 238 |
+
|
| 239 |
+
## Async Usage
|
| 240 |
+
|
| 241 |
+
FastMCP provides both synchronous and asynchronous APIs for running your server. The `run()` method seen in previous examples is a synchronous method that internally uses `anyio.run()` to run the asynchronous server. For applications that are already running in an async context, FastMCP provides the `run_async()` method.
|
| 242 |
+
|
| 243 |
+
```python {10-12}
|
| 244 |
+
from fastmcp import FastMCP
|
| 245 |
+
import asyncio
|
| 246 |
+
|
| 247 |
+
mcp = FastMCP(name="MyServer")
|
| 248 |
+
|
| 249 |
+
@mcp.tool()
|
| 250 |
+
def hello(name: str) -> str:
|
| 251 |
+
return f"Hello, {name}!"
|
| 252 |
+
|
| 253 |
+
async def main():
|
| 254 |
+
# Use run_async() in async contexts
|
| 255 |
+
await mcp.run_async(transport="streamable-http")
|
| 256 |
+
|
| 257 |
+
if __name__ == "__main__":
|
| 258 |
+
asyncio.run(main())
|
| 259 |
+
```
|
| 260 |
+
|
| 261 |
+
<Warning>
|
| 262 |
+
The `run()` method cannot be called from inside an async function because it already creates its own async event loop internally. If you attempt to call `run()` from inside an async function, you'll get an error about the event loop already running.
|
| 263 |
+
|
| 264 |
+
Always use `run_async()` inside async functions and `run()` in synchronous contexts.
|
| 265 |
+
</Warning>
|
| 266 |
+
|
| 267 |
+
Both `run()` and `run_async()` accept the same transport arguments, so all the examples above apply to both methods.
|
| 268 |
+
|
| 269 |
+
## Custom Routes
|
| 270 |
+
|
| 271 |
+
You can also add custom web routes to your FastMCP server, which will be exposed alongside the MCP endpoint. To do so, use the `@custom_route` decorator. Note that this is less flexible than using a full ASGI framework, but can be useful for adding simple endpoints like health checks to your standalone server.
|
| 272 |
+
|
| 273 |
+
```python
|
| 274 |
+
from fastmcp import FastMCP
|
| 275 |
+
from starlette.requests import Request
|
| 276 |
+
from starlette.responses import PlainTextResponse
|
| 277 |
+
|
| 278 |
+
mcp = FastMCP("MyServer")
|
| 279 |
+
|
| 280 |
+
@mcp.custom_route("/health", methods=["GET"])
|
| 281 |
+
async def health_check(request: Request) -> PlainTextResponse:
|
| 282 |
+
return PlainTextResponse("OK")
|
| 283 |
+
|
| 284 |
+
if __name__ == "__main__":
|
| 285 |
+
mcp.run()
|
| 286 |
+
```
|