Skip to main content
Glama

mcp_feast

Un servidor MCP sobre un feature store de Feast, para un modelo de fraude por pases de tarjeta. Se ejecuta por completo en local: offline store en Parquet, online store en SQLite, sin nube, sin broker.

Claude  --MCP/stdio-->  mcp_server/  --HTTP-->  api/  --SDK-->  Feast  -->  Parquet + SQLite
                        (no feast)              (holds the FeatureStore)

La frontera HTTP del medio es el punto clave. Todo lo específico de Feast vive por debajo; el servidor MCP que está por encima no necesita instalación de Feast, ni drivers de store, ni credenciales de almacén de datos. Cambiar SQLite por Redis es un cambio en feature_repo/feature_store.yaml que el servidor MCP jamás ve.

Inicio rápido

Python 3.11. Feast declara >=3.10, pero clasifica solo 3.10, y su pila transitiva de dependencias es la fuente habitual de problemas con intérpretes más nuevos.

python3.11 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

./setup.sh        # preflight + data + apply + materialize
./run_api.sh      # API on :8000, docs at /docs

Ambos scripts respetan una sobreescritura PYTHON si las dependencias están en otro sitio:

PYTHON=/opt/miniconda3/envs/myenv/bin/python3 ./setup.sh

El servidor MCP lo lanza el host mediante .mcp.json, que fija una ruta absoluta de intérprete por el motivo que se explica en «Solución de problemas» más abajo. ./run_mcp.sh lo ejecuta a mano para depurar.

Solución de problemas: intérprete incorrecto

Dos síntomas, una causa: un Python distinto del que tiene las dependencias:

ModuleNotFoundError: No module named 'feast'
ImportError: cannot import name 'MCPServer' from 'mcp.server'

El segundo es el que más quebraderos da: mcp 1.x importa bien, pero expone mcp.server.fastmcp.FastMCP, no el mcp.server.MCPServer 2.x que usa este proyecto. Que el prompt de la shell muestre un entorno conda activo no es prueba: revisa el PATH:

which python3 && python3 -V
echo $PATH | tr ":" "\n" | head -3

Si un Python de framework o del sistema aparece por delante de tu entorno, todo lo que llame a python3 se escapa de ese entorno diga lo que el prompt diga. Diagnostícalo bien con:

python3 preflight.py

Importa el símbolo exacto que necesita cada parte del código, no solo el módulo; así una dependencia con la versión mayor equivocada se detecta por el nombre, y avisa cuando uvicorn o feast de tu PATH pertenecen a otro entorno.

Todos los puntos de entrada aceptan una sobreescritura PYTHON, así nunca tienes que pelear contigo para con el PATH:

PYTHON=/opt/miniconda3/envs/myenv/bin/python3 ./setup.sh
PYTHON=/opt/miniconda3/envs/myenv/bin/python3 ./run_api.sh
PYTHON=/opt/miniconda3/envs/myenv/bin/python3 python3 mcp_cli.py tools

Dos reglas evitan esto del todo:

  • Inicia la API con ./run_api.sh, o python3 -m uvicorn api.main:app. Nunca uvicorn api.main:app a secas: eso resuelve uvicorn desde el PATH, que puede pertenecer a un Python distinto del que tiene Feast, y el fallo sale a la superficie cuarenta frames dentro de una cadena de imports.

  • Mantén el command de .mcp.json como ruta absoluta del intérprete. Un "python3" ahí se resuelve contra el PATH que tuviera el proceso del host a mano.

Related MCP server: tecton-mcp

Qué hay en el registro

Entidadescard (card_id), customer (customer_id)

Vistas de características

Vista

Entidad

Tipo

Características

TTL

card_velocity

card

push

txn_count_1h, txn_count_24h, amount_sum_1h

2 h

customer_profile

customer

batch

avg_amount_30d, distinct_merchants_30d, home_country, chargebacks_lifetime

7 d

Servicio de característicasfraud_model_v2, que vincula las 7 características.

La división de TTL de 2 h / 7 d es intencionada: hace que las herramientas de frescura produzcan respuestas reales en lugar de un permanente todo en verde.

Datos simulados

data_gen/generate_swipes.py escribe 15,000 instantáneas de clientes (500 clientes × 30 días) y 14,394 filas de velocidad (600 tarjetas × 24 horas, menos 6 eliminadas para crear el caso de obsolescencia). Todo está anclado al momento de ejecución, de modo que regenerar siempre produce datos que se materializan sin problema.

Seis perfiles están fijados para que las demos sean deterministas:

Tarjeta / Cliente

Perfil

Demuestra

C-4471 / CU-8842

7 pases/h, 2,140 $ frente a una media de 58,20 $, contracargos nulos

El caso de fraude y una característica nula

C-1002 / CU-1002

Todo en la mediana

Control

C-7788 / CU-3310

La fila de velocidad más reciente tiene 6 h

