EnrichMCP – AI 에이전트를 위한 데이터 ORM Python 프레임워크

AI 에이전트가 여러분의 데이터를 이해하고 탐색할 수 있도록 돕는 Python 프레임워크

소개

EnrichMCP는 MCP(Model Context Protocol)를 기반으로 구축된 Python 프레임워크로, 데이터 모델을 AI 에이전트가 이해할 수 있는 의미론적 계층으로 변환해줍니다. SQLAlchemy가 개발자에게 ORM을 제공하듯이, EnrichMCP는 AI 에이전트에게 “데이터 ORM”을 제공한다고 생각하시면 됩니다.

기존 방식에서는 AI 에이전트가 데이터베이스나 API에 접근하려면 복잡한 쿼리나 API 호출을 직접 작성해야 했습니다. EnrichMCP는 데이터 모델을 자동으로 분석해 타입 안전한 도구들을 생성하고, 엔티티 간의 관계를 자동으로 처리하며, AI 에이전트가 자연스럽게 데이터를 탐색할 수 있도록 합니다.

주요 특징

  • 자동 도구 생성: 데이터 모델에서 타입 안전한 도구들을 자동으로 생성
  • 관계 탐색: 사용자 → 주문 → 상품처럼 엔티티 간의 관계를 자연스럽게 탐색
  • 스키마 발견: AI 에이전트가 전체 데이터 구조를 이해할 수 있도록 스키마 정보 제공
  • 타입 안전성: Pydantic 모델을 통한 모든 입출력 검증
  • 다양한 백엔드 지원: 데이터베이스, API, 커스텀 로직 등 어떤 백엔드든 연결 가능
  • SQLAlchemy 통합: 기존 SQLAlchemy 모델을 바로 AI 도구로 변환
  • 페이지네이션: 대용량 데이터셋을 효율적으로 처리
  • 인증 및 컨텍스트: 사용자 인증, 데이터베이스 연결 등을 안전하게 관리

설치 방법

# 기본 설치
pip install enrichmcp

# SQLAlchemy 지원 포함
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.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")

# 선언적 베이스에 믹스인 추가
class Base(DeclarativeBase, EnrichSQLAlchemyMixin):
    pass

class User(Base):
    __tablename__ = "users"

    id: Mapped[int] = mapped_column(primary_key=True)
    email: Mapped[str] = mapped_column(unique=True)
    status: Mapped[str] = mapped_column(default="active")
    orders: Mapped[list["Order"]] = relationship(back_populates="user")

class Order(Base):
    __tablename__ = "orders"

    id: Mapped[int] = mapped_column(primary_key=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
    total: Mapped[float] = mapped_column()
    user: Mapped[User] = relationship(back_populates="orders")

# MCP 앱 생성
app = EnrichMCP(
    "E-commerce Data",
    lifespan=sqlalchemy_lifespan(Base, engine, cleanup_db_file=True),
)
include_sqlalchemy_models(app, Base)

if __name__ == "__main__":
    app.run()

이제 AI 에이전트는 다음과 같은 작업을 할 수 있습니다:

  • explore_data_model() – 전체 스키마 구조 이해하기
  • list_users(status='active') – 필터링된 사용자 목록 조회
  • get_user(id=123) – 특정 사용자 정보 가져오기
  • 관계 탐색: user.ordersorder.user

2. REST API가 있는 경우 (2분)

기존 API를 의미론적 이해가 가능한 형태로 래핑할 수 있습니다:

from enrichmcp import EnrichMCP, EnrichModel, Relationship
from pydantic import Field

app = EnrichMCP("API Gateway")

@app.entity
class Customer(EnrichModel):
    """CRM 시스템의 고객 정보."""

    id: int = Field(description="고유 고객 ID")
    email: str = Field(description="주 연락처 이메일")
    tier: str = Field(description="구독 등급: free, pro, enterprise")

    # 탐색 가능한 관계 정의
    orders: list["Order"] = Relationship(description="고객의 구매 이력")

@app.entity
class Order(EnrichModel):
    """전자상거래 플랫폼의 고객 주문."""

    id: int = Field(description="주문 ID")
    customer_id: int = Field(description="연결된 고객")
    total: float = Field(description="USD 단위 주문 총액")
    status: str = Field(description="주문 상태: pending, shipped, delivered")

    customer: Customer = Relationship(description="이 주문을 한 고객")

# 데이터 가져오는 방법 정의
@app.retrieve
async def get_customer(customer_id: int) -> Customer:
    """CRM API에서 고객 정보를 가져옵니다."""
    response = await http.get(f"/api/customers/{customer_id}")
    return Customer(**response.json())

# 관계 해결자 정의
@Customer.orders.resolver
async def get_customer_orders(customer_id: int) -> list[Order]:
    """고객의 주문 목록을 가져옵니다."""
    response = await http.get(f"/api/customers/{customer_id}/orders")
    return [Order(**order) for order in response.json()]

app.run()

3. 완전한 컨트롤이 필요한 경우 (5분)

커스텀 로직을 포함한 완전한 데이터 계층을 구축할 수 있습니다:

from enrichmcp import EnrichMCP, EnrichModel, Relationship, EnrichContext
from datetime import datetime
from decimal import Decimal

app = EnrichMCP("Analytics Platform")

@app.entity
class User(EnrichModel):
    """계산된 분석 필드를 포함한 사용자."""

    id: int = Field(description="사용자 ID")
    email: str = Field(description="연락처 이메일")
    created_at: datetime = Field(description="가입 날짜")

    # 계산된 필드
    lifetime_value: Decimal = Field(description="사용자로부터의 총 수익")
    churn_risk: float = Field(description="ML로 예측한 이탈 확률 0-1")

    # 관계
    orders: list["Order"] = Relationship(description="구매 이력")
    segments: list["Segment"] = Relationship(description="마케팅 세그먼트")

@app.entity
class Segment(EnrichModel):
    """마케팅을 위한 동적 사용자 세그먼트."""

    name: str = Field(description="세그먼트 이름")
    criteria: dict = Field(description="세그먼트 기준")
    users: list[User] = Relationship(description="이 세그먼트의 사용자들")

# 비즈니스 로직이 포함된 복잡한 리소스
@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]:
    """이탈할 가능성이 높은 고가치 고객을 찾습니다."""
    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]

