mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-21 04:54:17 +02:00
Merge pull request #184 from jlowin/docs
Improve integration documentation
This commit is contained in:
commit
08c40e7d67
5 changed files with 221 additions and 233 deletions
|
|
@ -1,114 +1,120 @@
|
|||
---
|
||||
title: FastAPI Integration
|
||||
sidebarTitle: FastAPI
|
||||
description: Automatically create FastMCP servers directly from FastAPI applications.
|
||||
description: Generate MCP servers from FastAPI apps
|
||||
icon: square-bolt
|
||||
---
|
||||
|
||||
If you build your APIs using the popular [FastAPI](https://fastapi.tiangolo.com/) framework, FastMCP offers a seamless way to expose your FastAPI application as an MCP server. This leverages the OpenAPI integration internally but simplifies the setup significantly.
|
||||
|
||||
## The Goal: FastAPI App -> MCP Server
|
||||
FastMCP can automatically convert FastAPI applications into MCP servers.
|
||||
|
||||
FastAPI automatically generates an OpenAPI specification for your application. FastMCP uses this built-in capability to create an MCP server that mirrors your API routes.
|
||||
<Tip>
|
||||
FastMCP does *not* include FastAPI as a dependency; you must install it separately to run these examples.
|
||||
</Tip>
|
||||
|
||||
- FastAPI path operations (`@app.get`, `@app.post`, etc.) become MCP tools, resources, or templates.
|
||||
- Pydantic models used in FastAPI for request/response validation are used to generate MCP schemas.
|
||||
- Communication happens directly in memory, making it very efficient.
|
||||
|
||||
## Creating from FastAPI App
|
||||
```python {2, 22, 25}
|
||||
from fastapi import FastAPI
|
||||
from fastmcp import FastMCP
|
||||
|
||||
Use the `FastMCP.from_fastapi()` class method. You only need your FastAPI `app` instance.
|
||||
|
||||
# A FastAPI app
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/items")
|
||||
def list_items():
|
||||
return [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}]
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def get_item(item_id: int):
|
||||
return {"id": item_id, "name": f"Item {item_id}"}
|
||||
|
||||
@app.post("/items")
|
||||
def create_item(name: str):
|
||||
return {"id": 3, "name": name}
|
||||
|
||||
|
||||
# Create an MCP server from your FastAPI app
|
||||
mcp = FastMCP.from_fastapi(app=app)
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run() # Start the MCP server
|
||||
```
|
||||
|
||||
## Route Mapping
|
||||
|
||||
By default, FastMCP will map FastAPI routes to MCP components according to the following rules:
|
||||
|
||||
| FastAPI Route Type | FastAPI Example | MCP Component | Notes |
|
||||
|--------------------|--------------|---------|-------|
|
||||
| GET without path params | `@app.get("/stats")` | Resource | Simple resources for fetching data |
|
||||
| GET with path params | `@app.get("/users/{id}")` | Resource Template | Path parameters become template parameters |
|
||||
| POST, PUT, DELETE, etc. | `@app.post("/users")` | Tool | Operations that modify data |
|
||||
|
||||
For more details on route mapping or custom mapping rules, see the [OpenAPI integration documentation](/patterns/openapi#route-mapping); FastMCP uses the same mapping rules for both FastAPI and OpenAPI integrations.
|
||||
|
||||
## Complete Example
|
||||
|
||||
Here's a more detailed example with a data model:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from fastapi import FastAPI
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from fastmcp import FastMCP, Client # Import FastMCP and Client
|
||||
|
||||
# 1. Define your FastAPI application
|
||||
api_app = FastAPI(title="MyFastAPIApp")
|
||||
from fastmcp import FastMCP, Client
|
||||
|
||||
# Define your Pydantic model
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: bool | None = None
|
||||
|
||||
@api_app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
# Create your FastAPI app
|
||||
app = FastAPI()
|
||||
items = {} # In-memory database
|
||||
|
||||
@api_app.get("/items/{item_id}") # -> Resource Template
|
||||
def read_item(item_id: int, q: str | None = None):
|
||||
# This will become resource://openapi/read_item_items__item_id__get/{item_id}
|
||||
return {"item_id": item_id, "q": q, "description": f"Details for item {item_id}"}
|
||||
@app.get("/items")
|
||||
def list_items():
|
||||
"""List all items"""
|
||||
return list(items.values())
|
||||
|
||||
@api_app.post("/items/") # -> Tool
|
||||
@app.get("/items/{item_id}")
|
||||
def get_item(item_id: int):
|
||||
"""Get item by ID"""
|
||||
if item_id not in items:
|
||||
raise HTTPException(404, "Item not found")
|
||||
return items[item_id]
|
||||
|
||||
@app.post("/items")
|
||||
def create_item(item: Item):
|
||||
# This will become the 'create_item_items__post' tool
|
||||
print(f"Creating item: {item.name}")
|
||||
return {"item_name": item.name, "status": "created"}
|
||||
"""Create a new item"""
|
||||
item_id = len(items) + 1
|
||||
items[item_id] = {"id": item_id, **item.model_dump()}
|
||||
return items[item_id]
|
||||
|
||||
# 2. Create the FastMCP server directly from the FastAPI app
|
||||
# This is an async class method
|
||||
async def create_mcp_server_from_fastapi():
|
||||
mcp_server = await FastMCP.from_fastapi(
|
||||
app=api_app,
|
||||
name="FastAPI_MCP_Bridge" # Optional name for the MCP server
|
||||
)
|
||||
return mcp_server
|
||||
|
||||
# 3. (Example) Run the MCP server and test with an in-memory client
|
||||
async def run_and_test():
|
||||
server = await create_mcp_server_from_fastapi()
|
||||
print(f"Created MCP server '{server.name}' from FastAPI app '{api_app.title}'")
|
||||
|
||||
# List discovered components
|
||||
tools = await server.list_tools()
|
||||
templates = await server.list_resource_templates()
|
||||
print("Discovered Tools:", [t.name for t in tools])
|
||||
print("Discovered Templates:", [t.uriTemplate for t in templates])
|
||||
|
||||
# Test using an in-memory client
|
||||
client = Client(server) # Uses FastMCPTransport
|
||||
async with client:
|
||||
# Call the tool derived from POST /items/
|
||||
create_result = await client.call_tool(
|
||||
"create_item_items__post",
|
||||
{"name": "MCP Special", "price": 99.99} # Pydantic model fields become args
|
||||
)
|
||||
print("Create Item Tool Result:", create_result[0].text) # JSON string
|
||||
|
||||
# Read the resource derived from GET /items/{item_id}
|
||||
read_result = await client.read_resource(
|
||||
"resource://openapi/read_item_items__item_id__get/42" # Match template URI
|
||||
)
|
||||
print("Read Item Resource Result:", read_result[0].text) # JSON string
|
||||
|
||||
# In a real scenario, you might run the MCP server via stdio or sse
|
||||
# print("Running MCP server via stdio...")
|
||||
# server.run()
|
||||
# Test your MCP server with a client
|
||||
async def test():
|
||||
# Create MCP server from FastAPI app
|
||||
mcp = await FastMCP.from_fastapi(app=app)
|
||||
|
||||
# List the components that were created
|
||||
tools = await mcp.list_tools()
|
||||
resources = await mcp.list_resources()
|
||||
templates = await mcp.list_resource_templates()
|
||||
|
||||
print(f"Generated {len(tools)} tools")
|
||||
print(f"Generated {len(resources)} resources")
|
||||
print(f"Generated {len(templates)} templates")
|
||||
|
||||
# In a real scenario, you would run the server:
|
||||
# mcp.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Requires fastapi, uvicorn, httpx:
|
||||
# uv pip install "fastapi[all]" httpx
|
||||
try:
|
||||
asyncio.run(run_and_test())
|
||||
except ImportError as e:
|
||||
print(f"Error: {e}. Please install required packages: uv pip install \"fastapi[all]\" httpx")
|
||||
|
||||
# Example Output might include:
|
||||
# Created MCP server 'FastAPI_MCP_Bridge' from FastAPI app 'MyFastAPIApp'
|
||||
# Discovered Tools: ['read_root___get', 'create_item_items__post']
|
||||
# Discovered Templates: ['resource://openapi/read_item_items__item_id__get/{item_id}']
|
||||
# Create Item Tool Result: {"item_name": "MCP Special", "status": "created"}
|
||||
# Read Item Resource Result: {"item_id": 42, "q": null, "description": "Details for item 42"}
|
||||
asyncio.run(test())
|
||||
```
|
||||
|
||||
### How it Works Internally
|
||||
## Benefits
|
||||
|
||||
1. **OpenAPI Generation**: `from_fastapi` asks the FastAPI `app` for its OpenAPI schema dictionary (`app.openapi()`).
|
||||
2. **In-Memory Client**: It creates an `httpx.AsyncClient` configured with an `ASGITransport`. This special transport allows `httpx` to call the FastAPI application directly in memory without needing a running web server process.
|
||||
3. **OpenAPI Integration**: It calls `FastMCP.from_openapi()`, passing the generated schema and the in-memory `httpx` client.
|
||||
4. **MCP Server Creation**: The standard OpenAPI integration logic then proceeds to parse the schema and create the `Tool`, `Resource`, and `ResourceTemplate` components that wrap calls to the in-memory FastAPI app.
|
||||
|
||||
This provides a highly efficient way to expose your FastAPI logic through the MCP protocol, leveraging FastAPI's routing, dependency injection, and validation features.
|
||||
- **Leverage existing FastAPI apps** - No need to rewrite your API logic
|
||||
- **Schema reuse** - FastAPI's Pydantic models and validation are inherited
|
||||
- **Full feature support** - Works with FastAPI's authentication, dependencies, etc.
|
||||
- **ASGI transport** - Direct communication without additional HTTP overhead
|
||||
|
|
|
|||
|
|
@ -1,174 +1,153 @@
|
|||
---
|
||||
title: OpenAPI Integration
|
||||
sidebarTitle: OpenAPI
|
||||
description: Automatically create FastMCP servers from existing OpenAPI specifications.
|
||||
description: Generate MCP servers from OpenAPI specs
|
||||
icon: code-branch
|
||||
---
|
||||
|
||||
If you have existing REST APIs documented with the OpenAPI Specification (OAS), FastMCP can automatically generate MCP tools, resources, and resource templates directly from that specification. This provides a quick way to make your existing HTTP APIs accessible to MCP clients and LLMs.
|
||||
FastMCP can automatically generate an MCP server from an OpenAPI specification. Users only need to provide an OpenAPI specification (3.0 or 3.1) and an API client.
|
||||
|
||||
FastMCP supports both OpenAPI 3.0 and 3.1 specifications for maximum compatibility with existing API definitions.
|
||||
```python
|
||||
import httpx
|
||||
from fastmcp import FastMCP
|
||||
|
||||
## The Goal: API -> MCP Server
|
||||
# Create a client for your API
|
||||
api_client = httpx.AsyncClient(base_url="https://api.example.com")
|
||||
|
||||
The core idea is to map OpenAPI paths and operations (like `GET /users/{id}` or `POST /orders`) to their corresponding MCP components:
|
||||
# Load your OpenAPI spec
|
||||
spec = {...}
|
||||
|
||||
- `GET` requests often map to MCP **Resources** (for fetching single items) or **Resource Templates** (if the path has parameters).
|
||||
- `POST`, `PUT`, `PATCH`, `DELETE` requests typically map to MCP **Tools** (for actions that create or modify data).
|
||||
# Create an MCP server from your OpenAPI spec
|
||||
mcp = FastMCP.from_openapi(openapi_spec=spec, client=api_client)
|
||||
|
||||
FastMCP automates this mapping process.
|
||||
if __name__ == "__main__":
|
||||
mcp.run()
|
||||
```
|
||||
|
||||
## Creating from OpenAPI Spec
|
||||
## Route Mapping
|
||||
|
||||
Use the `FastMCP.from_openapi()` class method. You need:
|
||||
By default, OpenAPI routes are mapped to MCP components based on these rules:
|
||||
|
||||
1. The OpenAPI specification as a Python dictionary.
|
||||
2. An `httpx.AsyncClient` configured to make requests to the actual API backend.
|
||||
| OpenAPI Route | Example |MCP Component | Notes |
|
||||
|- | - | - | - |
|
||||
| `GET` without path params | `GET /stats` | Resource | Simple resources for fetching data |
|
||||
| `GET` with path params | `GET /users/{id}` | Resource Template | Path parameters become template parameters |
|
||||
| `POST`, `PUT`, `PATCH`, `DELETE`, etc. | `POST /users` | Tool | Operations that modify data |
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python server.py
|
||||
Internally, FastMCP uses a priority-ordered set of `RouteMap` objects to determine the component type. Route maps indicate that a specific HTTP method (or methods) and path pattern should be treated as a specific component type. This is the default set of route maps:
|
||||
|
||||
```python
|
||||
# Simplified version of the actual mapping rules
|
||||
DEFAULT_ROUTE_MAPPINGS = [
|
||||
# GET with path parameters -> ResourceTemplate
|
||||
RouteMap(methods=["GET"], pattern=r".*\{.*\}.*",
|
||||
route_type=RouteType.RESOURCE_TEMPLATE),
|
||||
|
||||
# GET without path parameters -> Resource
|
||||
RouteMap(methods=["GET"], pattern=r".*",
|
||||
route_type=RouteType.RESOURCE),
|
||||
|
||||
# All other methods -> Tool
|
||||
RouteMap(methods=["POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"],
|
||||
pattern=r".*", route_type=RouteType.TOOL),
|
||||
]
|
||||
```
|
||||
|
||||
### Custom Route Maps
|
||||
|
||||
Users can add custom route maps to override the default mapping behavior. User-supplied route maps are always applied first, before the default route maps.
|
||||
|
||||
```python
|
||||
from fastmcp.server.openapi import RouteMap, RouteType
|
||||
|
||||
# Custom mapping rules
|
||||
custom_maps = [
|
||||
# Force all analytics endpoints to be Tools
|
||||
RouteMap(methods=["GET"],
|
||||
pattern=r"^/analytics/.*",
|
||||
route_type=RouteType.TOOL)
|
||||
]
|
||||
|
||||
# Apply custom mappings
|
||||
mcp = await FastMCP.from_openapi(
|
||||
openapi_spec=spec,
|
||||
client=api_client,
|
||||
route_maps=custom_maps
|
||||
)
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
1. FastMCP parses your OpenAPI spec to extract routes and schemas
|
||||
2. It applies mapping rules to categorize each route
|
||||
3. When an MCP client calls a tool or accesses a resource:
|
||||
- FastMCP constructs an HTTP request based on the OpenAPI definition
|
||||
- It sends the request through the provided httpx client
|
||||
- It translates the HTTP response to the appropriate MCP format
|
||||
|
||||
## Complete Example
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import httpx
|
||||
from fastmcp import FastMCP
|
||||
|
||||
# load the OpenAPI specification from the openapi_spec.py file
|
||||
petstore_spec = PETSTORE_SPEC
|
||||
|
||||
# Client to communicate with the actual Pet Store API backend
|
||||
# The base_url should match the server URL in the OpenAPI spec
|
||||
http_client = httpx.AsyncClient(base_url="http://petstore.example.com/api")
|
||||
|
||||
# Create the FastMCP server from the spec
|
||||
# This is an async class method
|
||||
async def create_openapi_server():
|
||||
mcp_server = await FastMCP.from_openapi(
|
||||
openapi_spec=petstore_spec,
|
||||
client=http_client,
|
||||
name="PetStoreMCP" # Optional name for the MCP server
|
||||
)
|
||||
return mcp_server
|
||||
|
||||
async def run_server():
|
||||
server = await create_openapi_server()
|
||||
print(f"Starting OpenAPI-based server '{server.name}'...")
|
||||
|
||||
# List discovered components
|
||||
tools = await server.list_tools()
|
||||
resources = await server.list_resources()
|
||||
templates = await server.list_resource_templates()
|
||||
print("Discovered Tools:", [t.name for t in tools])
|
||||
print("Discovered Resources:", [r.uri for r in resources]) # Should be empty if no parameterless GETs
|
||||
print("Discovered Templates:", [t.uriTemplate for t in templates])
|
||||
|
||||
# Run the server (e.g., via stdio)
|
||||
# server.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example: Create the server and print discovered components
|
||||
# Requires httpx: uv pip install httpx
|
||||
asyncio.run(run_server())
|
||||
|
||||
# Expected Output might include:
|
||||
# Discovered Tools: ['listPets', 'createPet']
|
||||
# Discovered Resources: []
|
||||
# Discovered Templates: ['resource://openapi/showPetById/{petId}']
|
||||
```
|
||||
|
||||
```python openapi_spec.py
|
||||
# Example OpenAPI Specification (simplified Pet Store)
|
||||
PETSTORE_SPEC = {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "Simple Pet Store", "version": "1.0.0"},
|
||||
"servers": [{"url": "http://petstore.example.com/api"}], # Base URL for API calls
|
||||
# Sample OpenAPI spec for a Pet Store API
|
||||
petstore_spec = {
|
||||
"openapi": "3.0.0",
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"get": {
|
||||
"summary": "List all pets",
|
||||
"operationId": "listPets",
|
||||
"tags": ["pets"],
|
||||
"parameters": [{ # Query parameter -> Tool argument
|
||||
"name": "limit", "in": "query", "schema": {"type": "integer"}
|
||||
}],
|
||||
"responses": {"200": {"description": "A list of pets."}},
|
||||
"summary": "List all pets"
|
||||
},
|
||||
"post": { # POST -> Tool
|
||||
"summary": "Create a pet",
|
||||
"post": {
|
||||
"operationId": "createPet",
|
||||
"tags": ["pets"],
|
||||
"requestBody": { # Request body -> Tool arguments
|
||||
"required": True,
|
||||
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/PetInput"}}}
|
||||
},
|
||||
"responses": {"201": {"description": "Pet created."}},
|
||||
},
|
||||
"summary": "Create a new pet"
|
||||
}
|
||||
},
|
||||
"/pets/{petId}": { # Path parameter -> Resource Template
|
||||
"get": { # GET with path param -> Resource Template / FunctionResource
|
||||
"summary": "Info for a specific pet",
|
||||
"operationId": "showPetById",
|
||||
"tags": ["pets"],
|
||||
"parameters": [{ # Path parameter -> Template function argument
|
||||
"name": "petId", "in": "path", "required": True, "schema": {"type": "string"}
|
||||
}],
|
||||
"responses": {"200": {"description": "Information about the pet."}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"PetInput": {"type": "object", "properties": {"name": {"type": "string"}, "tag": {"type": "string"}}},
|
||||
"/pets/{petId}": {
|
||||
"get": {
|
||||
"operationId": "getPet",
|
||||
"summary": "Get a pet by ID",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "petId",
|
||||
"in": "path",
|
||||
"required": True,
|
||||
"schema": {"type": "string"}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### How it Works Internally
|
||||
|
||||
1. **Parsing**: `from_openapi` parses the spec using utilities that leverage `openapi-pydantic`. It extracts paths, operations, parameters, request bodies, and responses.
|
||||
2. **Mapping**: It applies mapping rules (see below) to decide whether each OpenAPI operation (`GET /pets`, `POST /pets`, `GET /pets/{petId}`) becomes an MCP `Tool`, `Resource`, or `ResourceTemplate`.
|
||||
3. **Component Creation**: It creates specialized internal components (`OpenAPITool`, `OpenAPIResource`, `OpenAPIResourceTemplate`).
|
||||
4. **HTTP Execution**: When an MCP client calls a tool or reads a resource from this server:
|
||||
* The corresponding OpenAPI component constructs an HTTP request based on the OpenAPI definition and the arguments provided by the MCP client.
|
||||
* It uses the provided `httpx.AsyncClient` to send the request to the backend API.
|
||||
* It processes the HTTP response and returns it to the MCP client in the appropriate MCP format.
|
||||
5. **Schema Generation**: The schemas for MCP tools are derived by combining OpenAPI parameters (path, query, header) and request body schemas. Resource template function arguments are derived from path parameters.
|
||||
6. **Descriptions**: Tool/Resource descriptions are enhanced with information from OpenAPI responses to give the LLM more context about potential outcomes.
|
||||
|
||||
### Default Mapping Rules
|
||||
|
||||
FastMCP uses the following default rules to map OpenAPI operations:
|
||||
|
||||
- `GET` operation with path parameters (e.g., `/users/{id}`) -> **`ResourceTemplate`**
|
||||
- `GET` operation without path parameters (e.g., `/users`) -> **`Resource`**
|
||||
- `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`, `HEAD` -> **`Tool`**
|
||||
|
||||
### Customize Route Mapping
|
||||
|
||||
You can customize the mapping rules by providing a list of `RouteMap` objects directly to `FastMCP.from_openapi()` using the `route_maps` parameter:
|
||||
|
||||
```python
|
||||
from fastmcp.server.openapi import RouteMap, RouteType
|
||||
from fastmcp import FastMCP
|
||||
|
||||
# Custom mapping: Treat GET /admin/stats as a Tool, not a Resource
|
||||
custom_maps = [
|
||||
RouteMap(methods=["GET"], pattern=r"^/admin/stats$", route_type=RouteType.TOOL)
|
||||
]
|
||||
|
||||
async def create_server_with_custom_mapping():
|
||||
mcp_server = await FastMCP.from_openapi(
|
||||
async def main():
|
||||
# Client for the Pet Store API
|
||||
client = httpx.AsyncClient(base_url="https://petstore.example.com/api")
|
||||
|
||||
# Create the MCP server
|
||||
mcp = await FastMCP.from_openapi(
|
||||
openapi_spec=petstore_spec,
|
||||
client=http_client,
|
||||
name="PetStoreMCP",
|
||||
route_maps=custom_maps # Pass custom mapping rules
|
||||
client=client,
|
||||
name="PetStore"
|
||||
)
|
||||
return mcp_server
|
||||
|
||||
# List what components were created
|
||||
tools = await mcp.list_tools()
|
||||
resources = await mcp.list_resources()
|
||||
templates = await mcp.list_resource_templates()
|
||||
|
||||
print(f"Tools: {len(tools)}") # Should include createPet
|
||||
print(f"Resources: {len(resources)}") # Should include listPets
|
||||
print(f"Templates: {len(templates)}") # Should include getPet
|
||||
|
||||
# Start the MCP server
|
||||
mcp.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
Each `RouteMap` maps one or more HTTP methods and a regular expression pattern for the route path to an MCP `RouteType`. Route maps are processed in order, and the first match wins.
|
||||
|
||||
All parameters passed to `FastMCP.from_openapi()` will be forwarded to the underlying `FastMCPOpenAPI` constructor, so you can customize any aspect of the OpenAPI integration directly through this method call.
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ description = "The fast, Pythonic way to build MCP servers."
|
|||
authors = [{ name = "Jeremiah Lowin" }]
|
||||
dependencies = [
|
||||
"dotenv>=0.9.9",
|
||||
"exceptiongroup>=1.2.2",
|
||||
"httpx>=0.28.1",
|
||||
"mcp>=1.6.0,<2.0.0",
|
||||
"openapi-pydantic>=0.5.1",
|
||||
"rich>=13.9.4",
|
||||
"typer>=0.15.2",
|
||||
"websockets>=15.0.1",
|
||||
"fastapi>=0.115.12",
|
||||
"openapi-pydantic>=0.5.1",
|
||||
"exceptiongroup>=1.2.2",
|
||||
]
|
||||
requires-python = ">=3.10"
|
||||
readme = "README.md"
|
||||
|
|
@ -38,6 +38,11 @@ classifiers = [
|
|||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"copychat>=0.5.2",
|
||||
"dirty-equals>=0.9.0",
|
||||
"fastapi>=0.115.12",
|
||||
"ipython>=8.12.3",
|
||||
"pdbpp>=0.10.3",
|
||||
"pre-commit",
|
||||
"pyright>=1.1.389",
|
||||
"pytest>=8.3.3",
|
||||
|
|
@ -45,10 +50,6 @@ dev = [
|
|||
"pytest-flakefinder",
|
||||
"pytest-xdist>=3.6.1",
|
||||
"ruff",
|
||||
"copychat>=0.5.2",
|
||||
"ipython>=8.12.3",
|
||||
"pdbpp>=0.10.3",
|
||||
"dirty-equals>=0.9.0",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import anyio
|
|||
import httpx
|
||||
import pydantic_core
|
||||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from mcp.server.lowlevel.helper_types import ReadResourceContents
|
||||
from mcp.server.lowlevel.server import LifespanResultT
|
||||
from mcp.server.lowlevel.server import Server as MCPServer
|
||||
|
|
@ -846,11 +845,12 @@ class FastMCP(Generic[LifespanResultT]):
|
|||
|
||||
@classmethod
|
||||
def from_fastapi(
|
||||
cls, app: FastAPI, name: str | None = None, **settings: Any
|
||||
cls, app: "Any", name: str | None = None, **settings: Any
|
||||
) -> "FastMCPOpenAPI":
|
||||
"""
|
||||
Create a FastMCP server from a FastAPI application.
|
||||
"""
|
||||
|
||||
from .openapi import FastMCPOpenAPI
|
||||
|
||||
client = httpx.AsyncClient(
|
||||
|
|
|
|||
8
uv.lock
generated
8
uv.lock
generated
|
|
@ -254,12 +254,12 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "fastmcp"
|
||||
version = "2.1.3.dev31+8d922d9"
|
||||
version = "2.1.3.dev42+be2ccc6"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "dotenv" },
|
||||
{ name = "exceptiongroup" },
|
||||
{ name = "fastapi" },
|
||||
{ name = "httpx" },
|
||||
{ name = "mcp" },
|
||||
{ name = "openapi-pydantic" },
|
||||
{ name = "rich" },
|
||||
|
|
@ -271,6 +271,7 @@ dependencies = [
|
|||
dev = [
|
||||
{ name = "copychat" },
|
||||
{ name = "dirty-equals" },
|
||||
{ name = "fastapi" },
|
||||
{ name = "ipython" },
|
||||
{ name = "pdbpp" },
|
||||
{ name = "pre-commit" },
|
||||
|
|
@ -286,7 +287,7 @@ dev = [
|
|||
requires-dist = [
|
||||
{ name = "dotenv", specifier = ">=0.9.9" },
|
||||
{ name = "exceptiongroup", specifier = ">=1.2.2" },
|
||||
{ name = "fastapi", specifier = ">=0.115.12" },
|
||||
{ name = "httpx", specifier = ">=0.28.1" },
|
||||
{ name = "mcp", specifier = ">=1.6.0,<2.0.0" },
|
||||
{ name = "openapi-pydantic", specifier = ">=0.5.1" },
|
||||
{ name = "rich", specifier = ">=13.9.4" },
|
||||
|
|
@ -298,6 +299,7 @@ requires-dist = [
|
|||
dev = [
|
||||
{ name = "copychat", specifier = ">=0.5.2" },
|
||||
{ name = "dirty-equals", specifier = ">=0.9.0" },
|
||||
{ name = "fastapi", specifier = ">=0.115.12" },
|
||||
{ name = "ipython", specifier = ">=8.12.3" },
|
||||
{ name = "pdbpp", specifier = ">=0.10.3" },
|
||||
{ name = "pre-commit" },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue