Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ba1feb6
Revert "fix: Update milvus connect function to work with remote insta…
franciscojavierarceo May 29, 2025
86b6a20
test: Add Operator E2E tests for Feast Apply and Materialize function…
Srihari1192 May 29, 2025
1ed32d4
fix: Updating milvus connect function to work with remote instance (#…
Fiona-Waters May 30, 2025
2bb7248
feat: Add MCP support to feature server configuration
YassinNouh21 May 31, 2025
479eb7a
fix linter
YassinNouh21 May 31, 2025
edbb58f
add example
YassinNouh21 May 31, 2025
a8b17e1
test: add test cases for the mcp server
YassinNouh21 May 31, 2025
bc00dba
fix linter
YassinNouh21 May 31, 2025
e3a30d7
formatting
YassinNouh21 May 31, 2025
8a644b5
docs: update README for MCP setup instructions
YassinNouh21 May 31, 2025
08c4dd6
fix: update transformation service endpoint and refactor MCP integration
YassinNouh21 May 31, 2025
6c6f6ee
feat: add Model Context Protocol (MCP) support and update documentation
YassinNouh21 May 31, 2025
c3043c1
fix: update entity key serialization version and improve README clarity
YassinNouh21 May 31, 2025
8b26804
Merge branch 'master' into feat/mcp
YassinNouh21 May 31, 2025
1bec81f
fix: refactor MCP imports to use the correct module path
YassinNouh21 May 31, 2025
8aa31a7
feat: Add MCP server implementation files
YassinNouh21 Jun 1, 2025
9409e6a
test: MCP server unit tests and integration tests
YassinNouh21 Jun 1, 2025
426744b
fix formatting
YassinNouh21 Jun 1, 2025
c40809b
fix formatting
YassinNouh21 Jun 1, 2025
6135cde
adding compiled requirements
franciscojavierarceo Jun 4, 2025
b31cc87
Merge branch 'master' into feat/mcp
franciscojavierarceo Jun 4, 2025
b9a84f3
fix linter
franciscojavierarceo Jun 4, 2025
dc71713
reverting duckdb change
franciscojavierarceo Jun 4, 2025
ba6f51a
needed to do file source and duckdb
franciscojavierarceo Jun 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
* [Validating historical features with Great Expectations](tutorials/validating-historical-features.md)
* [Building streaming features](tutorials/building-streaming-features.md)
* [Retrieval Augmented Generation (RAG) with Feast](tutorials/rag-with-docling.md)
* [MCP - AI Agent Example](../examples/mcp_feature_store/README.md)

## How-to Guides

Expand Down Expand Up @@ -147,6 +148,7 @@
* [Feature servers](reference/feature-servers/README.md)
* [Python feature server](reference/feature-servers/python-feature-server.md)
* [\[Alpha\] Go feature server](reference/feature-servers/go-feature-server.md)
* [MCP Feature Server](reference/feature-servers/mcp-feature-server.md)
* [Offline Feature Server](reference/feature-servers/offline-feature-server.md)
* [Registry server](reference/feature-servers/registry-server.md)
* [\[Beta\] Web UI](reference/alpha-web-ui.md)
Expand Down
49 changes: 49 additions & 0 deletions docs/getting-started/genai.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,62 @@ This integration enables:
- Generating embeddings for millions of text chunks
- Efficiently materializing features to vector databases
- Scaling RAG applications to enterprise-level document repositories

## Model Context Protocol (MCP) Support

Feast supports the Model Context Protocol (MCP), which enables AI agents and applications to interact with your feature store through standardized MCP interfaces. This allows seamless integration with LLMs and AI agents for GenAI applications.

### Key Benefits of MCP Support

* **Standardized AI Integration**: Enable AI agents to discover and use features dynamically without hardcoded definitions
* **Easy Setup**: Add MCP support with a simple configuration change and `pip install feast[mcp]`
* **Agent-Friendly APIs**: Expose feature store capabilities through MCP tools that AI agents can understand and use
* **Production Ready**: Built on top of Feast's proven feature serving infrastructure

### Getting Started with MCP

1. **Install MCP support**:
```bash
pip install feast[mcp]
```

2. **Configure your feature store** to use MCP:
```yaml
feature_server:
type: mcp
enabled: true
mcp_enabled: true
mcp_server_name: "feast-feature-store"
mcp_server_version: "1.0.0"
```

### How It Works

The MCP integration uses the `fastapi_mcp` library to automatically transform your Feast feature server's FastAPI endpoints into MCP-compatible tools. When you enable MCP support:

1. **Automatic Discovery**: The integration scans your FastAPI application and discovers all available endpoints
2. **Tool Generation**: Each endpoint becomes an MCP tool with auto-generated schemas and descriptions
3. **Dynamic Access**: AI agents can discover and call these tools dynamically without hardcoded definitions
4. **Standard Protocol**: Uses the Model Context Protocol for standardized AI-to-API communication

### Available MCP Tools

The fastapi_mcp integration automatically exposes your Feast feature server's FastAPI endpoints as MCP tools. This means AI assistants can:

* **Call `/get-online-features`** to retrieve features from the feature store
* **Use `/health`** to check server status

For a complete example, see the [MCP Feature Store Example](../../examples/mcp_feature_store/).

## Learn More

For more detailed information and examples:

* [Vector Database Reference](../reference/alpha-vector-database.md)
* [RAG Tutorial with Docling](../tutorials/rag-with-docling.md)
* [Milvus Quickstart Example](https://github.com/feast-dev/feast/tree/master/examples/rag/milvus-quickstart.ipynb)
* [MCP Feature Store Example](../../examples/mcp_feature_store/)
* [MCP Feature Server Reference](../reference/feature-servers/mcp-feature-server.md)
* [Spark Data Source](../reference/data-sources/spark.md)
* [Spark Offline Store](../reference/offline-stores/spark.md)
* [Spark Batch Materialization](../reference/batch-materialization/spark.md)
77 changes: 77 additions & 0 deletions examples/mcp_feature_store/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Feast MCP Feature Server Example

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this!

I'd also add this to the GenAI docs and make it an extra that we enable with pip install feast[mcp]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@franciscojavierarceo done can u check it


This example demonstrates how to enable MCP (Model Context Protocol) support in Feast, allowing AI agents and applications to interact with your features through standardized MCP interfaces.

## Prerequisites

1. Python 3.8+
2. Feast installed
3. FastAPI MCP library

## Installation

1. Install Feast with MCP support:
```bash
pip install feast[mcp]
```

Alternatively, you can install the dependencies separately:
```bash
pip install feast
pip install fastapi_mcp
```

## Setup

1. Navigate to this example directory within your cloned Feast repository:
```bash
cd examples/mcp_feature_store
```

2. Initialize a Feast repository in this directory. We'll use the existing `feature_store.yaml` that's already configured for MCP:
```bash
feast init .
```
This will create a `data` subdirectory and a `feature_repo` subdirectory if they don't exist, and will use the `feature_store.yaml` present in the current directory (`examples/mcp_feature_store`).

3. Apply the feature store configuration:
```bash
cd feature_repo
feast apply
cd .. # Go back to examples/mcp_feature_store for the next steps
```

## Starting the MCP-Enabled Feature Server

Start the Feast feature server with MCP support:

```bash
feast serve --host 0.0.0.0 --port 6566
```

If MCP is properly configured, you should see a log message indicating that MCP support has been enabled:

```
INFO:feast.feature_server:MCP support has been enabled for the Feast feature server
```

## Available MCP Tools

The fastapi_mcp integration automatically exposes your Feast feature server's FastAPI endpoints as MCP tools. This means AI assistants can:

- **Call `/get-online-features`** to retrieve features from the feature store
- **Use `/health`** to check server status


## Configuration Details

The key configuration that enables MCP support:

```yaml
feature_server:
type: mcp # Use MCP feature server type
enabled: true # Enable feature server
mcp_enabled: true # Enable MCP protocol support
mcp_server_name: "feast-feature-store"
mcp_server_version: "1.0.0"
```
22 changes: 22 additions & 0 deletions examples/mcp_feature_store/feature_store.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
project: feast_mcp_example
registry: data/registry.db
provider: local

online_store:
type: sqlite
path: data/online_store.db

offline_store:
type: file

# MCP Feature Server Configuration
feature_server:
type: mcp
enabled: true
mcp_enabled: true # Enable MCP support - defaults to false
mcp_server_name: "feast-feature-store"
mcp_server_version: "1.0.0"
feature_logging:
enabled: false

entity_key_serialization_version: 3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as mcp will only implement onlinstore, instead of make new section with feature_server is that possible we can add into into onlinstore section WDYT ?

online_store:
  type: sqlite
  path: data/online_store.db

  mcp:
    enabled: true
    server_name: "feast-feature-store"
    server_version: "1.0.0"
    feature_logging:
      enabled: false```

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While embedding MCP config in the online_store section might seem logical, I'd recommend using a separate feature_server section instead:

online_store:
  type: sqlite
  path: data/online_store.db

feature_server:
  type: mcp
  enabled: true
  mcp_enabled: true
  mcp_server_name: "feast-feature-store"
  mcp_server_version: "1.0.0"
  feature_logging:
    enabled: false

Why this approach is better:

  • MCP is a feature server protocol for API exposure, not an online store storage concern
  • Follows the same pattern as other feature server types (local, etc.)
  • The McpFeatureServerConfig class inherits from BaseFeatureServerConfig, indicating it's designed as a feature server component

What do u think @franciscojavierarceo @ntkathole

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm good with it.

Copy link
Contributor

@redhatHameed redhatHameed Jun 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of these 3 fields

type: mcp  
enabled: true  
mcp_enabled: true  

my suggestion was if we change the name for example mcp_server then maybe we don't required these field. you can look mcp_server section if user added that section then it will be enabled else by default it will disabled/null. Let me know if that make sense or the current approach is more better. Thanks

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What @redhatHameed suggested 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In short MCP online store config looks like:

feature_server:
  type: mcp
  mcp_server_name: "feast-feature-store"
  mcp_server_version: "1.0.0"
  feature_logging: enabled: false

No hassle of enabling explicitely.

Copy link
Contributor

@redhatHameed redhatHameed Jun 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even if we can make like, that will remove extra type field.

mcp_server:
  mcp_server_name: "feast-feature-store"
  mcp_server_version: "1.0.0"
  feature_logging: enabled: false

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@redhatHameed mind addressing in a follow up PR? I think this is good enough as an MVP

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@YassinNouh21 this item. Removing the type field from the mcp_server object.

5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ snowflake = [
"snowflake-connector-python[pandas]>=3.7,<4",
]
sqlite_vec = ["sqlite-vec==v0.1.6"]
mcp = ["fastapi_mcp"]

ci = [
"build",
Expand Down Expand Up @@ -162,13 +163,13 @@ ci = [
"types-setuptools",
"types-tabulate",
"virtualenv<20.24.2",
"feast[aws, azure, cassandra, clickhouse, couchbase, delta, docling, duckdb, elasticsearch, faiss, gcp, ge, go, grpcio, hazelcast, hbase, ibis, ikv, k8s, milvus, mssql, mysql, opentelemetry, spark, trino, postgres, pytorch, qdrant, redis, singlestore, snowflake, sqlite_vec]"
"feast[aws, azure, cassandra, clickhouse, couchbase, delta, docling, duckdb, elasticsearch, faiss, gcp, ge, go, grpcio, hazelcast, hbase, ibis, ikv, k8s, mcp, milvus, mssql, mysql, opentelemetry, spark, trino, postgres, pytorch, qdrant, redis, singlestore, snowflake, sqlite_vec]"
]
nlp = ["feast[docling, milvus, pytorch]"]
dev = ["feast[ci]"]
docs = ["feast[ci]"]
# used for the 'feature-server' container image build
minimal = ["feast[aws, gcp, snowflake, redis, go, mysql, postgres-c, opentelemetry, grpcio, k8s, duckdb, milvus]"]
minimal = ["feast[aws, gcp, snowflake, redis, go, mysql, postgres-c, opentelemetry, grpcio, k8s, duckdb, mcp, milvus]"]
minimal-sdist-build = [
"feast[minimal]",
"feast[ibis]",
Expand Down
30 changes: 30 additions & 0 deletions sdk/python/feast/feature_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ def get_app(
- `/materialize-incremental`: Materialize features incrementally
- `/chat`: Chat UI
- `/ws/chat`: WebSocket endpoint for chat
MCP Support:
- If MCP is enabled in feature server configuration, MCP endpoints will be added automatically
"""
proto_json.patch()
# Asynchronously refresh registry, notifying shutdown and canceling the active timer if the app is shutting down
Expand Down Expand Up @@ -490,9 +492,37 @@ async def websocket_endpoint(websocket: WebSocket):
with importlib_resources.as_file(static_dir_ref) as static_dir:
app.mount("/static", StaticFiles(directory=static_dir), name="static")

# Add MCP support if enabled in feature server configuration
_add_mcp_support_if_enabled(app, store)

return app


def _add_mcp_support_if_enabled(app, store: "feast.FeatureStore"):
"""Add MCP support to the FastAPI app if enabled in configuration."""
try:
# Check if MCP is enabled in feature server config
if (
store.config.feature_server
and hasattr(store.config.feature_server, "type")
and store.config.feature_server.type == "mcp"
and getattr(store.config.feature_server, "mcp_enabled", False)
):
from feast.infra.mcp_servers.mcp_server import add_mcp_support_to_app

mcp_server = add_mcp_support_to_app(app, store, store.config.feature_server)

if mcp_server:
logger.info("MCP support has been enabled for the Feast feature server")
else:
logger.warning("MCP support was requested but could not be enabled")
else:
logger.debug("MCP support is not enabled in feature server configuration")
except Exception as e:
logger.error(f"Error checking/adding MCP support: {e}")
# Don't fail the entire server if MCP fails to initialize


if sys.platform != "win32":
import gunicorn.app.base

Expand Down
9 changes: 9 additions & 0 deletions sdk/python/feast/infra/mcp_servers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# MCP (Model Context Protocol) server implementations for Feast

from .mcp_config import McpFeatureServerConfig
from .mcp_server import add_mcp_support_to_app

__all__ = [
"McpFeatureServerConfig",
"add_mcp_support_to_app",
]
27 changes: 27 additions & 0 deletions sdk/python/feast/infra/mcp_servers/mcp_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from typing import Literal, Optional

from pydantic import StrictBool, StrictStr

from feast.infra.feature_servers.base_config import BaseFeatureServerConfig


class McpFeatureServerConfig(BaseFeatureServerConfig):
"""MCP (Model Context Protocol) Feature Server configuration."""

# Feature server type selector
type: Literal["mcp"] = "mcp"

# Enable MCP server support - defaults to False as requested
mcp_enabled: StrictBool = False

# MCP server name for identification
mcp_server_name: StrictStr = "feast-mcp-server"

# MCP server version
mcp_server_version: StrictStr = "1.0.0"

# Optional MCP transport configuration
mcp_transport: Optional[StrictStr] = None

# The endpoint definition for transformation_service (inherited from base)
transformation_service_endpoint: StrictStr = "localhost:6566"
58 changes: 58 additions & 0 deletions sdk/python/feast/infra/mcp_servers/mcp_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""
MCP (Model Context Protocol) integration for Feast Feature Server.

This module provides MCP support for Feast by integrating with fastapi_mcp
to expose Feast functionality through the Model Context Protocol.
"""

import logging
from typing import Optional

from feast.feature_store import FeatureStore

logger = logging.getLogger(__name__)

try:
from fastapi_mcp import FastApiMCP

MCP_AVAILABLE = True
except ImportError:
logger.warning(
"fastapi_mcp is not installed. MCP support will be disabled. "
"Install it with: pip install fastapi_mcp"
)
MCP_AVAILABLE = False
# Create placeholder classes for testing
FastApiMCP = None


def add_mcp_support_to_app(app, store: FeatureStore, config) -> Optional["FastApiMCP"]:
"""Add MCP support to the FastAPI app if enabled in configuration."""
if not MCP_AVAILABLE:
logger.warning("MCP support requested but fastapi_mcp is not available")
return None

try:
# Create MCP server from the FastAPI app
mcp = FastApiMCP(
app,
name=getattr(config, "mcp_server_name", "feast-feature-store"),
description="Feast Feature Store MCP Server - Access feature store data and operations through MCP",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@YassinNouh21 can we check if we can use other parameters like

describe_full_response_schema=True, 
describe_all_responses=True,  

https://github.com/tadata-org/fastapi_mcp/blob/main/examples/02_full_schema_description_example.py#L13-L19

)

# Mount the MCP server to the FastAPI app
mcp.mount()

logger.info(
"MCP support has been enabled for the Feast feature server at /mcp endpoint"
)
logger.info(
f"MCP integration initialized for {getattr(config, 'mcp_server_name', 'feast-feature-store')} "
f"v{getattr(config, 'mcp_server_version', '1.0.0')}"
)

return mcp

except Exception as e:
logger.error(f"Failed to initialize MCP integration: {e}")
return None
2 changes: 1 addition & 1 deletion sdk/python/feast/infra/offline_stores/duckdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def _write_data_source(
prev_schema = (
DeltaTable(file_options.uri, storage_options=storage_options)
.schema()
.to_pyarrow()
.to_arrow()
)
table = table.cast(ibis.Schema.from_pyarrow(prev_schema))
write_mode = "append"
Expand Down
2 changes: 1 addition & 1 deletion sdk/python/feast/infra/offline_stores/file_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def get_table_column_names_and_types(
schema = (
DeltaTable(self.path, storage_options=storage_options)
.schema()
.to_pyarrow()
.to_arrow()
)
else:
raise Exception(f"Unknown FileFormat -> {self.file_format}")
Expand Down
1 change: 1 addition & 0 deletions sdk/python/feast/repo_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@

FEATURE_SERVER_CONFIG_CLASS_FOR_TYPE = {
"local": "feast.infra.feature_servers.local_process.config.LocalFeatureServerConfig",
"mcp": "feast.infra.mcp_servers.mcp_config.McpFeatureServerConfig",
}

ALLOWED_AUTH_TYPES = ["no_auth", "kubernetes", "oidc"]
Expand Down
Loading