mcpField
M
MCPEngine

MCPEngine

本地服务
featureform.com开发工具64348 周前更新

关于 MCPEngine

EnrichMCP 是一个 Python 框架,用于构建数据驱动的 MCP 服务。它在 MCP 之上增加语义层,将数据模型转换为带类型、可发现的工具,面向需要让 AI Agent 理解和操作数据的开发者。框架基于 Pydantic 做输入输出校验,并支持 SQLAlchemy 集成。

主要功能

  1. 01从数据模型自动生成带类型的工具
  2. 02自动提供实体关系导航
  3. 03通过 explore_data_model 进行模式发现
  4. 04基于 Pydantic 的输入输出校验
  5. 05内置分页、缓存与上下文认证

适用场景

  1. 01为已有 SQLAlchemy 模型提供 AI Agent 可查询的接口
  2. 02用语义层封装已有 REST API
  3. 03为 AI Agent 构建带过滤和分页的数据服务

MCP 相关

EnrichMCP 基于 MCP 构建,其应用以 MCP 服务的形式运行,向 MCP 客户端暴露数据模型对应的工具。它还支持通过 MCP 的 sampling 功能,由已连接的客户端选择 LLM 完成请求。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

EnrichMCP

AI Agent 的 ORM——将您的数据模型转化为语义 MCP 层

CI Coverage PyPI Python 3.11+ License Docs

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 之上添加了三个关键层:

  1. 语义层——AI Agent 能理解数据的含义,而不只是数据结构
  2. 数据层——具备验证和关系功能的类型安全模型
  3. 控制层——身份验证、分页和业务逻辑

最终,AI Agent 能像开发者使用 ORM 一样自然地处理您的数据。

服务端 LLM 采样

EnrichMCP 可以通过 MCP 的 sampling 功能请求语言模型补全。可从任何资源调用 ctx.ask_llm() 或其别名 ctx.sampling(),由已连接的客户端选择 LLM 并支付使用费用。你可以使用 model_preferences、allow_tools 和 max_tokens 等选项调整行为。如需了解更多 详情,请参阅 docs/server_side_llm.md。

示例

请查看示例目录:

文档

贡献

欢迎贡献!详情请参阅 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

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。