When should you use this server
- Ask natural-language questions over governed Snowflake data via Cortex Analyst
- Run semantic/Cortex Search over indexed documents and support content
- Execute parameterized SQL from agents under guardrails and access control
Key features
- Managed, cloud-hosted endpoint—no self-hosted binary to run
- Role-scoped access: every request runs under a specific Snowflake role
- OAuth 2.1 with an external identity provider (per-user attribution)
Authentication
- Method: OAuth 2.1 with manual OAuth metadata (pre-registered client).
-
Why: Snowflake’s OAuth server does not support Dynamic Client Registration (DCR / RFC 7591). Portkey’s default OAuth flow auto-registers a client against the upstream server, which Snowflake rejects with:
-
The supported pattern: front Snowflake with an IdP it trusts (this guide uses Okta via Snowflake External OAuth), pre-register a confidential OAuth client there, and give Portkey those credentials in
oauth_metadata. Portkey then skips DCR and uses the pre-registered client for the upstream token exchange.
With this pattern, Okta (not Snowflake) is the OAuth authorization server. Snowflake validates the resulting JWT and maps its
scp claim to a Snowflake role.Endpoint
A Snowflake managed MCP server URL looks like:Connect via Portkey MCP Gateway
The setup has three parts: Snowflake (trust the IdP, map roles), Okta (issue tokens with the role scope), and Portkey (register the server withoauth_metadata).
Step 1: Snowflake — role, user, and External OAuth integration
Run asACCOUNTADMIN in a Snowsight worksheet.
| Field | What it does |
|---|---|
EXTERNAL_OAUTH_ISSUER | Must match the token’s iss claim exactly (no trailing-slash mismatch) |
EXTERNAL_OAUTH_AUDIENCE_LIST | Must include the Snowflake account URL and match the Okta auth server’s Audience |
EXTERNAL_OAUTH_TOKEN_USER_MAPPING_CLAIM | Token claim identifying the user (sub); must equal a user’s LOGIN_NAME |
EXTERNAL_OAUTH_SCOPE_MAPPING_ATTRIBUTE | Role selector—scp. This is why the token’s scp must carry session:role:<role> |
Step 2: Okta — authorization server, scope, and confidential app
-
Security → API → Authorization Servers → Add. Set Audience to the Snowflake account URL (
https://<account>.<region>.snowflakecomputing.com). Note the Issuer URI—feed it into Step 1 and Step 3. -
Scopes → Add Scope: create
session:role:<role>(literal, colons and all; lowercase as Snowflake expects). Check Include in public metadata. -
Access Policies → Add Policy + Rule: grant type
Authorization Code(+Refresh Token), and list thesession:role:<role>scope and the allowed users. -
Applications → Create App Integration → OIDC → Web Application (gives a
client_secret). Set the Sign-in redirect URI to: -
Copy the Client ID, Client Secret, and from
<issuer>/.well-known/oauth-authorization-serverthe authorization_endpoint and token_endpoint.
Step 3: Register the integration in Portkey
- In Portkey, go to MCP Registry → Add MCP Integration.
- Set:
| Field | Value |
|---|---|
| Name | Snowflake |
| Slug | snowflake |
| Server URL | https://<account>.<region>.snowflakecomputing.com/api/v2/databases/<db>/schemas/<schema>/mcp-servers/<server> |
| Auth Type | OAuth 2.1 |
- Expand Advanced Configuration and paste (replace placeholders):
Use
oauth_metadata (upstream auth), not external_auth_config. With client_id and client_secret present, Portkey skips DCR and uses your pre-registered Okta client. See OAuth Client Metadata.- Configure workspace access as needed, then save.
Step 4: Connect from an agent
Gateway URL pattern:https://mcp.portkey.ai/{slug}/mcp.
Claude Desktop / Cursor
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Incompatible auth server: does not support dynamic client registration | oauth_metadata missing or incomplete → Portkey fell back to DCR against Snowflake | Confirm the field is oauth_metadata with both client_id and client_secret, saved on the control plane you actually use |
Okta authorize URL shows scope=session:role:all | Snowflake’s advertised scopes_supported overrode the configured scope | Ensure oauth_metadata.scope is set; confirm your deploy target has the scope-passthrough fix (SaaS and self-hosted deploy independently) |
One or more scopes are not configured | Scope doesn’t exist in Okta, isn’t in the access-policy rule, or doesn’t map to a granted role | Re-check Step 2.2 (scope exists), 2.3 (scope in rule), Step 1 (role granted), and EXTERNAL_OAUTH_SCOPE_MAPPING_ATTRIBUTE='scp' |
Snowflake returns 401 to a direct-token test | aud/iss mismatch or sub doesn’t map to a LOGIN_NAME | Compare the token’s aud/iss/sub (jwt.io) to the SECURITY INTEGRATION fields and the user’s LOGIN_NAME |
Tools provided
Tools depend on what the Snowflake MCP server exposes (Cortex Search services, Cortex Analyst semantic views, and SQL execution). Use the client’s tool inspector or
tools/list on the gateway URL as the source of truth.- Cortex Analyst — natural-language questions answered against a configured semantic view/model.
- Cortex Search — semantic search over an indexed service (documents, tickets, etc.).
- SQL execution — run SQL under the mapped Snowflake role.
For self-hosted gateways, replace
mcp.portkey.ai with your gateway host (and use that host in the Okta redirect URI and redirect_uri).
