Snowflake Managed MCP Server
A lean, security-first MCP server that exposesgoverned Snowflake data and Cortex AI to AI agents (e.g. agents built inGoogle Gemini Enterprise). See CLAUDE.md for the fullarchitecture and security model.
Read-only by design. No DDL/DML. Access is restricted to an allow-list ofgoverned views and enforced again by a least-privilege Snowflake role.
Tools
| Tool | What it does |
|---|---|
list_datasets |
List allow-listed governed datasets agents may query |
describe_dataset |
Column names/types for one allow-listed dataset |
run_query |
Run a single read-only SELECT/WITH query (row-capped, timed out) |
cortex_search |
Semantic retrieval over an approved Cortex Search service |
cortex_complete |
LLM completion via SNOWFLAKE.CORTEX.COMPLETE (allow-listed models) |
Cortex Analyst (NL→SQL) is a planned addition; it uses a REST endpoint andwas left out of v0.1 to avoid shipping an untested HTTP client. The SQL-basedCortex tools above cover retrieval and completion today.
Transports
- stdio — stdin/stdout for a trusted local agent process (no network auth).
- sse — HTTP + Server-Sent Events, protected by bearer-token authentication(
MCP_SSE_BEARER_TOKENS). Refuses to start if no tokens are configured.
Setup
python -m venv .venv && source .venv/bin/activate
pip install -e .
cp .env.example .env # then fill in Snowflake creds, allow-list, and limits
Run
# Local trusted agent (stdio)
python -m snowflake_mcp --transport stdio
# Network agents (authenticated SSE)
python -m snowflake_mcp --transport sse
# Agents connect to http://$MCP_SSE_HOST:$MCP_SSE_PORT/sse with header:
# Authorization: Bearer <one of MCP_SSE_BEARER_TOKENS>
Run with Docker (primary deployment)
The server is operated as a container service over SSE. Secrets are injected atruntime from .env — never baked into the image.
cp .env.example .env # fill in creds, MCP_SSE_BEARER_TOKENS, and MCP_BEARER_TOKEN
docker compose up --build server # start the MCP server (SSE on 127.0.0.1:8080)
docker compose run --rm client # run the example client against it
The image runs as a non-root user and publishes only to 127.0.0.1. Inproduction, place the SSE port behind a gateway enforcing mTLS/OAuth.
Test
pip install pytest
pytest # all guardrail tests
pytest tests/test_security.py::test_rejects_dangerous_sql # a single test
Security notes
- Set
MCP_ALLOWED_OBJECTSto fully-qualified governed views only — an emptyallow-list means the server can read nothing (safe default). - Prefer Snowflake key-pair auth; password is a dev-only fallback.
- The Snowflake role in
SNOWFLAKE_ROLEmust be least-privilege (read-only ongoverned views). MCP guardrails are defense-in-depth, not a substitute for it.