Snowflake

How to Connect Claude to Snowflake (Step-by-Step)

10 min read
Linus Tse
Linus Tse

Greyfield Data

I recently connected two people at the same company from Claude to the same Snowflake MCP server.

One worked almost immediately. The other completed the Snowflake login and OAuth consent screen, but Claude still could not query anything.

That distinction matters. Connected only means the authorization flow finished. It does not prove the Snowflake session has a warehouse, the right role, or access to the schema that contains the MCP server.

The fix was in Snowflake, not Claude. The user's default warehouse and role needed to be correct, the role needed access to the database and PUBLIC schema that hosted the MCP server, and the user needed to reconnect so Claude received a fresh token.

Here is the setup I would use again.

What you are actually connecting

Claude does not connect straight to every table in a Snowflake account. It connects to a Snowflake-managed Model Context Protocol (MCP) server over HTTPS.

The path is:

Claude
  -> Snowflake OAuth security integration
  -> Snowflake user and default role
  -> Snowflake-managed MCP server
  -> approved Snowflake tools and data

That separation is useful. Snowflake still controls identity, roles, warehouses, object grants, and query history. Claude only gets the access held by the person who signs in.

Where to get every value Claude asks for

The connector form is short, but the labels make it sound like all the values come from the same place. They do not.

Claude field Where it comes from
Connector name A label you choose, such as Company Snowflake
Snowflake account identifier Your Snowflake organization name and account name
MCP server URL Your Snowflake account URL plus the database, schema, and MCP server name
OAuth client ID The Snowflake OAuth security integration
OAuth client secret The same Snowflake OAuth security integration
Callback or redirect URL Claude shows this while the connector is being added
Snowflake username and SSO The individual employee's normal Snowflake identity

If you are the employee connecting Claude, you should not have to invent any of this. Your Snowflake administrator or Claude Team owner should prepare the connector. You sign in with your own Snowflake account after it appears in Claude.

If you are setting up the connector for the company, collect the values in the order below.

Find the Snowflake account identifier and account URL

The preferred Snowflake account identifier is the organization name and account name joined with a hyphen. It looks like this:

<organization_name>-<account_name>

If you are already signed into Snowflake, run:

SELECT
  CURRENT_ORGANIZATION_NAME() AS organization_name,
  CURRENT_ACCOUNT_NAME() AS account_name,
  CURRENT_ACCOUNT() AS account_locator,
  CURRENT_REGION() AS region;

For a normal public Snowflake account, build the hostname from the first two values:

https://<organization_name>-<account_name>.snowflakecomputing.com

If the organization or account name contains an underscore, replace the underscore with a hyphen in the hostname. Snowflake still supports older account-locator URLs, but recommends the organization-and-account format for new connections.

Find the database, schema, and MCP server name

The rest of the MCP URL identifies the Snowflake object Claude will call. An administrator can list the available servers with:

SHOW MCP SERVERS IN ACCOUNT;

If the result shows an MCP server named CLAUDE_MCP in ANALYTICS.PUBLIC, the complete URL is:

https://<organization>-<account>.snowflakecomputing.com/api/v2/databases/ANALYTICS/schemas/PUBLIC/mcp-servers/CLAUDE_MCP

Copy the database, schema, and server names from Snowflake. Do not guess them from the name someone gave the connector in Claude.

Get the OAuth client ID and secret

These values do not come from the employee's Snowflake profile. They belong to the OAuth security integration created for Claude.

After creating CLAUDE_MCP_INTEGRATION, run this as an authorized administrator:

SELECT SYSTEM$SHOW_OAUTH_CLIENT_SECRETS('CLAUDE_MCP_INTEGRATION');

The JSON result contains:

  • oauth_client_id
  • oauth_client_secret
  • oauth_client_secret_2, which Snowflake provides for secret rotation

Put the client ID and one active client secret into Claude's advanced connector settings. The integration name is case-sensitive in this function and normally needs to be uppercase.

The client ID and secret identify the connector application. They are not the employee's Snowflake username and password. Each employee still signs in through Snowflake or the company's SSO after clicking Connect.

Get the callback URL from Claude first

The redirect goes in the opposite direction: Claude supplies it, and Snowflake must allow it.

Start adding the connector in Claude and copy the callback URL it displays. Use that exact value as OAUTH_REDIRECT_URI when creating the Snowflake security integration. A small mismatch—web versus desktop, a different hostname, or a missing path—can make OAuth fail before Snowflake permissions are even tested.

The Claude Team plan has an extra owner step

The menus are slightly different on Claude Team and Enterprise plans.

An Owner or Primary Owner first adds the connector for the organization:

  1. Open Organization settings.
  2. Open Connectors and click Add.
  3. Choose Custom, then Web.
  4. Enter the Snowflake MCP server URL.
  5. Open Advanced settings and enter the OAuth client ID and secret from Snowflake.
  6. Add the connector to the organization.

After that, each team member goes to Customize > Connectors, finds the connector, clicks Connect, and signs into Snowflake individually.

The owner step makes the connector available. It does not give every employee the owner's Snowflake access.

On an individual Claude plan, the person can add the custom connector directly under Customize > Connectors.

Set up the Snowflake side with one narrow role

Do not make ACCOUNTADMIN the connector role. Snowflake itself recommends against using ACCOUNTADMIN as a user's default role, and privileged roles are restricted in Snowflake OAuth by default.

Create or reuse a role that has only the access Claude needs. In this example, the MCP server lives in ANALYTICS.PUBLIC and uses REPORTING_WH:

USE ROLE SECURITYADMIN;

CREATE ROLE IF NOT EXISTS CLAUDE_ANALYST;

GRANT USAGE ON WAREHOUSE REPORTING_WH
  TO ROLE CLAUDE_ANALYST;

GRANT USAGE ON DATABASE ANALYTICS
  TO ROLE CLAUDE_ANALYST;

GRANT USAGE ON SCHEMA ANALYTICS.PUBLIC
  TO ROLE CLAUDE_ANALYST;

GRANT USAGE ON MCP SERVER ANALYTICS.PUBLIC.CLAUDE_MCP
  TO ROLE CLAUDE_ANALYST;

Then grant the privileges required by the tools exposed through the MCP server. Those grants depend on whether the server exposes a Cortex Agent, semantic view, Cortex Search service, function, or procedure.

For a server that is intentionally allowed to read reporting tables directly, the role may also need narrow read grants such as:

GRANT USAGE ON SCHEMA ANALYTICS.REPORTING
  TO ROLE CLAUDE_ANALYST;

GRANT SELECT ON ALL TABLES IN SCHEMA ANALYTICS.REPORTING
  TO ROLE CLAUDE_ANALYST;

GRANT SELECT ON FUTURE TABLES IN SCHEMA ANALYTICS.REPORTING
  TO ROLE CLAUDE_ANALYST;

Keep the role at the approved reporting layer. Do not give an AI connector broad access to raw, finance, HR, or administrative data just because it is easier than tracing the required objects.

Create the OAuth integration for Claude

Snowflake's current pattern is a custom confidential OAuth integration restricted to the MCP access role:

USE ROLE ACCOUNTADMIN;

CREATE OR REPLACE SECURITY INTEGRATION CLAUDE_MCP_INTEGRATION
  TYPE = OAUTH
  OAUTH_CLIENT = CUSTOM
  ENABLED = TRUE
  OAUTH_CLIENT_TYPE = 'CONFIDENTIAL'
  OAUTH_REDIRECT_URI = '<CLAUDE_CALLBACK_URI>'
  OAUTH_USE_SECONDARY_ROLES = NONE
  ALLOWED_ROLES_LIST = ('CLAUDE_ANALYST');

Use the exact callback URI Claude shows during setup. Then retrieve the client ID and secret in Snowflake and enter them in Claude's advanced connector settings:

SELECT SYSTEM$SHOW_OAUTH_CLIENT_SECRETS('CLAUDE_MCP_INTEGRATION');

Treat the client secret like a password. Do not paste it into a shared document, ticket, or public setup guide.

The MCP server URL follows this shape:

https://<account-url>/api/v2/databases/ANALYTICS/schemas/PUBLIC/mcp-servers/CLAUDE_MCP

Use the fully qualified path. Snowflake also notes that some client hostnames need hyphens instead of underscores.

Set the user's default role and warehouse before connecting

This is where the first successful user gave us the clue: Claude required a default warehouse before it could query Snowflake. He selected one in Snowflake's preferences and the integration began working.

A warehouse is the compute Snowflake uses to run a query. The account identifier answers “which Snowflake account?” The default warehouse answers “where should this query run?” They are separate settings.

For Claude, I use an existing reporting warehouse or a small dedicated warehouse with auto-suspend. I do not use a loading or transformation warehouse just because it already exists.

To see the warehouses available in the account, run:

SHOW WAREHOUSES;

Choose the warehouse intended for interactive reporting, then make sure the connector role can use it:

GRANT USAGE ON WAREHOUSE REPORTING_WH
  TO ROLE CLAUDE_ANALYST;

Snowflake's MCP OAuth flow normally requests session:role:all. Despite the name, that does not activate every role. It starts the session with the user's DEFAULT_ROLE.

Set both defaults explicitly:

USE ROLE USERADMIN;

ALTER USER <USERNAME> SET
  DEFAULT_ROLE = CLAUDE_ANALYST
  DEFAULT_WAREHOUSE = REPORTING_WH;

USE ROLE SECURITYADMIN;

GRANT ROLE CLAUDE_ANALYST TO USER <USERNAME>;

Setting a default role does not grant it. The user must actually have the role, and that role must have USAGE on the warehouse.

You can also edit the user in Snowsight under Governance & security > Users & roles. Open the user, edit the advanced options, and set Default role and Default warehouse. The SQL version is easier to review and repeat across several employees.

If DEFAULT_WAREHOUSE is blank, OAuth may still finish successfully. Claude then reaches Snowflake with no active compute and the MCP session can fail to initialize. If the warehouse is set but the default role lacks USAGE on it, the result is effectively the same.

Why the second user's connection failed

In the failed setup, the browser completed the authorization flow. That sent us down the wrong path at first because the connector looked connected.

The working and failing users did not start their Snowflake sessions the same way. The failing user's active/default role could not use the full path to the MCP server. The missing access included the PUBLIC schema where the server lived. The session also needed a usable default warehouse.

The practical repair was:

  1. Confirm the intended role was granted to the user.
  2. Grant that role USAGE on the database and ANALYTICS.PUBLIC schema.
  3. Grant USAGE on the MCP server and its underlying objects.
  4. Set the user's default role and default warehouse.
  5. Disconnect and reconnect Snowflake in Claude.

That last step is not housekeeping. An existing OAuth token can preserve the old session context. Changing the Snowflake user after Claude is already connected does not prove the next tool call will use the new defaults.

A short verification query is better than a green checkmark

After reconnecting, ask Claude to run a harmless read-only test that exposes the session context:

SELECT
  CURRENT_USER(),
  CURRENT_ROLE(),
  CURRENT_WAREHOUSE(),
  CURRENT_DATABASE(),
  CURRENT_SCHEMA();

Then run one narrow business query against an approved table or tool. A good test has an obvious result and does not expose sensitive rows. For example: count records by month in an approved reporting view.

Verify all of these before calling the setup complete:

  • OAuth consent completed.
  • Claude can see the intended MCP tools.
  • CURRENT_ROLE() is the least-privilege connector role.
  • CURRENT_WAREHOUSE() is the intended reporting warehouse.
  • The role can use the database, MCP schema, MCP server, and underlying objects.
  • A read-only business query returns a sensible result.

The troubleshooting order I use now

If Claude signs into Snowflake but cannot query, I check these in order:

  1. MCP URL: Is it the complete database, schema, and server path?
  2. Default warehouse: Does the user have one, and does the default role have USAGE on it?
  3. Default role: Is it the intended connector role rather than an admin role or unrelated analyst role?
  4. Server path: Does that role have USAGE on the database, schema, and MCP server?
  5. Underlying tool: Does the role have the privilege required by the agent, semantic view, search service, function, or procedure?
  6. Fresh token: Did the user disconnect and reconnect after grants or defaults changed?
  7. Network policy: If OAuth itself fails with invalid_client, can Anthropic's outbound infrastructure reach the Snowflake account?

This order separates authentication from authorization. It also avoids the tempting but unsafe fix of widening OAuth access to a privileged role.

Connector only or connector plus a data plugin?

The connector supplies access. A data-oriented plugin can add a more repeatable analysis workflow and self-checks, but it does not fix Snowflake permissions.

I would get the connector working first, verify the real Snowflake role and warehouse, then add any analysis workflow on top. If a query fails because the role cannot use ANALYTICS.PUBLIC, no prompt or plugin will repair the grant.

The lesson from this setup was simple: a completed login is the start of the test, not the end.

Sources: Snowflake-managed MCP server documentation, Snowflake user management, and Anthropic's custom connector setup.

Related

← All articles