Skip to main content
Glama

Feast MCP Server

Standalone MCP server for Feast, built on FastMCP.

Composes two namespaced sub-servers behind a single MCP endpoint:

  • features — proxies to the Feast feature server (online features, vector search, push, materialization). Mounted when --feast-url is provided.

  • registry — proxies to the Feast REST registry server (browse feature views, entities, data sources, lineage). Mounted when --registry-url is provided.

The caller's Authorization: Bearer <token> header is passed through so that upstream servers handle OIDC / Kubernetes RBAC as usual.

Documentation

Full guides live in docs/:

Related MCP server: @dotlab-hq/vector-store-mcp

Quick start

cd MCP
pip install -e .

# Feature server only (9 tools)
feast-mcp --feast-url http://localhost:6566

# Registry only (13 tools)
feast-mcp --registry-url http://localhost:8080

# Both (22 tools)
feast-mcp --feast-url http://localhost:6566 --registry-url http://localhost:8080

# HTTP transport on a custom port
feast-mcp --feast-url http://localhost:6566 --transport http --port 8000

Environment variables work too:

export FEAST_MCP_FEATURE_SERVER_URL=http://localhost:6566
export FEAST_MCP_REGISTRY_URL=http://localhost:8080
feast-mcp

Tools exposed

Feature server tools (features_ prefix)

Tool

Upstream endpoint

Description

features_get_online_features

POST /get-online-features

Retrieve online feature values

features_search

POST /search

Vector similarity search

features_list_vector_stores

GET /v1/vector_stores

List vector stores

features_get_vector_store

GET /v1/vector_stores/{id}

Get a vector store

features_vector_store_search

POST /v1/vector_stores/{id}/search

OpenAI-compatible vector search

features_push

POST /push

Push features to the store

features_materialize

POST /materialize

Materialize features

features_materialize_incremental

POST /materialize-incremental

Incremental materialization

features_health

GET /health

Health check

Registry tools (registry_ prefix)

Tool

Upstream endpoint

Description

registry_list_projects

GET /api/v1/projects

List all projects

registry_get_project

GET /api/v1/projects/{name}

Get project details

registry_list_entities

GET /api/v1/entities

List entities in a project

registry_get_entity

GET /api/v1/entities/{name}

Get entity details

registry_list_feature_views

GET /api/v1/feature_views

List all feature views

registry_get_feature_view

GET /api/v1/feature_views/{name}

Get feature view details

registry_list_features

GET /api/v1/features

List individual features

registry_list_feature_services

GET /api/v1/feature_services

List feature services

registry_get_feature_service

GET /api/v1/feature_services/{name}

Get feature service details

registry_list_data_sources

GET /api/v1/data_sources

List data sources

registry_get_data_source

GET /api/v1/data_sources/{name}

Get data source details

registry_search_registry

GET /api/v1/search

Full-text search across registry

registry_get_lineage

GET /api/v1/lineage/complete

Get lineage relationships

Project structure

feast_mcp/
  server.py         — composition + CLI entry point
  features.py       — feature server tools (9 tools)
  registry.py       — registry server tools (13 tools)
  client.py         — shared HTTP client
  auth.py           — shared auth helpers
  session_storage/  — factory for the shared OAuth-state store (key_value.aio)
  observability/    — logging fanned out to stdout + OpenTelemetry

Authorization

The MCP server itself does not validate tokens. It forwards the bearer token from the MCP request context to the upstream servers, which perform OIDC or Kubernetes token validation and RBAC enforcement.

For OIDC browser-based login:

feast-mcp \
  --feast-url http://localhost:6566 \
  --auth-mode oidc \
  --oidc-discovery-url https://keycloak.example.com/realms/feast/.well-known/openid-configuration \
  --oidc-client-id feast-mcp \
  --transport http --port 8000

Session storage (load-balanced OIDC)

The OIDC OAuth flow is a multi-request handshake (/authorize → IdP → /callback/token), and the proxy correlates those requests through server-side state: client registrations, in-flight transactions, authorization codes, and token mappings. By default this state lives in an on-disk, per-node store, so behind a load balancer with more than one replica a /callback can hit a replica that never saw the matching /authorize — and the login fails.

Point the proxy at a shared backend to make the flow load-balancer safe. Backends are provided by py-key-value-aio: redis, valkey, postgresql, mongodb, disk, memory.

feast-mcp \
  --feast-url http://localhost:6566 \
  --auth-mode oidc \
  --oidc-discovery-url https://keycloak.example.com/realms/feast/.well-known/openid-configuration \
  --oidc-client-id feast-mcp \
  --session-storage-backend redis \
  --transport http --port 8000

The backend can also be set via FEAST_MCP_SESSION_STORAGE_BACKEND. Backend-specific connection options go in feast_mcp.yaml under session_storage.options and are passed through to the underlying store:

session_storage:
  backend: redis          # redis | valkey | postgresql | mongodb | disk | memory
  options:
    url: redis://localhost:6379

Install the extra for your chosen backend, e.g. pip install 'py-key-value-aio[redis]'. When no backend is configured, the proxy falls back to FastMCP's default on-disk store (fine for a single replica). memory and disk are not shared across processes — the server logs a warning if you select them.

Observability (logging + OpenTelemetry)

Logs always go to the console (stderr — stdout is reserved by the MCP stdio transport). When an OTLP endpoint is configured, the same log lines are also exported to your OpenTelemetry backend for visibility.

