FastAPI-MCP实战案例:从简单应用到复杂业务场景
本文通过完整的实战案例,详细展示了如何将FastAPI应用无缝集成到MCP生态系统中。从基础的CRUD应用到复杂的业务逻辑处理,涵盖了商品管理、订单处理、搜索过滤等核心业务场景。文章将深入探讨FastAPI-MCP的自动工具生成机制、错误处理最佳实践以及复杂业务端点的智能转换策略,为开发者提供从入门到精通的完整指南。
基础CRUD应用的MCP集成示例
在现代应用开发中,CRUD(创建、读取、更新、删除)操作是最基础也是最核心的功能。通过FastAPI-MCP,我们可以将这些基础的API端点无缝转换为MCP工具,让AI助手能够直接与我们的业务逻辑进行交互。本节将详细演示如何将一个完整的商品管理CRUD应用集成到MCP生态系统中。
项目结构与核心模型设计
首先,我们定义一个标准的商品数据模型,这是整个CRUD应用的基础:
from fastapi import FastAPI, HTTPException, Query
from pydantic import BaseModel
from typing import List, Optional
class Item(BaseModel):
id: int
name: str
description: Optional[str] = None
price: float
tags: List[str] = []
# 内存数据库模拟
items_db: dict[int, Item] = {}
这个Item模型包含了商品的核心属性:唯一标识符、名称、描述、价格和标签。我们使用内存字典来模拟数据库存储,便于演示。
完整的CRUD端点实现
接下来,我们实现标准的RESTful API端点,每个端点都包含详细的文档和参数验证:
@app.get("/items/", response_model=List[Item], tags=["items"], operation_id="list_items")
async def list_items(skip: int = 0, limit: int = 10):
"""列出数据库中的所有商品,支持分页功能"""
return list(items_db.values())[skip : skip + limit]
@app.get("/items/{item_id}", response_model=Item, tags=["items"], operation_id="get_item")
async def read_item(item_id: int):
"""根据ID获取特定商品的详细信息"""
if item_id not in items_db:
raise HTTPException(status_code=404, detail="商品不存在")
return items_db[item_id]
@app.post("/items/", response_model=Item, tags=["items"], operation_id="create_item")
async def create_item(item: Item):
"""创建新商品并保存到数据库"""
items_db[item.id] = item
return item
@app.put("/items/{item_id}", response_model=Item, tags=["items"], operation_id="update_item")
async def update_item(item_id: int, item: Item):
"""更新现有商品的信息"""
if item_id not in items_db:
raise HTTPException(status_code=404, detail="商品不存在")
item.id = item_id
items_db[item_id] = item
return item
@app.delete("/items/{item_id}", tags=["items"], operation_id="delete_item")
async def delete_item(item_id: int):
"""从数据库中删除指定商品"""
if item_id not in items_db:
raise HTTPException(status_code=404, detail="商品不存在")
del items_db[item_id]
return {"message": "商品删除成功"}
高级搜索功能实现
除了基本的CRUD操作,我们还提供了强大的搜索功能,支持多条件过滤:
@app.get("/items/search/", response_model=List[Item], tags=["search"], operation_id="search_items")
async def search_items(
q: Optional[str] = Query(None, description="搜索关键词"),
min_price: Optional[float] = Query(None, description="最低价格"),
max_price: Optional[float] = Query(None, description="最高价格"),
tags: List[str] = Query([], description="按标签过滤"),
):
"""根据多种条件搜索商品"""
results = list(items_db.values())
# 关键词搜索(名称和描述)
if q:
q = q.lower()
results = [
item for item in results
if q in item.name.lower() or (item.description and q in item.description.lower())
]
# 价格范围过滤
if min_price is not None:
results = [item for item in results if item.price >= min_price]
if max_price is not None:
results = [item for item in results if item.price <= max_price]
# 标签过滤
if tags:
results = [item for item in results if all(tag in item.tags for tag in tags)]
return results
MCP集成配置与部署
将FastAPI应用转换为MCP服务器的过程极其简单,只需几行代码:
from fastapi_mcp import FastApiMCP
# 创建FastAPI应用实例
app = FastAPI()
# 初始化MCP服务器
mcp = FastApiMCP(app)
# 挂载MCP端点
mcp.mount_http()
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
MCP工具自动生成机制
FastAPI-MCP会自动分析你的API端点并生成对应的MCP工具。以下是生成的MCP工具结构:
生成的MCP工具包含完整的类型信息和文档:
| 工具名称 | 对应端点 | 功能描述 |
|---|---|---|
| list_items | GET /items/ | 列出所有商品,支持分页 |
| get_item | GET /items/{item_id} | 获取特定商品详情 |
| create_item | POST /items/ | 创建新商品 |
| update_item | PUT /items/{item_id} | 更新商品信息 |
| delete_item | DELETE /items/{item_id} | 删除商品 |
| search_items | GET /items/search/ | 多条件搜索商品 |
示例数据初始化
为了演示效果,我们在应用启动时预加载一些示例数据:
sample_items = [
Item(id=1, name="锤子", description="用于敲钉子的工具", price=9.99, tags=["工具", "五金"]),
Item(id=2, name="螺丝刀", description="用于拧螺丝的工具", price=7.99, tags=["工具", "五金"]),
Item(id=3, name="扳手", description="用于拧螺栓的工具", price=12.99, tags=["工具", "五金"]),
Item(id=4, name="锯子", description="用于切割木材的工具", price=19.99, tags=["工具", "五金", "切割"]),
Item(id=5, name="电钻", description="用于钻孔的工具", price=49.99, tags=["工具", "五金", "电动"]),
]
for item in sample_items:
items_db[item.id] = item
MCP工具调用示例
集成完成后,AI助手可以通过MCP协议直接调用这些工具:
# MCP客户端调用示例
response = await mcp_client.call_tool("search_items", {
"q": "电动工具",
"min_price": 10.0,
"max_price": 100.0,
"tags": ["电动"]
})
完整的应用启动流程
通过这个完整的CRUD应用示例,我们可以看到FastAPI-MCP如何将传统的RESTful API无缝转换为MCP工具,使得AI助手能够以结构化的方式与业务系统进行交互。这种集成方式不仅保持了API的完整性和一致性,还为AI应用提供了强大的业务能力支持。
搜索与过滤功能的工具化实现
在现代API开发中,搜索和过滤功能是几乎所有业务系统的核心需求。通过FastAPI-MCP,我们可以将这些功能无缝地转换为MCP工具,让AI助手能够直接调用这些强大的搜索能力。本节将深入探讨如何将复杂的搜索与过滤逻辑工具化,并充分利用FastAPI-MCP的过滤机制来优化工具暴露策略。
搜索API端点的设计与实现
首先,让我们看一个典型的搜索端点实现。这个端点支持多种过滤条件,包括关键字搜索、价格范围过滤和标签过滤:
@app.get("/items/search/", response_model=List[Item], tags=["search"], operation_id="search_items")
async def search_items(
q: Optional[str] = Query(None, description="搜索查询字符串"),
min_price: Optional[float] = Query(None, description="最低价格"),
max_price: Optional[float] = Query(None, description="最高价格"),
tags: List[str] = Query([], description="按标签过滤"),
):
"""
使用各种过滤器搜索物品。
返回符合搜索条件的物品列表。
"""
results = list(items_db.values())
if q:
q = q.lower()
results = [
item for item in results if q in item.name.lower() or (item.description and q in item.description.lower())
]
if min_price is not None:
results = [item for item in results if item.price >= min_price]
if max_price is not None:
results = [item for item in results if item.price <= max_price]
if tags:
results = [item for item in results if all(tag in item.tags for tag in tags)]
return results
这个搜索端点提供了丰富的过滤能力,包括:
- 关键字搜索:在名称和描述中搜索
- 价格范围过滤:支持最小和最大价格限制
- 多标签过滤:支持同时按多个标签进行过滤
MCP工具转换机制
FastAPI-MCP通过分析OpenAPI schema自动将这个搜索端点转换为MCP工具。转换过程遵循以下流程:
转换后的MCP工具将包含完整的参数信息和文档描述,使得AI助手能够理解如何使用这个搜索功能。
灵活的过滤策略配置
FastAPI-MCP提供了多种过滤策略来控制哪些端点被暴露为MCP工具:
1. 按操作ID过滤
# 只包含特定的搜索操作
search_only_mcp = FastApiMCP(
app,
name="搜索专用MCP",
include_operations=["search_items"]
)
# 排除管理操作,只保留查询功能
query_only_mcp = FastApiMCP(
app,
name="查询专用MCP",
exclude_operations=["create_item", "update_item", "delete_item"]
)
2. 按标签过滤
# 只包含搜索相关的端点
search_mcp = FastApiMCP(
app,
name="搜索服务MCP",
include_tags=["search"]
)
# 排除搜索功能,专注于数据管理
management_mcp = FastApiMCP(
app,
name="管理服务MCP",
exclude_tags=["search"]
)
3. 组合过滤策略
# 组合操作ID和标签过滤
combined_mcp = FastApiMCP(
app,
name="综合搜索MCP",
include_operations=["search_items"],
include_tags=["search"]
)
过滤策略的优先级规则
FastAPI-MCP的过滤机制遵循明确的优先级规则:
表格总结了不同过滤模式的组合效果:
| 过滤模式 | 操作ID过滤 | 标签过滤 | 最终结果 |
|---|---|---|---|
| 包含模式 | 包含A,B | 包含X,Y | A∪B∪X∪Y |
| 排除模式 | 排除C,D | 排除Z | 所有-(C∪D∪Z) |
| 混合模式 | 包含A,B | 排除Z | (A∪B)-Z |
实际应用场景
场景1:专用搜索服务
# 创建专门的搜索MCP服务
search_service = FastApiMCP(
app,
name="智能搜索助手",
include_tags=["search"],
description="专为搜索功能优化的MCP服务"
)
search_service.mount_http(mount_path="/search-mcp")
场景2:权限分离的服务
# 为不同用户角色创建不同的MCP服务
user_mcp = FastApiMCP(
app,
name="用户查询服务",
include_operations=["list_items", "get_item", "search_items"]
)
admin_mcp = FastApiMCP(
app,
name="管理服务",
exclude_operations=["search_items"] # 管理员不需要搜索功能
)
场景3:功能模块化
# 按功能模块创建独立的MCP服务
search_module = FastApiMCP(app, include_tags=["search"])
crud_module = FastApiMCP(app, include_tags=["items"])
analytics_module = FastApiMCP(app, include_operations=["get_analytics"])
最佳实践建议
- 明确的标签策略:为端点定义清晰的标签,便于后续的过滤管理
- 有意义的操作ID:使用描述性的操作ID,便于识别和过滤
- 渐进式暴露:开始时暴露较少的工具,根据需要逐步增加
- 文档完整性:确保每个端点的文档描述完整准确,便于AI助手理解
- 测试验证:创建不同的过滤配置并进行测试,确保符合预期
通过合理的过滤策略配置,我们可以创建高度专业化的MCP服务,每个服务都专注于特定的功能领域,为AI助手提供最合适的工具集。这种模块化的方法不仅提高了工具的可发现性,还增强了系统的安全性和可维护性。
复杂业务逻辑的端点转换
在FastAPI-MCP的实际应用中,我们经常会遇到包含复杂业务逻辑的端点。这些端点可能涉及多个数据模型、复杂的验证逻辑、数据库事务处理以及与其他服务的集成。FastAPI-MCP能够智能地将这些复杂的业务端点转换为MCP工具,同时保持原有的业务逻辑完整性。
复杂业务场景的端点设计
让我们通过一个电商订单处理的复杂示例来展示FastAPI-MCP如何处理复杂业务逻辑的转换:
from fastapi import FastAPI, HTTPException, Depends, BackgroundTasks
from pydantic import BaseModel, Field, validator
from typing import List, Optional, Dict, Any
from datetime import datetime
from enum import Enum
import uuid
app = FastAPI()
class OrderStatus(str, Enum):
PENDING = "pending"
CONFIRMED = "confirmed"
PROCESSING = "processing"
SHIPPED = "shipped"
DELIVERED = "delivered"
CANCELLED = "cancelled"
class Address(BaseModel):
street: str = Field(..., description="Street address")
city: str = Field(..., description="City")
state: str = Field(..., description="State/Province")
zip_code: str = Field(..., description="Postal/ZIP code")
country: str = Field(..., description="Country")
class OrderItem(BaseModel):
product_id: int = Field(..., description="Product ID")
quantity: int = Field(..., description="Quantity", gt=0)
unit_price: float = Field(..., description="Unit price", gt=0)
@validator('quantity')
def validate_quantity(cls, v):
if v <= 0:
raise ValueError('Quantity must be greater than 0')
return v
class PaymentMethod(str, Enum):
CREDIT_CARD = "credit_card"
DEBIT_CARD = "debit_card"
PAYPAL = "paypal"
BANK_TRANSFER = "bank_transfer"
class CreateOrderRequest(BaseModel):
customer_id: int = Field(..., description="Customer ID")
items: List[OrderItem] = Field(..., description="Order items")
shipping_address: Address = Field(..., description="Shipping address")
payment_method: PaymentMethod = Field(..., description="Payment method")
discount_code: Optional[str] = Field(None, description="Discount code")
@validator('items')
def validate_items(cls, v):
if not v:
raise ValueError('Order must contain at least one item')
return v
class OrderResponse(BaseModel):
order_id: str = Field(..., description="Order ID")
customer_id: int = Field(..., description="Customer ID")
status: OrderStatus = Field(..., description="Order status")
total_amount: float = Field(..., description="Total amount")
created_at: datetime = Field(..., description="Creation timestamp")
items: List[OrderItem] = Field(..., description="Order items")
shipping_address: Address = Field(..., description="Shipping address")
# 模拟数据库
orders_db: Dict[str, Dict] = {}
inventory_db: Dict[int, int] = {1: 100, 2: 50, 3: 75, 4: 30, 5: 60}
@app.post("/orders/",
response_model=OrderResponse,
tags=["orders"],
operation_id="create_order",
summary="Create a new order with complex validation")
async def create_order(
order_request: CreateOrderRequest,
background_tasks: BackgroundTasks
):
"""
Create a new order with comprehensive validation and processing.
This endpoint handles:
- Inventory validation
- Price calculation
- Payment method validation
- Order status management
- Background task scheduling
Returns the created order with complete details.
"""
# 验证库存
for item in order_request.items:
if item.product_id not in inventory_db:
raise HTTPException(status_code=400, detail=f"Product {item.product_id} not found")
if inventory_db[item.product_id] < item.quantity:
raise HTTPException(
status_code=400,
detail=f"Insufficient inventory for product {item.product_id}"
)
# 计算总金额
total_amount = sum(item.quantity * item.unit_price for item in order_request.items)
# 应用折扣(如果有)
if order_request.discount_code == "SUMMER2024":
total_amount *= 0.9 # 10% 折扣
# 创建订单
order_id = str(uuid.uuid4())
order_data = {
"order_id": order_id,
"customer_id": order_request.customer_id,
"status": OrderStatus.PENDING,
"total_amount": total_amount,
"created_at": datetime.now(),
"items": [item.dict() for item in order_request.items],
"shipping_address": order_request.shipping_address.dict(),
"payment_method": order_request.payment_method
}
orders_db[order_id] = order_data
# 安排后台任务处理支付和库存更新
background_tasks.add_task(process_order_payment, order_id)
background_tasks.add_task(update_inventory, order_request.items)
return OrderResponse(**order_data)
@app.put("/orders/{order_id}/status",
response_model=OrderResponse,
tags=["orders"],
operation_id="update_order_status",
summary="Update order status with state transition validation")
async def update_order_status(
order_id: str,
new_status: OrderStatus,
notes: Optional[str] = None
):
"""
Update order status with proper state transition validation.
Valid state transitions:
- pending → confirmed
- confirmed → processing
- processing → shipped
- shipped → delivered
- any → cancelled (with restrictions)
Returns the updated order.
"""
if order_id not in orders_db:
raise HTTPException(status_code=404, detail="Order not found")
current_status = orders_db[order_id]["status"]
# 验证状态转换
valid_transitions = {
OrderStatus.PENDING: [OrderStatus.CONFIRMED, OrderStatus.CANCELLED],
OrderStatus.CONFIRMED: [OrderStatus.PROCESSING, OrderStatus.CANCELLED],
OrderStatus.PROCESSING: [OrderStatus.SHIPPED, OrderStatus.CANCELLED],
OrderStatus.SHIPPED: [OrderStatus.DELIVERED],
OrderStatus.DELIVERED: [],
OrderStatus.CANCELLED: []
}
if new_status not in valid_transitions[current_status]:
raise HTTPException(
status_code=400,
detail=f"Invalid status transition from {current_status} to {new_status}"
)
# 更新状态
orders_db[order_id]["status"] = new_status
if notes:
orders_db[order_id].setdefault("notes", []).append({
"timestamp": datetime.now(),
"status": new_status,
"message": notes
})
return OrderResponse(**orders_db[order_id])
@app.get("/orders/customer/{customer_id}",
response_model=List[OrderResponse],
tags=["orders"],
operation_id="get_customer_orders",
summary="Get all orders for a specific customer with filtering")
async def get_customer_orders(
customer_id: int,
status: Optional[OrderStatus] = None,
start_date: Optional[datetime] = None,
end_date: Optional[datetime] = None,
limit: int = 50,
offset: int = 0
):
"""
Retrieve orders for a specific customer with advanced filtering options.
Supports filtering by:
- Order status
- Date range
- Pagination
Returns a list of matching orders.
"""
customer_orders = [
order for order in orders_db.values()
if order["customer_id"] == customer_id
]
# 应用过滤器
if status:
customer_orders = [order for order in customer_orders if order["status"] == status]
if start_date:
customer_orders = [order for order in customer_orders if order["created_at"] >= start_date]
if end_date:
customer_orders = [order for order in customer_orders if order["created_at"] <= end_date]
# 应用分页
paginated_orders = customer_orders[offset:offset + limit]
return [OrderResponse(**order) for order in paginated_orders]
# 后台任务函数
async def process_order_payment(order_id: str):
"""模拟支付处理"""
# 这里会有实际的支付网关集成
await asyncio.sleep(2) # 模拟支付处理时间
orders_db[order_id]["status"] = OrderStatus.CONFIRMED
async def update_inventory(items: List[OrderItem]):
"""更新库存"""
for item in items:
inventory_db[item.product_id] -= item.quantity
FastAPI-MCP的智能转换机制
FastAPI-MCP能够智能地处理这种复杂的业务端点,将其转换为MCP工具。转换过程遵循以下逻辑:
复杂端点的MCP工具转换结果
对于上述复杂订单处理端点,FastAPI-MCP会生成以下MCP工具:
| 工具名称 | 描述 | 输入参数 | 输出结构 |
|---|---|---|---|
create_order | 创建新订单并进行复杂验证 | customer_id, items[], shipping_address{}, payment_method, discount_code? | order_id, status, total_amount, items[], shipping_address{} |
update_order_status | 更新订单状态并进行状态转换验证 | order_id, new_status, notes? | 完整的订单响应 |
get_customer_orders | 获取客户订单并进行高级过滤 | customer_id, status?, start_date?, end_date?, limit, offset | 订单列表 |
复杂验证逻辑的保留
FastAPI-MCP能够完整保留Pydantic模型的复杂验证逻辑:
# 转换后的MCP工具会自动包含这些验证规则
validation_rules = {
"quantity": {"type": "integer", "minimum": 1},
"unit_price": {"type": "number", "minimum": 0},
"items": {"minItems": 1},
"payment_method": {"enum": ["credit_card", "debit_card", "paypal", "bank_transfer"]}
}
状态机转换的智能处理
对于包含状态机逻辑的端点,FastAPI-MCP会生成适当的工具描述:
复杂查询参数的转换
对于包含复杂查询参数的端点,FastAPI-MCP会生成详细的参数描述:
{
"get_customer_orders": {
"parameters": {
"customer_id": {"type": "integer", "description": "Customer ID"},
"status": {
"type": "string",
"enum": ["pending", "confirmed", "processing", "shipped", "delivered", "cancelled"],
"description": "Filter by order status"
},
"start_date": {"type": "string", "format": "date-time", "description": "Start date filter"},
"end_date": {"type": "string", "format": "date-time", "description": "End date filter"},
"limit": {"type": "integer", "default": 50, "description": "Pagination limit"},
"offset": {"type": "integer", "default": 0, "description": "Pagination offset"}
}
}
}
实际使用示例
通过FastAPI-MCP转换后,AI助手可以直接使用这些复杂的业务工具:
# AI助手使用转换后的MCP工具
result = await mcp_client.call_tool("create_order", {
"customer_id": 123,
"items": [
{"product_id": 1, "quantity": 2, "unit_price": 9.99},
{"product_id": 3, "quantity": 1, "unit_price": 12.99}
],
"shipping_address": {
"street": "123 Main St",
"city": "Anytown",
"state": "CA",
"zip_code": "12345",
"country": "USA"
},
"payment_method": "credit_card",
"discount_code": "SUMMER2024"
})
最佳实践建议
在处理复杂业务逻辑的端点转换时,建议遵循以下最佳实践:
- 明确的operation_id: 为每个复杂端点设置清晰的operation_id
- 详细的文档: 在端点文档中详细描述业务逻辑和验证规则
- 合理的错误处理: 确保HTTP异常和验证错误能够正确传递到MCP客户端
- 状态管理: 对于状态机逻辑,在文档中明确状态转换规则
- 参数验证: 充分利用Pydantic的验证功能,确保输入数据的完整性
通过这种方式,FastAPI-MCP能够将最复杂的业务端点无缝转换为MCP工具,让AI助手能够直接与您的业务系统进行深度集成。
错误处理与异常管理的最佳实践
在FastAPI-MCP项目中,错误处理与异常管理是确保系统稳定性和用户体验的关键环节。通过深入分析项目代码,我们可以总结出一套完整的错误处理最佳实践体系,涵盖了从HTTP异常处理到MCP协议错误传递的各个方面。
统一的HTTP异常处理机制
FastAPI-MCP充分利用了FastAPI原生的HTTP异常处理机制,通过标准化的HTTP状态码和错误信息来确保客户端能够准确理解错误原因:
from fastapi import HTTPException, status
# 认证失败错误
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authorization header"
)
# 服务器内部错误
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal server error"
)
# 网关错误
raise HTTPException(
status_code=status.HTTP_502_BAD_GATEWAY,
detail="Failed to fetch OAuth metadata"
)
这种处理方式确保了错误信息的标准化和可读性,客户端可以根据状态码快速判断错误类型并采取相应措施。
MCP协议错误传递机制
在MCP协议层面,FastAPI-MCP实现了完整的错误传递机制,确保MCP客户端能够接收到结构化的错误信息:
当FastAPI端点返回错误状态码时,MCP服务器会将这些错误转换为MCP协议能够理解的格式:
# 在transport/sse.py中的错误处理实现
error_data = ErrorData(
code=-32700, # JSON-RPC解析错误代码
message="Parse error",
data={"validation_error": str(message)}
)
json_rpc_error = JSONRPCError(
jsonrpc="2.0",
error=error_data
)
error_message = SessionMessage(JSONRPCMessage(root=json_rpc_error))
await writer.send(error_message)
分层错误处理架构
FastAPI-MCP采用了分层错误处理架构,不同层次的错误由相应的组件处理:
| 错误层级 | 处理组件 | 错误类型 | 处理方式 |
|---|---|---|---|
| 传输层 | Transport | 连接错误、协议错误 | 返回HTTP错误状态码 |
| MCP协议层 | Server | 工具调用错误、参数验证错误 | 返回JSON-RPC错误响应 |
| 业务层 | FastAPI端点 | 业务逻辑错误、认证错误 | 抛出HTTPException |
这种分层架构确保了错误的合理归属和处理,避免了错误处理的混乱。
异常日志记录与监控
完善的日志记录是错误处理的重要组成部分。FastAPI-MCP在各个关键位置都添加了详细的错误日志:
# 在auth/proxy.py中的错误日志记录
if response.status_code != 200:
logger.error(
f"Failed to fetch OAuth metadata from {metadata_url}: "
f"{response.status_code}. Response: {response.text}"
)
raise HTTPException(
status_code=status.HTTP_502_BAD_GATEWAY,
detail="Failed to fetch OAuth metadata"
)
# 在transport/http.py中的异常处理
try:
# 业务逻辑
except Exception as e:
logger.exception("Error in StreamableHTTP session manager")
raise HTTPException(status_code=500, detail="Internal server error")
参数验证与输入清理
FastAPI-MCP在处理用户输入时采用了严格的参数验证机制,确保输入数据的合法性:
# 在transport/sse.py中的参数验证
if not session_id:
raise HTTPException(status_code=400, detail="session_id is required")
if not isinstance(session_id, str) or len(session_id) != 36:
raise HTTPException(status_code=400, detail="Invalid session ID")
if session_id not in self.sessions:
raise HTTPException(status_code=404, detail="Could not find session")
自定义错误响应格式
为了提供更好的开发者体验,FastAPI-MCP支持自定义错误响应格式:
# 自定义错误响应结构示例
{
"error": {
"code": "AUTHENTICATION_FAILED",
"message": "Invalid token provided",
"details": {
"token_type": "Bearer",
"required_scopes": ["read", "write"]
}
}
}
错误恢复与重试机制
在处理暂时性错误时,FastAPI-MCP实现了智能的重试机制:
测试中的错误场景覆盖
FastAPI-MCP的测试套件包含了全面的错误场景测试,确保错误处理逻辑的正确性:
# 测试用例示例 - 测试认证错误
def test_auth_failure(self):
"""测试认证失败时的错误处理"""
with pytest.raises(HTTPException) as exc_info:
await verify_auth(Request(scope={"type": "http"}, headers={}))
assert exc_info.value.status_code == 401
assert "Invalid authorization header" in exc_info.value.detail
# 测试用例示例 - 测试参数验证错误
def test_invalid_session_id(self):
"""测试无效session ID的错误处理"""
response = client.post("/mcp/messages", json={"session_id": "invalid"})
assert response.status_code == 400
assert "Invalid session ID" in response.text
通过这套完整的错误处理与异常管理实践,FastAPI-MCP确保了系统的稳定性和可靠性,为开发者提供了清晰的错误信息和调试线索,大大提升了开发效率和用户体验。
总结
通过本文的实战案例,我们可以看到FastAPI-MCP为传统RESTful API与AI助手集成提供了强大的解决方案。从简单的CRUD操作到复杂的业务逻辑,FastAPI-MCP都能智能地进行工具转换,同时保持业务逻辑的完整性和一致性。分层错误处理架构、参数验证机制和状态管理策略确保了系统的稳定性和可靠性。这套框架不仅简化了AI与业务系统的集成流程,还为开发者提供了清晰的错误信息和调试线索,大大提升了开发效率和用户体验,是现代应用开发中连接传统API与AI能力的重要桥梁。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