Obsolescencia más allá de un TTL de 2 h

C-9999

Nunca generado

Entidad desconocida

CU-5150

Perfil pero sin tarjeta

Cobertura parcial

C-3355 / CU-4402

4 contracargos, velocidad normal

Riesgo que no es velocidad

La API

Grupo

Endpoints

Catálogo

/entities /data-sources /feature-views /feature-views/{n} /feature-services /feature-services/{n} /features/search /cards/{id}

Linaje

/features/{view}/{feature}/lineage /feature-views/{n}/consumers

Salud

/feature-views/{n}/freshness /health/materialization /feature-views/{n}/materialize

Valores

/features/online /features/explain /features/push

Documentación interactiva en http://localhost:8000/docs.

La API no es un passthrough. Hace tres cosas que el SDK crudo no hace: combina metadatos del registro con timestamps del online store para calcular frescura, recorre fuente → vista → servicio para calcular el linaje, y aplana las formas proto de Feast en objetos planos y nombrados.

Herramientas MCP

12 herramientas de solo lectura, más 2 herramientas de escritura que solo se registran cuando la escritura está habilitada.

list_feature_views · describe_feature_view · list_feature_services · describe_feature_service · search_features · list_entities · resolve_card · get_feature_lineage · get_feature_consumers · check_feature_freshness · get_online_features · explain_features_for_entity · push_swipe ⚠ · trigger_materialization

Dos tipos de frescura

Responden a preguntas distintas, y confundirlas es el error más peligroso que hay aquí:

Herramienta

Responde

¿Para qué?

check_feature_freshness

«¿Está muerto un pipeline?»

Todas las entidades, a nivel de vista

explain_features_for_entity

«¿Están al día los datos de esta tarjeta

Una entidad

Una entidad concreta puede estar obsoleta seis horas dentro de una vista que se materializó hace segundos: la materialización escribe lo que tuviera la fuente, y para una tarjeta sin filas recientes eso es un valor viejo. Por eso una vista que muestra OK no demuestra nada sobre una tarjeta concreta.

Un modelo pequeño tiende a confundir las dos cosas y responder «suficientemente reciente para confiar» a partir de los metadatos de nivel de vista. Tres capas lo impiden: las INSTRUCTIONS del servidor, el texto de la herramienta check_feature_freshness y una nota añadida a la salida de esa herramienta; la última es la que de verdad funciona, porque un modelo que se saltó la descripción también lee el resultado sobre el que actuó.

Por qué existe explain_features_for_entity

get_online_features devuelve valores pelados. Un null pelado no puede distinguir cuatro situaciones distintas, y Feast sirve sin quejarse un valor caducado:

  • un cero real

  • una vista que nunca se materializó

  • una entidad que no existe

  • un valor que ha sobrepasado su TTL

explain_features_for_entity los separa usando el event_ts por entidad recuperado del online store. Por eso es la herramienta de consulta preferida.

FEAST_MCP_READONLY

Lo leen ambos procesos. Cuando es true (el valor por defecto), el servidor MCP no registra en absoluto push_swipe ni trigger_materialization; una herramienta que el modelo no puede ver no la va a intentar, y la API por su parte devuelve 403 en esas rutas, con lo que ni siquiera un curl directo entra.

Host de LLM local

host.py is a real MCP host impulsado por un modelo local de código abierto: sin clave de API, nada alojado. El modelo decide a qué herramientas llamar; mcp_cli.py solo llama a las herramientas que le nombres.

ollama/qwen2.5:7b  ->  host.py  ->  MCP server  ->  Feature API  ->  Feast  ->  SQLite
ollama serve &                      # if not already running
ollama pull qwen2.5:7b              # any tool-calling model works

python3 host.py "Why would card C-4471 be flagged?"
python3 host.py --trace --quiet "Is anything stale?"
python3 host.py                     # interactive

El prompt del sistema no está escrito en host.py. Sale de la instructions del propio servidor MCP, que se devuelve durante initialize(); el servidor le explica al modelo cómo deben usarse sus herramientas y el host lo transmite. Cambiar INSTRUCTIONS en mcp_server/server.py cambia el comportamiento del modelo sin tocar el host.

La elección del modelo importa: necesita soporte de tool-calling. lengqwen2.5:7b funciona; Gemma no tiene ninguna plantilla de herramientas en Ollama y no funcionará.

Protecciones del host

Un modelo de 7B es un planificador poco fiable, así que el bucle se protegen against contra tres fallos que de veras presenta:

Fallo

Protección

Repite una llamada que ya hizo, a veces hasta el límite de pasos

Los resultados quedan en la lazada por (tool, args); una repetición se sirve desde la caché con una nota de «esto ya lo hiciste» en lugar de una segunda vuelta

Narra en prosa el siguiente paso («Ahora vamos a llamar a describe_feature_view») en lugar de emergir una

Se detecta y se empuja una vez para que emita la llamada en vez de describirla (máximo 2)