# 비동기 계산 필드 해결자
@User.lifetime_value.resolver
async def calculate_lifetime_value(user_id: int) -> Decimal:
    """사용자 주문들의 총 수익을 계산합니다."""
    total = await db.query_single(
        "SELECT SUM(total) FROM orders WHERE user_id = ?",
        user_id
    )
    return Decimal(str(total or 0))

# ML 기반 필드
@User.churn_risk.resolver
async def predict_churn_risk(user_id: int, context: EnrichContext) -> float:
    """이탈 예측 모델을 실행합니다."""
    features = await gather_user_features(user_id)
    model = context.get("ml_models")["churn"]
    return float(model.predict_proba(features)[0][1])

app.run()

핵심 기능 살펴보기

🔍 자동 스키마 발견

AI 에이전트가 하나의 호출로 전체 데이터 모델을 탐색할 수 있습니다:

schema = await explore_data_model()
# 엔티티, 필드, 타입, 관계가 포함된 완전한 스키마 반환

🔗 관계 탐색

관계를 한 번만 정의하면 AI 에이전트가 자연스럽게 탐색할 수 있습니다:

# AI가 다음과 같이 탐색할 수 있습니다: user → orders → products → categories
user = await get_user(123)
orders = await user.orders()  # 자동 해결자
products = await orders[0].products()

🛡️ 타입 안전성 & 검증

모든 상호작용에서 완전한 Pydantic 검증을 제공합니다:

@app.entity
class Order(EnrichModel):
    total: float = Field(ge=0, description="양수여야 함")
    email: EmailStr = Field(description="고객 이메일")
    status: Literal["pending", "shipped", "delivered"]

✏️ 가변성 & CRUD

필드는 기본적으로 불변입니다. 가변으로 표시하고 업데이트를 위한 자동 생성 패치 모델을 사용할 수 있습니다:

@app.entity
class Customer(EnrichModel):
    id: int = Field(description="ID")
    email: str = Field(mutable=True, description="이메일")

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

🔐 컨텍스트 & 인증

인증, 데이터베이스 연결 또는 모든 컨텍스트를 전달할 수 있습니다:

@app.retrieve
async def get_user_profile(user_id: int, context: EnrichContext) -> UserProfile:
    # MCP 클라이언트가 제공한 컨텍스트 접근
    auth_user = context.get("authenticated_user_id")
    if auth_user != user_id:
        raise PermissionError("자신의 프로필만 접근할 수 있습니다")
    return await db.get_profile(user_id)

EnrichMCP를 선택하는 이유

EnrichMCP는 MCP 위에 세 가지 중요한 계층을 추가합니다:

  1. 의미론적 계층 – AI 에이전트가 데이터의 구조뿐만 아니라 의미를 이해
  2. 데이터 계층 – 검증과 관계가 포함된 타입 안전한 모델
  3. 제어 계층 – 인증, 페이지네이션, 비즈니스 로직

결과적으로 AI 에이전트는 개발자가 ORM을 사용하는 것처럼 자연스럽게 데이터와 작업할 수 있습니다.

예제 프로젝트

프로젝트의 examples 디렉토리에서 다양한 사용 사례를 확인할 수 있습니다:

  • hello_world – 가장 간단한 EnrichMCP 앱
  • shop_api – 페이지네이션과 필터가 포함된 인메모리 쇼핑몰 API
  • shop_api_sqlite – SQLite 백엔드 버전
  • shop_api_gateway – FastAPI 앞에 EnrichMCP를 게이트웨이로 사용
  • sqlalchemy_shop – SQLAlchemy 모델에서 자동 생성된 API
  • mutable_crud – 가변 필드와 CRUD 데코레이터 데모
  • openai_chat_agent – MCP 예제용 대화형 채팅 클라이언트

관련 링크

🔗 GitHub 저장소: https://github.com/featureform/enrichmcp
📖 전체 문서: https://featureform.github.io/enrichmcp
🚀 시작 가이드: https://featureform.github.io/enrichmcp/getting-started
🔧 API 레퍼런스: https://featureform.github.io/enrichmcp/api
🏠 Featureform 홈페이지: https://featureform.com
📋 MCP 프로토콜: https://modelcontextprotocol.io

라이선스

Apache 2.0 라이선스


🤗 이 글은 AI 모델이 정리한 내용을 기반으로 작성되었으며, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다.