Skip to content

Commit 46f4d87

Browse files
committed
Expose fastapi-mcp
1 parent 987d7b1 commit 46f4d87

File tree

3 files changed

+52
-36
lines changed

3 files changed

+52
-36
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Python Workers: FastMCP Example
1+
# Python Workers: FastAPI-MCP Example
22

3-
This is an example of a Python Worker that uses the FastMCP package.
3+
This is an example of a Python Worker that uses the FastAPI-MCP package.
44

55
## Adding Packages
66

src/worker.py

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,55 @@
44

55
class FastMCPServer(DurableObject):
66
def __init__(self, state, env):
7+
from fastapi import FastAPI, Request
8+
from pydantic import BaseModel
9+
from fastapi_mcp import FastApiMCP
710
from exceptions import HTTPException, http_exception
8-
from mcp.server.fastmcp import FastMCP
9-
self.state = state
10-
mcp = FastMCP("Demo")
11-
12-
@mcp.tool()
13-
def add(a: int, b: int) -> int:
14-
"""Add two numbers"""
15-
return a + b
16-
17-
@mcp.resource("greeting://{name}")
18-
def get_greeting(name: str) -> str:
19-
"""Get a personalized greeting"""
20-
return f"Hello, {name}!"
21-
22-
@mcp.tool()
23-
def calculate_bmi(weight_kg: float, height_m: float) -> float:
24-
"""Calculate BMI given weight in kg and height in meters"""
25-
return weight_kg / (height_m**2)
26-
27-
@mcp.prompt()
28-
def echo_prompt(message: str) -> str:
29-
"""Create an echo prompt"""
30-
return f"Please process this message: {message}"
31-
32-
# mcp depends on uvicorn and imports it at the top scope that we have to patch that to move the
33-
# import into the function that uses it.
34-
# TODO(now): Change uvicorn to optional in mcp
35-
app = mcp.sse_app()
36-
# Starlette default http exception handler is sync which starlette tries to run in threadpool
37-
# in https://github.com/encode/starlette/blob/master/starlette/_exception_handler.py#L61.
38-
# Since we don't support threads we need to override it with the same function but async.
39-
# TODO(now): change starlette's http_exception to be async, it is strictly slower to spawn a new
40-
# thread
11+
12+
app = FastAPI()
4113
app.add_exception_handler(HTTPException, http_exception)
14+
15+
mcp = FastApiMCP(
16+
app,
17+
# Optional parameters
18+
name="My API MCP",
19+
description="My API description",
20+
)
21+
22+
# Mount the MCP server directly to your FastAPI app
23+
mcp.mount()
24+
# Auto-generated operation_id (something like "read_user_users__user_id__get")
25+
@app.get("/")
26+
async def root():
27+
return {"message": "Hello, World!"}
28+
29+
@app.get("/env")
30+
async def root(req: Request):
31+
env = req.scope["env"]
32+
return {"message": "Here is an example of getting an environment variable: " + env.MESSAGE}
33+
34+
class Item(BaseModel):
35+
name: str
36+
description: str | None = None
37+
price: float
38+
tax: float | None = None
39+
40+
@app.post("/items/")
41+
async def create_item(item: Item):
42+
return item
43+
44+
@app.put("/items/{item_id}")
45+
async def create_item(item_id: int, item: Item, q: str | None = None):
46+
result = {"item_id": item_id, **item.dict()}
47+
if q:
48+
result.update({"q": q})
49+
return result
50+
51+
@app.get("/items/{item_id}")
52+
async def read_item(item_id: int):
53+
return {"item_id": item_id}
54+
55+
mcp.setup_server()
4256
self.mcp = mcp
4357
self.app = app
4458

vendor.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
mcp
1+
fastapi-mcp
2+
fastapi
3+
pydantic

0 commit comments

Comments
 (0)