FastMCP, the MCP SDK, and the web server (uvicorn / gunicorn) log to their own logger trees. Those are bridged onto the same handlers, so their output lands on the console and in OpenTelemetry alongside the server's own logs — you don't lose framework logs.

Every tool call passes through get_auth_token(), which logs one line of auth context per request: the authenticated user (from the token claims — preferred_username/email/sub and client_id), the client IP (honoring X-Forwarded-For / X-Real-IP behind a proxy), and the request (METHOD /path). Unauthenticated requests are logged too. Example:

INFO feast_mcp.auth [trace=4bf92f3577b34da6a3ce929d0e0e4736] Authenticated request: user=alice (client_id=feast-mcp) ip=10.0.0.7 request=POST /mcp

Request correlation (trace ids). Each incoming HTTP request is wrapped in an OpenTelemetry span, so every log line emitted while handling that request — tool dispatch, the auth line above, upstream calls — carries the same trace_id. This lets you group "all logs for one request" in your backend (trace_id field in JSON logs, [trace=…] in text logs). When the OTEL SDK is installed the id is a real W3C trace id and the span itself is exported too, so logs and traces line up and you can jump between them. Without the SDK, a generated per-request id is used so console logs are still groupable.

OTEL export is optional — install the extra:

pip install 'feast-mcp[otel]'

Enable it by pointing at an OTLP collector:

feast-mcp \
  --feast-url http://localhost:6566 \
  --log-level INFO \
  --log-format json \
  --otel-endpoint http://localhost:4317 \
  --transport http --port 8000

Setting --otel-endpoint turns export on automatically. Configuration resolves from CLI args, then environment variables, then feast_mcp.yaml:

Setting

CLI

Env var

Default

Log level

--log-level

FEAST_MCP_LOG_LEVEL

INFO

Log format (text/json)

--log-format

FEAST_MCP_LOG_FORMAT

text

Console logging

FEAST_MCP_LOG_STDIO

true

OTLP endpoint

--otel-endpoint

FEAST_MCP_OTEL_ENDPOINT / OTEL_EXPORTER_OTLP_ENDPOINT

Protocol (grpc/http)

--otel-protocol

FEAST_MCP_OTEL_PROTOCOL / OTEL_EXPORTER_OTLP_PROTOCOL

grpc

Service name

--otel-service-name

FEAST_MCP_OTEL_SERVICE_NAME / OTEL_SERVICE_NAME

feast-mcp

OTLP headers

FEAST_MCP_OTEL_HEADERS / OTEL_EXPORTER_OTLP_HEADERS

Standard OTEL_* variables are honored as a fallback, so existing OpenTelemetry tooling works unchanged. Equivalent feast_mcp.yaml:

observability:
  level: INFO
  format: json
  stdio: true
  otel_endpoint: http://localhost:4317
  otel_protocol: grpc       # grpc | http
  otel_service_name: feast-mcp

If OTEL is requested but the SDK/exporter isn't installed, the server logs a warning and continues with console logging only.

See examples/otel_demo for a runnable setup with a local OpenTelemetry Collector that prints the exported log records.

IDE / client configuration

Local (client launches feast-mcp over stdio)

The client starts the server as a subprocess and talks to it over stdio — no port, no running server to manage:

{
  "mcpServers": {
    "feast": {
      "command": "feast-mcp",
      "args": [
        "--feast-url", "http://localhost:6566",
        "--registry-url", "http://localhost:8080"
      ]
    }
  }
}

Feature server only:

{
  "mcpServers": {
    "feast": {
      "command": "feast-mcp",
      "args": ["--feast-url", "http://localhost:6566"]
    }
  }
}

Registry only:

{
  "mcpServers": {
    "feast": {
      "command": "feast-mcp",
      "args": ["--registry-url", "http://localhost:8080"]
    }
  }
}

Remote (paste a URL — no local command)

When the server is already running over HTTP (started with --transport http or deployed behind a load balancer), the client doesn't launch anything — just point it at the URL. Nothing is installed locally.

The endpoint depends on the transport the server was started with:

Server transport

Endpoint to paste

http / streamable-http

http://<host>:<port>/mcp

sse

http://<host>:<port>/sse

{
  "mcpServers": {
    "feast": {
      "url": "http://localhost:8000/mcp"
    }
  }
}

For a deployed server, use its public URL (HTTPS recommended):

{
  "mcpServers": {
    "feast": {
      "url": "https://feast-mcp.example.com/mcp"
    }
  }
}

If the server runs with --auth-mode oidc, the client performs the browser login automatically on first connect. For a server that expects a bearer token directly, clients that support custom headers can send one:

{
  "mcpServers": {
    "feast": {
      "url": "https://feast-mcp.example.com/mcp",
      "headers": {
        "Authorization": "Bearer <token>"
      }
    }
  }
}

Some clients name the fields differently (e.g. "type": "http" / "transport": "sse"). Check your client's MCP docs if url alone isn't recognized.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A feature-rich gateway and proxy that federates MCP, REST, and gRPC services into a unified endpoint for AI clients. It enables virtualization of legacy APIs as MCP-compliant tools while providing built-in security, rate-limiting, and OpenTelemetry observability.
    Apache 2.0
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for Flagsmith's Core and SDK APIs, enabling management of feature flags and configurations.
    161,179
    BSD 3-Clause
  • A
    license
    Not graded
    quality
    B
    maintenance
    Centralized MCP control plane that proxies multiple upstream MCP servers with tool namespacing, filtering, policy enforcement, audit logging, and health checks.
    16
    MIT

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/patelchaitany/feast-mcp'

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