Snowflake Managed MCP Server
README.md
# Snowflake Managed MCP Server
A lean, security-first [MCP](https://modelcontextprotocol.io) server that exposes
**governed Snowflake data** and **Cortex AI** to AI agents (e.g. agents built in
Google **Gemini Enterprise**). See [`CLAUDE.md`](./CLAUDE.md) for the full
architecture and security model.
> **Read-only by design.** No DDL/DML. Access is restricted to an allow-list of
> governed 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 and
> was left out of v0.1 to avoid shipping an untested HTTP client. The SQL-based
> Cortex 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
```bash
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
```bash
# 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 at
runtime from `.env` — never baked into the image.
```bash
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`. In
production, place the SSE port behind a gateway enforcing mTLS/OAuth.
## Test
```bash
pip install pytest
pytest # all guardrail tests
pytest tests/test_security.py::test_rejects_dangerous_sql # a single test
```
## Security notes
- Set `MCP_ALLOWED_OBJECTS` to fully-qualified governed views only — an empty
allow-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_ROLE` must be least-privilege (read-only on
governed views). MCP guardrails are defense-in-depth, not a substitute for it.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues