MCPEngine

by featureform

646 246 downloads Not rated yet Apache-2.0

About

EnrichMCP is a python framework for building data driven MCP servers

Details

License
Apache-2.0

Explore

- Automatic schema discovery – AI agents explore your entire data model with one call
- Relationship navigation – define relationships once, agents traverse naturally
- Type safety and validation – full Pydantic validation on every interaction
- Mutability and CRUD – auto-generated patch models for updates
- Built-in pagination – handle large datasets with PageResult
- Context and authentication – pass auth, database connections, or any context
- Request caching – reduce API overhead with per-request or global cache

pip install enrichmcp

Pass auth, database connections, or any context:

python
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()

The repository requires Python 3.11 or newer. The Makefile includes
commands to create a virtual environment and run the tests:

make setup            # create .venv and install dependencies
source .venv/bin/activate
make test             # run the test suite

This installs all development extras and pre-commit hooks so commands like
make lint or make docs work right away.

EnrichMCP

The ORM for AI Agents - Turn your data model into a semantic MCP layer

CI
Coverage
PyPI
Python 3.11+
License
Docs

EnrichMCP is a Python framework that helps AI agents understand and navigate your data. Built on MCP (Model Context Protocol), it adds a semantic layer that turns your data model into typed, discoverable tools - like an ORM for AI.

What is EnrichMCP?

Think of it as SQLAlchemy for AI agents. EnrichMCP automatically:

- Generates typed tools from your data models
- Handles relationships between entities (users → orders → products)
- Provides schema discovery so AI agents understand your data structure
- Validates all inputs/outputs with Pydantic models
- Works with any backend - databases, APIs, or custom logic

Installation

pip install enrichmcp

With SQLAlchemy support

pip install enrichmcp[sqlalchemy]

Show Me Code

Option 1: I Have SQLAlchemy Models (30 seconds)

Transform your existing SQLAlchemy models into an AI-navigable 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 agents can now:
- explore_data_model() - understand your entire schema
- list_users(status='active') - query with filters
- get_user(id=123) - fetch specific records
- Navigate relationships: user.orders → order.user

Option 2: I Have REST APIs (2 minutes)

Wrap your existing APIs with semantic understanding:

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()

Option 3: I Want Full Control (5 minutes)

Build a complete data layer with custom logic:

```python
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]

…

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.

Videos about MCPEngine

Relevant YouTube tutorials, setups, and demos