Se va más allá del presupuesto de pasos sin respuesta

En el último paso, o después de 3 repeticiones, las herramientas se le retiran, y tiene que responder con lo que ya haya recogido

Cada una imprime una línea HOST |, de forma que puedes ver al bucle interven.

Aun así, espera que divague en preguntas abiertas. Limitar el conjunto de herramientas es la solución práctica:

python3 host.py --tools resolve_card,explain_features_for_entity,check_feature_freshness \
  "Why would card C-4471 be flagged?"

Mientras MCP llama a la API

mcp_cli.py habla el mismo protocolo de stdio que el host, de modo que la cadena MCP → API se puede observar desde el shell:

python3 mcp_cli.py tools                    # what is registered
python3 mcp_cli.py --trace demo             # 11-step walkthrough, with HTTP calls
python3 mcp_cli.py --trace call resolve_card '{"card_id": "C-4471"}'

--trace imprime el endpoint que usa cada una de las herramientas:

      http | HTTP Request: GET http://localhost:8000/cards/C-4471 "HTTP/1.1 200 OK"
C-4471 is owned by CU-8842

Pruébalo

Investigar un rechazo

«¿Por qué se rechaza la tarjeta C-4471?»

list_feature_servicesresolve_cardexplain_features_for_entity. Devuelve 7 pases en la última hora que suman 2,140 $ frente a una media de 58,20 $, con un histórico de contracargos explícitamente no disponible en vez de dár por cero.

Detectar un pipeline muerto

«¿Está algo obsoleto en la tarjeta C-7708?»

explain_features_for_entity marca card_velocity como con 6 h 46 min de antigüedad frenterme TTL de 2 h. Los valores siguen viniendo: nada bloquea la lectura, que es exactamente el motivo por el que hace falta la marca.

Push de ida y vuelta (con escritura activada)

«Registra un pase en C-7788 y luego comprueba otra vez.»

push_swipe → la misma tarjeta se lee reciente. trigger_materialization en card_velocity lo deja de nuevo en la fila del lote de hace 6 h, así la demo es repetible.

Estructura

requirements.txt  pinned, verified working set
preflight.py      interpreter + dependency check, run by both scripts
setup.sh          data + apply + materialize
run_api.sh        starts the API on the right interpreter
run_mcp.sh        starts the MCP server by hand (debugging)
mcp_cli.py        drives the MCP server from a shell, with --trace
host.py           local-LLM MCP host -- the model picks the tools

feature_repo/     Feast definitions + feature_store.yaml   (the only Feast config)
data_gen/         mock data generator
api/              FastAPI + the Feast SDK        <- the API boundary
  routers/        catalog | lineage | health | values
mcp_server/       MCP tools, HTTP client only    <- no Feast import
  tools/          catalog | lineage | health | values | admin

api/routers/ y mcp_server/tools/ son espejo uno a uno del otro.

Notas

  • chargebacks_lifetime es Float64, no Int64. El atributo admite nulos de verdad, y un entero nulo no tiene representación en la ruta Parquet → pandas → Feast.

  • Usa feast materialize, no materialize-incremental, para la configuración. La modalidad incremental usa la TTL de la vista como límite inicial, así que con una TTL de 2h se saltaría la fila de 6h de antigüedad que hace que la persona obsoleta funcione.

  • Caché del registro. cache_ttl_seconds: 30 en feature_store.yaml significa que un feast apply desde otra consola aparece en 30 s. POST /admin/reload lo fuerza de inmediato y también reabre el almacén en línea, algo que una mera actualización del registro no hace.

  • Los datos simulados están anclados en el tiempo. card_velocity tiene una TTL de 2h, así que pasadas más de un par de horas desde ./setup.sh, todas las tarjetas se leen como obsoletas y las personas dejan de distinguirse. Vuelve a ejecutar ./setup.sh.

  • Concurrencia en SQLite. La escritura de feast materialize mientras uvicorn lee puede dar lugar a contención de bloqueos. Vale para local, pero no es un almacén en línea de producción.

F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI models to interact with local CSV and Parquet data through MCP tools, providing summarization and analysis capabilities.
    1
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables interaction with Tecton clusters through MCP, allowing management of feature stores, execution of Tecton CLI commands, and retrieval of feature store configurations via natural language.
  • A
    license
    A
    quality
    D
    maintenance
    Exposes Azure AI Foundry agents, workflows, and AI Search vector-database capabilities as MCP tools, enabling natural language interaction with agents, semantic search, and index management.
    10
    2
    MIT

View all related MCP servers

Related MCP Connectors

  • Hosted MCP endpoint with realistic fake data for prototyping agents. 12 tools, no setup.

  • Shared, governed long-term memory for AI agents across tools and sessions via MCP and REST.

  • A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sidbu546/mcp_feast_dev'

If you have feedback or need assistance with the MCP directory API, please join our Discord server