Building Custom MCP Connectors for Snowflake: Data-to-Agent Bridging at Scale

Written by

in

# Building Custom MCP Connectors for Snowflake: Data-to-Agent Bridging at Scale

*How data architects wire Snowflake to LLM agents through Model Context Protocol — without turning the warehouse into an uncontrolled query surface.*

—

## 1. The Silo Problem: Why Agents Need Direct Warehouse Access

Every modern enterprise runs on the same contradiction. The data warehouse — Snowflake, in the most ambitious cases — is the single governed source of truth: product marts, customer 360 views, financial reporting, operational telemetry. Analysts reach it through BI tools, executives through dashboards. And the newest consumer — the LLM agent — has no reach at all.

That is the silo problem. Your agents are the most data-hungry workloads you have ever deployed, and the data they need most sits behind the most carefully governed perimeter you operate. The first integration patterns are all compromises. Exporting warehouse tables to CSV and stuffing snapshots into a vector store gives agents stale copies with no lineage. REST APIs built for screens expose coarse endpoints, not semantics. Retrieving documents *about* the data instead of the data itself is how agents end up confidently citing last quarter’s numbers.

The alternative — letting agents query Snowflake the way an analyst would — fails differently. The warehouse was built for trusted humans with MFA who exercise judgment about cost and cardinality. An LLM will happily emit a cartesian product across a billion-row fact table, request 40,000 rows when it needs a summary, and restate the same expensive query while hunting for phrasing its prompt accepts. Hand a model a JDBC connection string and you have not bridged the silo; you have opened a data-exfiltration-and-budget-incident design.

What agents need is not *direct* access in the literal sense. They need **structured access**: a typed, permission-scoped, cost-bounded interface that exposes the warehouse’s semantics without exposing its raw surface. That is precisely the gap the Model Context Protocol was designed to fill.

![OnlineCloud AI engineering solutions](https://www.onlinecloud.dev/assets/hero-company-V8Xps1Ae.png)

—

## 2. MCP for Data: Typed Resources and Row-Level Access

Model Context Protocol is the contract layer between LLM applications and the systems they operate. For data work, its three primitives map cleanly onto warehouse patterns:

– **Tools** become parameterized, read-only query operations — `get_demand_actuals`, `lookup_forecast_error`, `check_inventory_position` — each declared with a name, usage description, and strict JSON Schema input contract.
– **Resources** become dataset references addressed by stable URIs (`snowflake://analytics/demand/fcst_vs_actual`), loaded through the connector on demand rather than stuffed into a system prompt.
– **Prompts** become server-side templates encoding how a workflow should be performed — an analysis recipe for “explain this forecast miss,” versionable without touching client code.

The load-bearing decision: **the model proposes intent; the connector disposes as SQL**. A custom MCP connector never exposes a free-text query tool; every tool maps to a hand-written, parameterized statement against a curated view or mart — engineered, reviewed, and eval-tested by a human. That inversion is what stops prompt injection from becoming SQL injection, and why custom connectors beat generic text-to-SQL for production-critical workflows.

Snowflake’s first-party MCP server (built on Cortex Analyst) is excellent for ad hoc natural-language exploration on well-described schemas. At scale, though, three factors push architects toward custom connectors: **determinism** (a typed tool either succeeds or fails against its contract; free-form SQL is a distribution of outcomes), **row-level enforcement** (below), and **operational telemetry** (a named tool with known cardinality meters far more cleanly than an arbitrary statement).

Row-level access is where Snowflake shines and naive integrations die. Since 2022 Snowflake has shipped first-class **Row Access Policies (RAP)** and **Dynamic Data Masking** — governance enforced in the query engine, not application code. The connector authenticates the caller; the policy engine scopes every query:

“`sql
— Row Access Policy: a planner sees only their region’s rows
CREATE OR REPLACE ROW ACCESS POLICY mcp.rls_region
AS (ship_region VARCHAR) RETURNS BOOLEAN ->
CURRENT_USER() IN (
SELECT user_name FROM mcp.user_region_map
WHERE region = ship_region
)
OR IS_ROLE_IN_SESSION(‘MCP_PLANNER_GLOBAL’);

ALTER TABLE analytics.demand_actuals
ADD ROW ACCESS POLICY mcp.rls_region ON (ship_region);
“`

The agent session is then *physically incapable* of reading another region’s demand — not because the prompt says “don’t,” but because the predicate is compiled into the query plan by Snowflake’s kernel. Defense at the data layer, never the prompt layer, is the rule for any regulated or commercially sensitive warehouse.

—

## 3. Snowflake Integration Architecture: VPC, RBAC, OAuth

Production connectors follow one architecture, regardless of model vendor: the MCP server runs **inside your network boundary**, and Snowflake never sees a query from a model — it sees queries from a service role whose sole purpose is enforcing policy.

**Network (VPC).** MCP servers deploy into your own VPC with no public ingress. The connector reaches Snowflake over private connectivity — AWS PrivateLink, Azure Private Link, or Google Private Service Connect — and Snowflake’s **network policies** restrict the account to accept connections only from your VPC CIDR and egress IPs. The agent host (Claude, a GPT-4-class model, or an open-weights deployment inside the same VPC) talks to the MCP server over streamable HTTP; the server mediates every byte of data movement. The blast radius of any compromise is one connector, one role, one network path — not the warehouse.

**RBAC.** The connector runs as a purpose-built principal with least privilege expressed as Snowflake roles and grants — never as the account owner and never with write access in the first release:

– Dedicated roles per surface (e.g. `MCP_DEMAND_READ`) granted `USAGE` and `SELECT` on curated views and marts only — never on base tables the agent path does not need.
– A dedicated virtual warehouse (`MCP_PLANNER_WH`) with aggressive `AUTO_SUSPEND` (60 seconds) and `AUTO_RESUME` on, so idle agent traffic costs nothing.
– Statement-level guardrails set at session start: `STATEMENT_TIMEOUT_IN_SECONDS = 30`, `USE_CACHED_RESULT = TRUE`, and a hard row cap enforced in every tool’s `LIMIT`.

**OAuth.** Identity flows end to end. For human-in-the-loop sessions, the corporate IdP (Okta, Entra ID, Ping) issues tokens via **Authorization Code + PKCE**; for unattended agents, the connector uses **client credentials or Snowflake key-pair authentication** with short-lived, rotating keys — no long-lived secrets in config files. Snowflake’s external OAuth maps the validated identity to a Snowflake user and role, so the warehouse’s audit trail inherits real caller identity. The three-layer mapping — token scope → MCP tool group → Snowflake role — means revoking a token takes effect immediately while no warehouse grant ever changes.

Finally, tag everything. Every session sets a query tag carrying the agent conversation’s correlation ID, so Snowflake’s own telemetry becomes the audit spine:

“`sql
ALTER SESSION SET QUERY_TAG =
‘mcp:session_9f3c2a|tool=get_demand_actuals|user=p.sundaram@beaconlogistics.com’;
“`

Now `QUERY_HISTORY` and `ACCOUNT_USAGE` answer the compliance question every CFO eventually asks: *which agent, acting for which person, ran which query, at what cost, and touched which rows?*

—

## 4. Optimization: Caching, Throttling, and Cost Ceilings

Snowflake’s economics reward disciplined access patterns. Compute is metered per second per warehouse — but the platform gives you unusually powerful levers if you design for them.

**Caching, in three layers.** First, Snowflake’s own **result cache** returns identical queries in milliseconds for up to 24 hours, consuming zero additional compute. This is the hidden argument for typed tools: LLM-generated SQL never repeats itself, so it never hits the result cache; hand-written parameterized tools, queried repeatedly with the same arguments, hit it constantly. Second, cache at the connector for datasets with a freshness budget — an agent checking last week’s shipments does not need sub-second warehouse truth, and a 15-minute TTL with a staleness header in the tool response cuts warehouse load dramatically. Third, pre-aggregate: expose marts (daily demand by SKU-region, forecast error by lane) so agents query 10,000-row summaries instead of 500-million-row detail. The warehouse stays the source of truth; the connector just stops asking it questions it already answered.

**Throttling.** Concurrency is the cost multiplier, because warehouses scale up and out to serve it. The connector enforces per-tool, per-session, and per-tenant rate limits before anything reaches the warehouse — a retrying agent exhausts its own budget, not your credits. Statement timeouts and the warehouse’s **statement queuing** provide backpressure; a well-designed connector fails closed with a structured error (“demand history query exceeded 30s budget; try a narrower date range”) rather than scaling the warehouse to satisfy a misbehaving agent.

**Cost ceilings.** Snowflake **resource monitors** are the non-negotiable safety net: a monthly credit quota on the agent warehouse that, when breached, suspends it automatically. Set the monitor the day the warehouse is created — not after the first surprise invoice:

“`sql
CREATE RESOURCE MONITOR mcp_forecast_monthly
WITH CREDIT_QUOTA = 120
FREQUENCY = MONTHLY
START_TIMESTAMP = IMMEDIATELY;

ALTER WAREHOUSE mcp_planner_wh SET RESOURCE_MONITOR = mcp_forecast_monthly;
“`

On top of warehouse-level monitors, the connector tracks **per-conversation budgets** — compute credits plus model tokens metered together as one dollar figure — and terminates a runaway agent loop when its session ceiling is hit. The discipline that makes this tractable is from Section 2: a bounded set of named tools with known cardinality is forecastable; a free-text SQL endpoint is not. You cannot cap a query surface you cannot predict.

—

## 5. Case Study: Logistics Demand Forecasting via Snowflake Agents

A national logistics provider — regional distribution centers, dedicated freight lanes, volume renegotiated quarterly — ran forecasting the way most mid-market operators do. Nightly batch jobs pushed shipment history from Snowflake into spreadsheets; planners spent the first two weeks of every month reconciling forecasts against actuals by hand; and the monthly S&OP cycle ran on numbers already stale by presentation.

OnlineCloud’s engagement followed the architecture above. Week one mapped the governed marts — shipment history, lane-level demand, customer contracts, a decade of forecast-versus-actual records — and wrote the eval defining “done”: the agent had to reproduce a planner’s regional exception list within a 5% margin, under a strict cost ceiling. Weeks two through six shipped a custom MCP connector exposing a small typed tool surface — `get_demand_history`, `get_forecast_accuracy`, `compare_plan_vs_actual`, `list_exception_lanes`, `draft_replenishment_note`. Every tool was read-only, bound to curated marts, scoped by a regional row access policy, and capped at a 30-second timeout.

The agent runs as a daily morning loop: pull yesterday’s shipment actuals, recompute forecast error (MAPE) by SKU and lane, flag exceptions against planner-set thresholds, and draft replenishment recommendations with supporting records cited — surfacing only the lanes that need human judgment. Regional planners review in a console; nothing ships without a human click. Because every query carries a `QUERY_TAG` with the planner’s identity and conversation ID, the audit trail doubles as the planning log.

The measured results, reported by the client’s Head of Data:

– **2.8x forecast accuracy** within two quarters, as the loop’s daily error feedback replaced a monthly, human-mediated correction cycle.
– Planning cycle compressed from two weeks to a daily cadence — exceptions are caught in hours, not at month-end reconciliation.
– **Warehouse cost stayed flat** despite the new workload: the typed tool surface, connector caching, and the resource monitor kept agent compute inside a predictable monthly envelope.
– The system **paid for itself within two months** — the inventory-carrying-cost savings from earlier exception detection exceeded the entire engagement cost, before counting the planner hours returned.

The lesson the client’s data team took away was architectural, not anecdotal: the connector’s value was less about the model and more about the discipline of the seam — typed tools, row-level policies, query tags, and a credit ceiling turned “give AI warehouse access” from a security review into a routine change request.

—

## 6. Handoff: The Senior Engineer’s Guide to Observability

The moment a Snowflake MCP connector becomes a platform service, it changes owners — from the architect who built it to the engineers who keep it alive at 3 a.m. A senior engineer’s handoff is not a README; it answers one question: *when this system misbehaves, how fast can the on-call engineer tell what happened, who did it, and what it cost?*

Instrument four things, and instrument them from day one:

**1. Correlation.** The query tag convention from Section 3 is the linchpin. Every agent conversation carries a correlation ID from the host through the MCP server into Snowflake’s `QUERY_HISTORY` and `ACCOUNT_USAGE`. When a planner reports “the agent gave me a wrong number this morning,” the on-call engineer runs one query — `SELECT * FROM snowflake.account_usage.query_history WHERE query_tag LIKE ‘%session_9f3c2a%’` — and replays the exact statements, arguments, and results the agent saw. If the model did it, a human can replay it.

**2. Cost.** Meter per-tool dollar cost, not just latency. `WAREHOUSE_METERING_HISTORY` gives warehouse credit burn; the connector logs token spend per tool call; the two merge into the metric that matters: **cost per resolved request**. Alert on the cost *rate*, not just the monthly total — a resource monitor fires after the damage; a per-tool cost anomaly alert fires while the agent loop is still running.

**3. Behavior.** Track cache hit ratio (collapsing cache means the tool surface drifted from what agents actually ask), p95 latency per tool, error rate per tool, and schema-validation failure spikes — a sudden burst of malformed tool calls is often the first sign of prompt-injection probing. Export tool calls as OpenTelemetry spans so they trace into the same observability platform as the rest of your estate — the connector is just another service, with unusually interesting semantics.

**4. Correctness.** Maintain the eval suite as a regression gate, checked into the repo and run on every schema change. When a column is renamed or a mart’s grain shifts, the eval fails *before* planners see hallucinations — and the diff names the broken tool contract. An agent you cannot measure is a liability you cannot price; an eval you do not run is a memo.

Finally, write runbooks for the failures you can predict: resource-monitor suspension (re-enable only after human review of the offending session), OAuth token rotation (automated, zero-downtime), cold-cache latency after a mart refresh (expected; document the window), and prompt-injection response (freeze the affected tools, replay the session from query tags, patch the tool’s data surface). Hand off dashboards, not documents — and keep the architect on call for the first month. The system gets sharper month over month because the instrumentation tells you exactly where to sharpen it.

—

## Ready to Bridge Snowflake to Your Agents?

OnlineCloud is a US-based engineering studio that builds MCP-native, agentic AI systems on Snowflake, Oracle, MS SQL Server, and Postgres — with row-level access policies, OAuth at the edge, resource monitors, and eval suites built in, not bolted on. Senior engineers only, no offshore handoffs, and a working vertical slice in your environment within six to ten weeks.

**Talk to an OnlineCloud architect about your Snowflake agent roadmap** — email [contact@onlinecloud.dev](mailto:contact@onlinecloud.dev) or visit [onlinecloud.dev](https://www.onlinecloud.dev/). Free initial consultation, response within 24 hours.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *