Snowflake MCP Server: Managed and Self-Hosted Options

Snowflake now runs its own MCP server inside your account, and the open-source Snowflake-Labs server is deprecated. How the managed server works, Cortex tools vs SQL, OAuth sign-in, a least-privilege role, read-only SQL, and connecting it to Claude Code.

7 min read

A Snowflake MCP server lets an AI assistant ask your Snowflake account questions through tools: a Cortex Agent, a Cortex Analyst semantic view, a Cortex Search service, your own functions and procedures, or plain SQL. Today there is one option to start with: the Snowflake-managed MCP server, which is generally available and runs inside your account, so there is nothing to host. You create it with SQL, choose its tools, sign in with OAuth, and control access with an ordinary Snowflake role. The open-source Snowflake-Labs server that many guides still describe is deprecated, and Snowflake asks its users to migrate.

The two options, and which one is current

  • The Snowflake-managed MCP server. Snowflake’s managed MCP server documentation (opens in a new tab) marks it generally available, not supported in government regions, and built on MCP revision 2025-11-25. It is a schema-level object, like a view, with its own URL in your account.
  • The Snowflake-Labs server. The Snowflake-Labs/mcp repository (opens in a new tab) now opens with a caution: the project is deprecated and no longer maintained, and users should move to the official server. It was a Python package you ran yourself with uvx snowflake-labs-mcp, driven by a YAML file, signing in through the Snowflake Python Connector.

If you run the Snowflake-Labs server today, it still starts, but nobody is fixing it. Treat it as legacy: plan the move, and do not build anything new on it. Its one lasting lesson is a good one. It let you allow or refuse SQL statement types one by one, with Select on and Drop off, and that habit carries straight over to the managed server’s read-only switch.

How the managed server is built

You create the server with the CREATE MCP SERVER SQL command (opens in a new tab), giving it a YAML specification that lists its tools. Each tool has a name, a type, the object it points at and a description the assistant reads when it decides which tool to call. Snowflake supports five tool types today:

  • CORTEX_AGENT_RUN: passes a question to a Cortex Agent, which picks among its own Analyst, Search and custom tools.
  • CORTEX_ANALYST_MESSAGE: turns a question into SQL against a semantic view and returns the statement. Semantic views only; the older semantic model files are not supported here.
  • CORTEX_SEARCH_SERVICE_QUERY: searches unstructured text through a Cortex Search service.
  • SYSTEM_EXECUTE_SQL: runs SQL the assistant writes.
  • GENERIC: exposes a user-defined function or stored procedure, with an input schema you declare.
SQL: a server that exposes one Cortex Agent
CREATE OR REPLACE MCP SERVER analytics.mcp.sales_mcp
  FROM SPECIFICATION $$
tools:
  - title: "Sales questions"
    name: "sales_agent"
    type: "CORTEX_AGENT_RUN"
    identifier: "analytics.mcp.sales_agent"
    description: "Answers questions about orders, revenue and pipeline."
$$;

The server’s address follows the pattern https://<account_url>/api/v2/databases/<database>/schemas/<schema>/mcp-servers/<name>. Use hyphens, not underscores, in the account host name; Snowflake warns that MCP clients fail to connect to hosts with underscores. SHOW MCP SERVERS, DESCRIBE MCP SERVER and DROP MCP SERVER manage it afterward.

The limits are worth knowing before you design around it. The server offers tools only: no resources, prompts or sampling. Each server holds at most 50 tools. Responses from the SQL and custom tools are cut off at 250 KB. MCP server objects are not replicated in failover groups, so a secondary account needs its own. Since August 20, 2026, tool call responses arrive as a Server-Sent Events stream, which clients that follow the current MCP specification handle without changes.

Cortex tools vs SQL

This is the main design choice. Snowflake’s own recommendation, for governed business questions, is to expose a single Cortex Agent as the only tool on a server. The agent uses the semantic views, verified queries and search services you gave it, so the numbers come out the same way every time, whoever asks.

The SQL tool is the opposite: the assistant writes whatever query it thinks answers the question. Snowflake warns that putting SYSTEM_EXECUTE_SQL on the same server as an agent lets the client bypass the agent’s semantic views and orchestration, and says that if you need direct SQL, you should put it on a separate server with its own least-privileged role. A rough guide:

  • Business users asking about revenue, churn or pipeline: one Cortex Agent, nothing else on that server.
  • An analyst who wants the assistant to explore tables: a separate SQL server, read-only, on a role that sees only the schemas in scope.
  • A repeated, fixed job, such as “refresh this summary”: a stored procedure exposed as a GENERIC tool, so the assistant supplies typed inputs and never writes the SQL.
  • A Cortex Agent’s responses include its reasoning, tool calls and search results, and can run to 200 KB or more. Set max_results on its search tools to keep them smaller.

Read-only SQL

The SQL tool takes three settings: read_only, query_timeout in seconds, and warehouse. read_only defaults to true, which allows only SELECT queries. Keep it that way, set a timeout, and point it at a small warehouse of its own so an enthusiastic assistant cannot slow anyone else’s work.

The SQL tool, read-only, on a separate server
tools:
  - title: "SQL (read-only)"
    name: "sql_readonly"
    type: "SYSTEM_EXECUTE_SQL"
    description: "Runs SELECT queries against the reporting schemas."
    config:
      read_only: true
      query_timeout: 60
      warehouse: "MCP_XS_WH"

As with any database, the switch is the second layer, and the role is the first. The general case, with grants, replicas and row limits, is in database MCP servers; everything there applies here.

Roles and least privilege

Access to the server does not give access to its tools. A role needs USAGE on the MCP server to connect and list tools, then a privilege on each thing a tool touches: USAGE on the agent or search service, SELECT on the semantic view, USAGE on the function or procedure. Snowflake’s pattern is a dedicated role granted only to the people who need it:

SQL: a role for the agent server
CREATE ROLE mcp_sales_reader;
GRANT DATABASE ROLE SNOWFLAKE.CORTEX_AGENT_USER TO ROLE mcp_sales_reader;
GRANT USAGE ON WAREHOUSE mcp_xs_wh TO ROLE mcp_sales_reader;
GRANT USAGE ON DATABASE analytics TO ROLE mcp_sales_reader;
GRANT USAGE ON SCHEMA analytics.mcp TO ROLE mcp_sales_reader;
GRANT USAGE ON MCP SERVER analytics.mcp.sales_mcp TO ROLE mcp_sales_reader;
GRANT USAGE ON AGENT analytics.mcp.sales_agent TO ROLE mcp_sales_reader;
GRANT ROLE mcp_sales_reader TO USER jordan;
  • Grant the agent’s own resources, such as its semantic view and search service, to the same role, and nothing more.
  • Never grant the role to PUBLIC, and never grant all current and future tables just to make a client work. Snowflake says both plainly.
  • An OAuth session uses the connecting user’s default role, so set DEFAULT_ROLE and DEFAULT_WAREHOUSE on each user. A missing default warehouse is the usual reason a session fails to start.

Authentication

The managed server uses Snowflake OAuth by default, or External OAuth through an identity provider such as Okta or Microsoft Entra ID. It does not support dynamic client registration, so you create an OAuth security integration first and give its client ID and secret to each client. Snowflake’s recommended settings keep the session narrow: OAUTH_USE_SECONDARY_ROLES = NONE, so no extra roles switch on, and ALLOWED_ROLES_LIST limited to the MCP role.

SQL: an OAuth integration for Claude Code
CREATE SECURITY INTEGRATION mcp_claude_code
  TYPE = OAUTH
  OAUTH_CLIENT = CUSTOM
  ENABLED = TRUE
  OAUTH_CLIENT_TYPE = 'CONFIDENTIAL'
  OAUTH_REDIRECT_URI = 'http://localhost:8080/callback'
  OAUTH_USE_SECONDARY_ROLES = NONE
  ALLOWED_ROLES_LIST = ('MCP_SALES_READER');

SELECT SYSTEM$SHOW_OAUTH_CLIENT_SECRETS('MCP_CLAUDE_CODE');

Snowflake also accepts a programmatic access token, but recommends OAuth because a hard-coded token can leak. If you do use one, tie it to the least-privileged role that works. Two other traps: an account network policy must allow the client’s outbound IP addresses, which for a hosted client such as Claude on the web are the provider’s, not yours; and a network policy block can surface as a misleading invalid_client error.

Setup in Claude Code

Snowflake documents Claude on the web and Claude Desktop (as a custom connector), ChatGPT and Cursor, and says any client that supports remote MCP servers over HTTP will work. Claude Code is one of those. Because the server needs pre-registered credentials, use the flags from Claude Code’s MCP documentation (opens in a new tab) for pre-configured OAuth: a client ID, a secret it prompts for and stores outside your config, and a fixed callback port that matches the redirect URI above.

Terminal
claude mcp add --transport http \
  --client-id <client_id> --client-secret --callback-port 8080 \
  snowflake \
  https://myorg-myaccount.snowflakecomputing.com/api/v2/databases/ANALYTICS/schemas/MCP/mcp-servers/SALES_MCP

# then, inside Claude Code, sign in:
/mcp

The browser opens on Snowflake’s consent screen. After you approve, run a harmless question first, such as “Which tools do you have from snowflake, and what does each one do?”, and check that only the tools you meant to expose appear. Claude Code asks before each MCP tool call unless you approve it; keeping reads quick and everything else on ask is covered in auto-approve in Claude Code.

Where the questions and findings go

Snowflake answers the question; it does not keep track of what should happen next. fenbs does that part. Connect it next to Snowflake with claude mcp add --transport http fenbs https://fenbs.ai/api/mcp, and when a query turns up a broken pipeline or a metric nobody trusts, the assistant can file it as a bug with the query and the result in the note. Each task has a plan and a test status, sits in To Do, Next Up, In Progress or Completed, and every change is recorded in History under the assistant’s name. A standing instruction, such as “never expose SQL on the agent server”, goes on the Decisions and rules page, which every connected assistant reads first. fenbs does not see your Snowflake data or log your queries; Snowflake’s own query history does that.

Related

The general database checklist: database MCP servers. Hosted vs local servers: local vs remote MCP servers. How sign-in works: MCP OAuth explained. Connecting fenbs: the MCP docs.

Questions people ask.

Does Snowflake have an official MCP server?

Yes. The Snowflake-managed MCP server is generally available. You create it in your account with CREATE MCP SERVER, choose its tools, and connect clients to its URL with OAuth. It is not supported in government regions.

Is the Snowflake-Labs MCP server still supported?

No. Its README states that it is deprecated and no longer maintained, and asks users to migrate to the Snowflake-managed MCP server.

Can the Snowflake MCP server be read-only?

The SQL execution tool has a read_only setting that defaults to true and allows only SELECT queries. The firmer limit is the role: grant the MCP role USAGE on the server and only the objects its tools need.

How do I connect Claude Code to the Snowflake MCP server?

Create an OAuth security integration whose redirect URI is http://localhost:8080/callback, read its client ID and secret, then run claude mcp add with the http transport, --client-id, --client-secret and --callback-port 8080, followed by your server URL, and sign in through /mcp.

Start with one thing.

There is nothing to set up first. Write one line and you’ve started.