Skip to content

Commit 0efab5c

Browse files
patelchaitanyntkathole
authored andcommitted
feat: Add standalone MCP server as a first-class component
* feat: Add standalone feast mcp server Adds `feast mcp`, a Model Context Protocol server that runs in its own process and proxies to a running Feast deployment over HTTP. It holds no registry or online store of its own; two sub-servers are mounted behind a single MCP endpoint, each only when its upstream URL is configured: - `features` -> the Python feature server (online features, vector search, push, materialization) - `registry` -> the REST registry server (feature views, entities, data sources, lineage) This is distinct from `feast serve` with `mcp_enabled: true`, which mounts an OpenAPI-derived MCP endpoint inside the feature server itself. Settings resolve CLI > environment > feast_mcp.yaml > defaults. The server enforces no RBAC of its own: it forwards the caller's bearer token upstream and lets Feast apply its permission model. `--auth-mode oidc` additionally fronts an OIDC provider so IDE clients can complete a browser login. The `feast mcp` subcommand resolves lazily so that FastMCP is not imported by unrelated commands such as `feast apply`, and degrades to a clear error when the optional `mcp-server` extra is absent. Two CI pins had to move to make the dependency set solvable. fastmcp requires httpx>=0.28.1, which the ci extra pinned down to 0.27.2 because python-keycloak <4.7.3 passed the `proxies` argument httpx removed in 0.28 (python-keycloak#623); raising the python-keycloak floor to >=4.7.3 lifts that constraint. virtualenv is unpinned from 20.23.0 to >=20.26,<21. Signed-off-by: Chaitany Patel <[email protected]> * feat: Add the MCP server as a served component in feast-operator Setting `spec.services.mcpServer` adds a dedicated `feast mcp` container to the FeatureStore deployment, exposed on its own Service on port 8100. The container runs in the same pod as the online and registry servers, so it reaches both over localhost. The operator owns only `--host` and `--port`, so they always match the generated Service. Everything else (transport, upstream URLs, auth, observability) is read from a feast_mcp.yaml supplied in a ConfigMap and mounted read-only at /etc/feast/mcp. A CEL rule enforces that at least one upstream is actually available: either onlineStore is present and not disabled, or registry.local.server.restAPI is true. Readiness is reported on the McpServer status condition, and the Service hostname on status.serviceHostnames.mcpServer. Operator-managed TLS is not yet supported for this container; the `tls` field is ignored. Signed-off-by: Chaitany Patel <[email protected]> * docs: Add standalone MCP server reference and example Adds the reference page for `feast mcp`, covering the CLI options, the feast_mcp.yaml schema and its environment equivalents, the available tools, both auth modes, and deployment with the Feast Operator. Links it from SUMMARY.md and the feature-servers index, and cross-references it from the existing MCP feature server page so the two are not confused. Adds examples/feast_mcp_server, an end-to-end walkthrough that starts a local feature store, runs the MCP server against it, and calls its tools from a client, plus the Kubernetes equivalent deployed by the operator. Signed-off-by: Chaitany Patel <[email protected]> * test: Add unit tests for the standalone feast mcp server Covers the parts that are easy to get wrong and invisible until someone else's deployment breaks: - config resolution, asserting CLI > env > yaml > default one rung at a time, because a stray CLI default silently outranks feast_mcp.yaml - token forwarding in both auth modes, including that a passthrough caller's bearer token still reaches Feast - that upstream denials surface as MCP tool errors rather than being handed to the model as feature data - a request matrix over every tool, asserting the upstream request each one builds and that optional arguments are omitted rather than sent as null Adds the operator-side controller test for the mcpserver container, Service, ConfigMap mount and status conditions. Signed-off-by: Chaitany Patel <[email protected]> * build: Relock Python requirements Regenerates the locked requirement sets for all supported Python versions so that the new `mcp-server` extra, and the dependency floors it forces, are reflected in the lock files. Signed-off-by: Chaitany Patel <[email protected]> * build: Add the feast-mcp container image Packages `feast mcp` as a container whose entrypoint is the server itself. It is a thin wrapper over the feature-server image, which already installs feast[minimal] and therefore everything the MCP server needs, so this only sets the entrypoint and inherits the UBI base and the arbitrary-uid permission setup. BASE_IMAGE and BASE_TAG select the feature-server image to build on, so the same Dockerfile serves a local build, a build against a published tag, and a downstream rebuild from another repository. TMPDIR is set to /dev/shm because Python needs a writable temp dir and the usual candidates are all read-only under readOnlyRootFilesystem. Also adds test-python-unit-mcp for iterating on the MCP server's tests alone; they are already covered by test-python-unit. Signed-off-by: Chaitany Patel <[email protected]> * fix: Address review feedback on the standalone MCP server - Treat an omitted onlineStore as available in the mcpServer CEL rule, matching the operator's default online feature server, and add admission tests for the omitted, disabled and REST-registry-only cases. - Decode JSON text in the demo client's CallToolResult fallback so registry discovery works on older fastmcp versions. - Describe the supported kubernetes auth mode in the example README and align the MCP docs, sample configs and API reference with the code. Signed-off-by: Chaitany Patel <[email protected]> * fix: Address review comments on the standalone MCP server - Reject unknown auth modes instead of falling back to passthrough - Percent-encode tool arguments used as URL path segments - Log the socket peer IP instead of trusting X-Forwarded-For/X-Real-IP - Build a fresh FastMCP instance per run and drop unused config helpers - Default the operator-managed MCP transport to http when no config is given - Reject an empty mcpServer.config.configMapRef.name at admission - Require BASE_TAG for the feast-mcp image instead of defaulting to latest - Keep the MCP API reference rows on one line and refresh the secrets baseline - Only recurse into real packages in the doctest walker so feast.mcp does not collide with the mcp SDK Signed-off-by: Chaitany Patel <[email protected]> --------- Signed-off-by: Chaitany Patel <[email protected]>
1 parent 0ed3285 commit 0efab5c

66 files changed

Lines changed: 27843 additions & 16776 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.secrets.baseline‎

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Makefile‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,14 @@ test-python-unit: ## Run Python unit tests (use pattern=<pattern> to filter test
176176
--cov-report=term-missing \
177177
sdk/python/tests/unit
178178

179+
# Standalone `feast mcp` server (feast[mcp-server] extra). Already covered by
180+
# test-python-unit; this target is for iterating on the MCP server alone.
181+
test-python-unit-mcp: ## Run unit tests for the standalone `feast mcp` server
182+
uv run python -m pytest -n 4 --color=yes $(if $(pattern),-k "$(pattern)") \
183+
--cov=sdk/python/feast/mcp \
184+
--cov-report=term-missing \
185+
sdk/python/tests/unit/mcp
186+
179187
# Fast unit tests only
180188
test-python-unit-fast: ## Run fast unit tests only (no external dependencies)
181189
uv run python -m pytest sdk/python/tests/unit -n auto -x --tb=short

‎docs/SUMMARY.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
* [Retrieval Augmented Generation (RAG) with Feast](tutorials/rag-with-docling.md)
6262
* [RAG Fine Tuning with Feast and Milvus](../examples/rag-retriever/README.md)
6363
* [MCP - AI Agent Example](../examples/mcp_feature_store/README.md)
64+
* [Standalone MCP Server Example](../examples/feast_mcp_server/README.md)
6465
* [Feast-Powered AI Agent](../examples/agent_feature_store/README.md)
6566
* [Demo Notebooks](tutorials/demo-notebooks.md)
6667
* [Feature Quality Monitoring Quickstart](../examples/monitoring/monitoring-quickstart.ipynb)
@@ -206,6 +207,7 @@
206207
* [Python feature server](reference/feature-servers/python-feature-server.md)
207208
* [\[Alpha\] Go feature server](reference/feature-servers/go-feature-server.md)
208209
* [MCP Feature Server](reference/feature-servers/mcp-feature-server.md)
210+
* [Standalone MCP server](reference/feature-servers/mcp-server.md)
209211
* [Offline Feature Server](reference/feature-servers/offline-feature-server.md)
210212
* [Registry server](reference/feature-servers/registry-server.md)
211213
* [\[Beta\] Web UI](reference/alpha-web-ui.md)

‎docs/reference/feature-servers/README.md‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,12 @@ Feast users can choose to retrieve features from a feature server, as opposed to
1616

1717
{% content-ref url="registry-server.md" %}
1818
[registry-server.md](registry-server.md)
19-
{% endcontent-ref %}
19+
{% endcontent-ref %}
20+
21+
{% content-ref url="mcp-feature-server.md" %}
22+
[mcp-feature-server.md](mcp-feature-server.md)
23+
{% endcontent-ref %}
24+
25+
{% content-ref url="mcp-server.md" %}
26+
[mcp-server.md](mcp-server.md)
27+
{% endcontent-ref %}

‎docs/reference/feature-servers/mcp-feature-server.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
Feast can expose the Python Feature Server as an MCP (Model Context Protocol) server using `fastapi_mcp`. When enabled, MCP clients can discover and call Feast tools such as online feature retrieval.
66

7+
This mounts MCP inside the feature server process. For a separately deployable MCP server that proxies both the feature server and the registry, see the [Standalone MCP server](mcp-server.md), started with `feast mcp`.
8+
79
## Installation
810

911
```bash

0 commit comments

Comments
 (0)