关于 MCPEngine
EnrichMCP 是一个 Python 框架,用于构建数据驱动的 MCP 服务。它在 MCP 之上增加语义层,将数据模型转换为带类型、可发现的工具,面向需要让 AI Agent 理解和操作数据的开发者。框架基于 Pydantic 做输入输出校验,并支持 SQLAlchemy 集成。
主要功能
- 01从数据模型自动生成带类型的工具
- 02自动提供实体关系导航
- 03通过 explore_data_model 进行模式发现
- 04基于 Pydantic 的输入输出校验
- 05内置分页、缓存与上下文认证
适用场景
- 01为已有 SQLAlchemy 模型提供 AI Agent 可查询的接口
- 02用语义层封装已有 REST API
- 03为 AI Agent 构建带过滤和分页的数据服务
MCP 相关
EnrichMCP 基于 MCP 构建,其应用以 MCP 服务的形式运行,向 MCP 客户端暴露数据模型对应的工具。它还支持通过 MCP 的 sampling 功能,由已连接的客户端选择 LLM 完成请求。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
EnrichMCP
AI Agent 的 ORM——将您的数据模型转化为语义 MCP 层
EnrichMCP 是一个 Python 框架,可帮助 AI Agent 理解和浏览您的数据。它基于 MCP(模型上下文协议)构建,添加了一个语义层,将您的数据模型转化为类型化、可发现的工具——就像面向 AI 的 ORM。
什么是 EnrichMCP?
可以把它看作面向 AI Agent 的 SQLAlchemy。EnrichMCP 会自动:
- 根据您的数据模型生成类型化工具
- 处理实体之间的关系(用户 → 订单 → 商品)
- 提供架构发现功能,让 AI Agent 理解您的数据结构
- 使用 Pydantic 模型验证所有输入和输出
- 支持任何后端——数据库、API 或自定义逻辑
安装
pip install enrichmcp
# With SQLAlchemy support
pip install enrichmcp[sqlalchemy]
看看代码
选项 1:我有 SQLAlchemy 模型(30 秒)
将现有的 SQLAlchemy 模型转换为可供 AI 浏览的 API:
from enrichmcp import EnrichMCP
from enrichmcp.sqlalchemy import (
include_sqlalchemy_models,
sqlalchemy_lifespan,
EnrichSQLAlchemyMixin,
)
from sqlalchemy import ForeignKey
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db")
# Add the mixin to your declarative base
class Base(DeclarativeBase, EnrichSQLAlchemyMixin):
pass
class User(Base):
"""User account."""
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True, info={"description": "Unique user ID"})
email: Mapped[str] = mapped_column(unique=True, info={"description": "Email address"})
status: Mapped[str] = mapped_column(default="active", info={"description": "Account status"})
orders: Mapped[list["Order"]] = relationship(
back_populates="user", info={"description": "All orders for this user"}
)
class Order(Base):
"""Customer order."""
__tablename__ = "orders"
id: Mapped[int] = mapped_column(primary_key=True, info={"description": "Order ID"})
user_id: Mapped[int] = mapped_column(
ForeignKey("users.id"), info={"description": "Owner user ID"}
)
total: Mapped[float] = mapped_column(info={"description": "Order total"})
user: Mapped[User] = relationship(
back_populates="orders", info={"description": "User who placed the order"}
)
# That's it! Create your MCP app
app = EnrichMCP(
"E-commerce Data",
"API generated from SQLAlchemy models",
lifespan=sqlalchemy_lifespan(Base, engine, cleanup_db_file=True),
)
include_sqlalchemy_models(app, Base)
if __name__ == "__main__":
app.run()
AI Agent 现在可以:
explore_data_model()- 了解完整架构list_users(status='active')- 使用筛选条件查询get_user(id=123)- 获取特定记录- 浏览关系:
user.orders→order.user
选项 2:我有 REST API(2 分钟)
为现有 API 添加语义理解能力:
from typing import Literal
from enrichmcp import EnrichMCP, EnrichModel, Relationship
from pydantic import Field
import httpx
app = EnrichMCP("API Gateway", "Wrapper around existing REST APIs")
http = httpx.AsyncClient(base_url="https://api.example.com")
@app.entity()
class Customer(EnrichModel):
"""Customer in our CRM system."""
id: int = Field(description="Unique customer ID")
email: str = Field(description="Primary contact email")
tier: Literal["free", "pro", "enterprise"] = Field(description="Subscription tier")
# Define navigable relationships
orders: list["Order"] = Relationship(description="Customer's purchase history")
@app.entity()
class Order(EnrichModel):
"""Customer order from our e-commerce platform."""
id: int = Field(description="Order ID")
customer_id: int = Field(description="Associated customer")
total: float = Field(description="Order total in USD")
status: Literal["pending", "shipped", "delivered"] = Field(description="Order status")
customer: Customer = Relationship(description="Customer who placed this order")
# Define how to fetch data
@app.retrieve()
async def get_customer(customer_id: int) -> Customer:
"""Fetch customer from CRM API."""
response = await http.get(f"/api/customers/{customer_id}")
return Customer(**response.json())
# Define relationship resolvers
@Customer.orders.resolver
async def get_customer_orders(customer_id: int) -> list[Order]:
"""Fetch orders for a customer."""
response = await http.get(f"/api/customers/{customer_id}/orders")
return [Order(**order) for order in response.json()]
@Order.customer.resolver
async def get_order_customer(order_id: int) -> Customer:
"""Fetch the customer for an order."""
response = await http.get(f"/api/orders/{order_id}/customer")
return Customer(**response.json())
app.run()
选项 3:我想要完全控制(5 分钟)
使用自定义逻辑构建完整的数据层:
from enrichmcp import EnrichMCP, EnrichModel, Relationship
from datetime import datetime
from decimal import Decimal
from pydantic import Field
app = EnrichMCP("Analytics Platform", "Custom analytics API")
db = ... # your database connection
@app.entity()
class User(EnrichModel):
"""User with computed analytics fields."""
id: int = Field(description="User ID")
email: str = Field(description="Contact email")
created_at: datetime = Field(description="Registration date")
# Computed fields
lifetime_value: Decimal = Field(description="Total revenue from user")
churn_risk: float = Field(description="ML-predicted churn probability 0-1")
# Relationships
orders: list["Order"] = Relationship(description="Purchase history")
segments: list["Segment"] = Relationship(description="Marketing segments")
@app.entity()
class Segment(EnrichModel):
"""Dynamic user segment for marketing."""
name: str = Field(description="Segment name")
criteria: dict = Field(description="Segment criteria")
users: list[User] = Relationship(description="Users in this segment")
@app.entity()
class Order(EnrichModel):
"""Simplified order record."""
id: int = Field(description="Order ID")
user_id: int = Field(description="Owner user ID")
total: Decimal = Field(description="Order total")
@User.orders.resolver
async def list_user_orders(user_id: int) -> list[Order]:
"""Fetch orders for a user."""
rows = await db.query(
"SELECT * FROM orders WHERE user_id = ? ORDER BY id DESC",
user_id,
)
return [Order(**row) for row in rows]
@User.segments.resolver
async def list_user_segments(user_id: int) -> list[Segment]:
"""Fetch segments that include the user."""
rows = await db.query(
"SELECT s.* FROM segments s JOIN user_segments us ON s.name = us.segment_name WHERE us.user_id = ?",
user_id,
)
return [Segment(**row) for row in rows]
@Segment.users.resolver
async def list_segment_users(name: str) -> list[User]:
"""List users in a segment."""
rows = await db.query(
"SELECT u.* FROM users u JOIN user_segments us ON u.id = us.user_id WHERE us.segment_name = ?",
name,
)
return [User(**row) for row in rows]
# Complex resource with business logic
@app.retrieve()
async def find_high_value_at_risk_users(
lifetime_value_min: Decimal = 1000, churn_risk_min: float = 0.7, limit: int = 100
) -> list[User]:
"""Find valuable customers likely to churn."""
users = await db.query(
"""
SELECT * FROM users
WHERE lifetime_value >= ? AND churn_risk >= ?
ORDER BY lifetime_value DESC
LIMIT ?
""",
lifetime_value_min,
churn_risk_min,
limit,
)
return [User(**u) for u in users]
# Async computed field resolver
@User.lifetime_value.resolver
async def calculate_lifetime_value(user_id: int) -> Decimal:
"""Calculate total revenue from user's orders."""
total = await db.query_single("SELECT SUM(total) FROM orders WHERE user_id = ?", user_id)
return Decimal(str(total or 0))
# ML-powered field
@User.churn_risk.resolver
async def predict_churn_risk(user_id: int) -> float:
"""Run churn prediction model."""
ctx = app.get_context()
features = await gather_user_features(user_id)
model = ctx.get("ml_models")["churn"]
return float(model.predict_proba(features)[0][1])
app.run()
主要功能
🔍 自动架构发现
AI Agent 只需一次调用即可探索您的整个数据模型:
schema = await explore_data_model()
# Returns complete schema with entities, fields, types, and relationships
🔗 关系导航
只需定义一次关系,AI Agent 就能自然地遍历:
# AI can navigate: user → orders → products → categories
user = await get_user(123)
orders = await user.orders() # Automatic resolver
products = await orders[0].products()
🛡️ 类型安全与验证
每次交互都进行完整的 Pydantic 验证:
@app.entity()
class Order(EnrichModel):
total: float = Field(ge=0, description="Must be positive")
email: EmailStr = Field(description="Customer email")
status: Literal["pending", "shipped", "delivered"]
describe_model() 会列出这些允许值,让 Agent 知道有效选项。
✏️ 可变性与 CRUD
字段默认不可变。将字段标记为可变,并使用 自动生成的补丁模型进行更新:
@app.entity()
class Customer(EnrichModel):
id: int = Field(description="ID")
email: str = Field(json_schema_extra={"mutable": True}, description="Email")
@app.create()
async def create_customer(email: str) -> Customer: ...
@app.update()
async def update_customer(cid: int, patch: Customer.PatchModel) -> Customer: ...
@app.delete()
async def delete_customer(cid: int) -> bool: ...
📄 内置分页
轻松处理大型数据集:
from enrichmcp import PageResult
@app.retrieve()
async def list_orders(page: int = 1, page_size: int = 50) -> PageResult[Order]:
orders, total = await db.get_orders_page(page, page_size)
return PageResult.create(items=orders, page=page, page_size=page_size, total_items=total)
更多示例请参阅分页指南。
🔐 上下文与身份验证
传递身份验证信息、数据库连接或任何上下文:
from pydantic import Field
from enrichmcp import EnrichModel
class UserProfile(EnrichModel):
"""User profile information."""
user_id: int = Field(description="User ID")
bio: str | None = Field(default=None, description="Short bio")
@app.retrieve()
async def get_user_profile(user_id: int) -> UserProfile:
ctx = app.get_context()
# Access context provided by MCP client
auth_user = ctx.get("authenticated_user_id")
if auth_user != user_id:
raise PermissionError("Can only access your own profile")
return await db.get_profile(user_id)
⚡ 请求缓存
将结果存储在每次请求、每个用户或全局缓存中,以减少 API 开销:
@app.retrieve()
async def get_customer(cid: int) -> Customer:
ctx = app.get_context()
async def fetch() -> Customer:
return await db.get_customer(cid)
return await ctx.cache.get_or_set(f"customer:{cid}", fetch)
🧭 参数提示
使用 EnrichParameter 为工具参数提供示例和元数据:
from enrichmcp import EnrichParameter
@app.retrieve()
async def greet_user(name: str = EnrichParameter(description="user name", examples=["bob"])) -> str:
return f"Hello {name}"
工具描述将包含参数类型、说明和示例。
🌐 HTTP 与 SSE 支持
通过标准输出(默认方式)、SSE 或 HTTP 提供 API:
app.run() # stdio default
app.run(transport="streamable-http")
为什么选择 EnrichMCP?
EnrichMCP 在 MCP 之上添加了三个关键层:
- 语义层——AI Agent 能理解数据的含义,而不只是数据结构
- 数据层——具备验证和关系功能的类型安全模型
- 控制层——身份验证、分页和业务逻辑
最终,AI Agent 能像开发者使用 ORM 一样自然地处理您的数据。
服务端 LLM 采样
EnrichMCP 可以通过 MCP 的 sampling
功能请求语言模型补全。可从任何资源调用 ctx.ask_llm() 或其别名
ctx.sampling(),由已连接的客户端选择 LLM 并支付使用费用。你可以使用
model_preferences、allow_tools 和 max_tokens 等选项调整行为。如需了解更多
详情,请参阅 docs/server_side_llm.md。
示例
请查看示例目录:
- hello_world - 最精简的 EnrichMCP 应用
- hello_world_http - 使用 streamable HTTP 的 HTTP 示例
- shop_api - 带分页和筛选功能的内存商店 API
- shop_api_sqlite - 基于 SQLite 的版本
- shop_api_gateway - 将 EnrichMCP 作为 FastAPI 前置网关
- sqlalchemy_shop - 根据 SQLAlchemy 模型自动生成的 API
- mutable_crud - 演示可变字段和 CRUD 装饰器
- caching - 演示 ContextCache 的用法
- basic_memory - 使用 FileMemoryStore 的简单记事 API
- openai_chat_agent - 用于 MCP 示例的交互式聊天客户端
文档
贡献
欢迎贡献!详情请参阅 CONTRIBUTING.md。
开发环境设置
此代码库要求使用 Python 3.11 或更高版本。Makefile 包含用于创建虚拟环境 和运行测试的命令:
make setup # create .venv and install dependencies
source .venv/bin/activate
make test # run the test suite
这会安装所有开发扩展和 pre-commit 钩子,让你可以立即运行 make lint 或
make docs 等命令。
许可证
Apache 2.0 - 请参阅 LICENSE
由 Featureform 构建 • MCP Protocol
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。