Snowflake-managed MCP server

Overview

Note

Snowflake supports Model Context Protocol revision 2025-11-25.

Model Context Protocol (MCP), is an open-source standard that lets AI agents securely interact with business applications and external data systems, such as databases and content repositories. MCP lets enterprise businesses reduce integration challenges and quickly deliver outcomes from models. Since its launch, MCP has become foundational for agentic applications, providing a consistent and secure mechanism for invoking tools and retrieving data.

The Snowflake-managed MCP server lets AI agents securely retrieve data from Snowflake accounts without needing to deploy separate infrastructure. You can configure the MCP server to serve Cortex Analyst, Cortex Search, and Cortex Agents as tools, along with custom tools and SQL executions on the standards-based interface. MCP clients discover and invoke these tools, and retrieve data required for the application. With managed MCP servers on Snowflake, you can build scalable enterprise-grade applications while maintaining access and privacy controls. The MCP server on Snowflake provides:

  • Standardized integration: Unified interface for tool discovery and invocation, in compliance with the rapidly evolving standards.
  • Comprehensive authentication: Snowflake’s built-in OAuth service to enable OAuth-based authentication for MCP integrations.
  • Robust governance: Role based access control (RBAC) for the MCP server and tools to manage tool discovery and invocation.

For information about the MCP lifecycle, see Lifecycle. For an example of an MCP implementation, see the Getting Started with Managed Snowflake MCP Server Quickstart.

MCP server security recommendations

Important

When you configure hostnames for MCP server connections, use hyphens (-) instead of underscores (_). MCP servers have connection issues with hostnames containing underscores.

Using multiple MCP servers without verifying tools and descriptions could lead to vulnerabilities such as tool poisoning or tool shadowing. Snowflake recommends verifying third-party MCP servers before using them. This includes any MCP server from another Snowflake user or account. Verify all tools offered by third-party MCP servers.

We recommend using OAuth as the authentication method. Using hardcoded tokens can lead to token leakage.

When using a Programmatic Access Token (PAT), set it to use the least-privileged role allowed to work with MCP. This will help prevent leaking a secret with access to a highly-privileged role.

Configure proper permissions for the MCP server and tools following the least-privilege principle. Access to the MCP Server does not give access to the tools. Permission needs to be granted for each tool.

Avoid configurations that can create recursive loops. For example, an external client calling a Cortex Agent tool through MCP, which in turn invokes another MCP server that calls back into a Cortex Agent, can produce expensive, unbounded loops. Snowflake enforces a maximum recursion depth of 10 invocations. Ensure your agent and tool configurations don’t create circular invocation paths.

Create an MCP Server object

Create an object, specifying the tools and other metadata. MCP clients that connect with the server, after requisite authentication, are able to discover and invoke these tools.

  1. Navigate to the desired database and schema to create the MCP server in.
  2. Create the MCP server:
    CREATE [ OR REPLACE ] MCP SERVER [ IF NOT EXISTS ] <server_name>
      FROM SPECIFICATION $$
     tools:
       - name: "product-search"
         type: "CORTEX_SEARCH_SERVICE_QUERY"
         identifier: "database1.schema1.Cortex_Search_Service1"
         description: "cortex search service for all products"
         title: "Product Search"
    
       - name: "revenue-semantic-view"
         type: "CORTEX_ANALYST_MESSAGE"
         identifier: "database1.schema1.Semantic_View_1"
         description: "Semantic view for all revenue tables"
         title: "Semantic view for revenue"
      $$

Snowflake currently supports the following tool types:

  • CORTEX_SEARCH_SERVICE_QUERY: Cortex Search Service tool
  • CORTEX_ANALYST_MESSAGE: Cortex Analyst tool
  • SYSTEM_EXECUTE_SQL: SQL execution
  • CORTEX_AGENT_RUN: Cortex Agent tool
  • GENERIC: tool for UDFs and stored procedures

The following examples show how to configure different tool types:

Using the Analyst tool, your client can generate SQL from natural language text. Use the following code to specify the tool configuration.

Note

The Snowflake-managed MCP server only supports using semantic views with Cortex Analyst. It does not support semantic models.

tools:
  - name: "revenue-semantic-view"
    type: "CORTEX_ANALYST_MESSAGE"
    identifier: "database1.schema1.Semantic_View_1"
    description: "Semantic view for all revenue tables"
    title: "Semantic view for revenue"

Use the following examples to create and configure custom tools using UDFs and stored procedures:

The following examples demonstrate creating UDFs that can be used as custom tools:

-- create a simple udf
CREATE OR REPLACE FUNCTION MULTIPLY_BY_TEN(x FLOAT)
RETURNS FLOAT
LANGUAGE PYTHON
RUNTIME_VERSION = '3.8'
HANDLER = 'multiply_by_ten'
AS
$$
def multiply_by_ten(x: float) -> float:
  return x * 10
$$;

SHOW FUNCTIONS LIKE 'MULTIPLY_BY_TEN';

-- test return json/variant
CREATE OR REPLACE FUNCTION CALCULATE_PRODUCT_AND_SUM(x FLOAT, y FLOAT)
RETURNS VARIANT
LANGUAGE PYTHON
RUNTIME_VERSION = '3.8'
HANDLER = 'calculate_values'
AS
$$
import json

def calculate_values(x: float, y: float) -> dict:
  """
  Calculates the product and sum of two numbers and returns them in a dictionary.
  The dictionary is converted to a VARIANT (JSON) in the SQL return.
  """
  product = x * y
  sum_val = x + y

  return {
      "product": product,
      "sum": sum_val
  }
$$;

-- test return list/array
CREATE OR REPLACE FUNCTION GET_NUMBERS_IN_RANGE(x FLOAT, y FLOAT)
RETURNS ARRAY -- Use ARRAY to explicitly state a list is being returned
LANGUAGE PYTHON
RUNTIME_VERSION = '3.8'
HANDLER = 'get_numbers'
AS
$$
def get_numbers(x: float, y: float) -> list:
  """
  Returns a list of integers between x (exclusive) and y (inclusive).
  Assumes x < y.
  """
  # Ensure x and y are treated as integers for range generation
  start = int(x) + 1
  end = int(y) + 1 # range() is exclusive on the stop value

  # Use a list comprehension to generate the numbers
  # The Python list will be converted to a Snowflake ARRAY.
  return list(range(start, end))
$$;
  1. To show MCP servers, use the following commands:

    SHOW MCP SERVERS IN DATABASE <database_name>;
    SHOW MCP SERVERS IN SCHEMA <schema_name>;
    SHOW MCP SERVERS IN ACCOUNT;

    The following shows the output of the command:

    |               created_on               |       name        | database_name | schema_name |    owner     |           comment            |
    ------------------------------------------+-------------------+---------------+-------------+--------------+------------------------------
    | Fri, 23 Jun 1967 07:00:00.123000 +0000 | TEST_MCP_SERVER   | TEST_DATABASE | TEST_SCHEMA | ACCOUNTADMIN | [NULL]                       |
    | Fri, 23 Jun 1967 07:00:00.123000 +0000 | TEST_MCP_SERVER_2 | TEST_DATABASE | TEST_SCHEMA | ACCOUNTADMIN | Test MCP server with comment |
  2. To describe an MCP server, use the following command:

    DESCRIBE MCP SERVER <server_name>;

    The following shows the output of the command:

    |      name       | database_name | schema_name |    owner     | comment |     server_spec        |               created_on               |
    ------------------------------------------------------------------------------------------------------+-------------------------------------
    | TEST_MCP_SERVER | TEST_DATABASE | TEST_SCHEMA | ACCOUNTADMIN | [NULL]  | {"version":1,"tools":[{"name":"product-search","identifier":"db.schema.search_service","type":"CORTEX_SEARCH_SERVICE_QUERY"}]} | Fri, 23 Jun 1967 07:00:00.123000 +0000 |
  3. To drop an MCP server, use the following command:

    DROP MCP SERVER <server_name>;

MCP server URL

To connect to the MCP server, use the URL endpoint with the following format:

https://<account_URl>/api/v2/databases/{database}/schemas/{schema}/mcp-servers/{name}

For information about formatting your account URL, see Account identifiers.

Access control

You can use the following privileges to manage access to the MCP server and the underlying tools.

PrivilegeObjectDescription
CREATEMCP SERVERRequired to create the MCP server
OWNERSHIPMCP SERVERRequired to update the object configuration
MODIFYMCP SERVERProvides update, drop, describe, show, and use (tools/list and tools/call) on the object configuration
USAGEMCP SERVERRequired to connect with the MCP server and discover tools
USAGECortex Search ServiceRequired to invoke the Cortex Search tool in the MCP server
SELECTSemantic ViewRequired to invoke the Cortex Analyst tool in the MCP server
USAGECortex AgentRequired to invoke the Cortex Agent as a tool in the MCP server
USAGEUser-defined function (UDF) or stored procedureRequired to invoke the UDF or stored procedure as a tool in the MCP server

Set up OAuth authentication

Configure authentication on the MCP client. The Snowflake-managed MCP server supports OAuth 2.0 aligned with the authorization recommendation in the MCP protocol. The Snowflake-managed MCP server doesn’t support dynamic client registration.

A single OAuth security integration (client ID and secret) can be shared across all users in an account. Each user still authenticates individually with their own credentials to obtain an access token, but the client ID and secret from the integration are the same for everyone. A single integration can also issue tokens that work across multiple MCP servers within the same account.

  1. First, create the security integration. For information about this command, see CREATE SECURITY INTEGRATION (Snowflake OAuth).

    CREATE [ OR REPLACE ] SECURITY INTEGRATION [IF NOT EXISTS] <integration_name>
      TYPE = OAUTH
      OAUTH_CLIENT = CUSTOM
      ENABLED = TRUE
      OAUTH_CLIENT_TYPE = 'CONFIDENTIAL'
      OAUTH_REDIRECT_URI = '<redirect_URI>'

    If your MCP client requires multiple redirect URIs (for example, VS Code registers more than one callback URL), use OAUTH_ALTERNATE_REDIRECT_URIS to specify additional URIs:

    CREATE [ OR REPLACE ] SECURITY INTEGRATION [IF NOT EXISTS] <integration_name>
      TYPE = OAUTH
      OAUTH_CLIENT = CUSTOM
      ENABLED = TRUE
      OAUTH_CLIENT_TYPE = 'CONFIDENTIAL'
      OAUTH_REDIRECT_URI = '<primary_redirect_URI>'
      OAUTH_ALTERNATE_REDIRECT_URIS = ('<alternate_URI_1>', '<alternate_URI_2>')
  2. Then, call the system function to retrieve your client id and keys for client configuration. The integration name is case sensitive and must be in uppercase.

    SELECT SYSTEM$SHOW_OAUTH_CLIENT_SECRETS('<integration_name>');

Role behavior in OAuth sessions

The MCP server uses the connecting user’s DEFAULT_ROLE for the OAuth session. Secondary roles aren’t supported. Some MCP clients (such as Claude) don’t support specifying a role in the OAuth scope (session:role:<role_name>), so the session always uses the user’s DEFAULT_ROLE.

To ensure the correct role is used:

  • Set each user’s DEFAULT_ROLE to the role that has the required privileges on the MCP server and its tools.
  • Ensure each user has a DEFAULT_WAREHOUSE set (sessions fail to initialize if this is null).
ALTER USER <username> SET DEFAULT_ROLE = '<mcp_access_role>' DEFAULT_WAREHOUSE = '<warehouse_name>';

If you need different data access levels per user, use separate agents with dedicated roles rather than relying on secondary roles.

Note

Some MCP clients (such as Claude) request the session:role:all OAuth scope. This may cause the consent screen to display “secondary roles = ALL” even when your security integration has OAUTH_USE_SECONDARY_ROLES = NONE. The display is cosmetic only. Snowflake enforces the security integration setting regardless of what the client requests, so no additional roles are granted beyond the user’s DEFAULT_ROLE.

Interact with the MCP server using a custom MCP client

For information about building a custom MCP client, see Build an MCP client.

Note

The Snowflake MCP server currently only supports tool capabilities.

Discover and invoke tools

The MCP clients can discover and invoke tools with tools/list and tools/call requests.

To discover or invoke tools, issue a POST call as shown in the tools/list request:

For the Analyst tool, your client passes messages in the request. The SQL statement is listed in the output. You must pass the name of the tool that you’re invoking in the request in the name parameter.

POST /api/v2/databases/<database>/schemas/<schema>/mcp-servers/<name>
    {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "tools/call",
        "params": {
            "name": "test-analyst",
            "arguments": {
                "message": "text"
            }
        }
    }

The following example shows the response:

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "content": [
            {
                "type": "text",
                "text": "string"
            }
        ]
    }
}

For Search tool requests, your client can pass the query and the following optional arguments:

  • columns
  • limit

The search results and request ID are returned in the output. You must pass the name of the tool that you’re invoking in the request as the name parameter.

POST /api/v2/databases/{database}/schemas/{schema}/mcp-servers/{name}
    {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "tools/call",
        "params": {
            "name": "product-search",
            "arguments": {
                "query": "Hotels in NYC",
                "columns": array of strings,
                "limit": int
            }
        }
  }

The following example shows the response:

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "results": {}
    }
}

Limitations

Snowflake managed MCP server does not support the following constructs in the MCP protocol: resources, prompts, roots, notifications, version negotiations, life cycle phases, and sampling.

Only non-streaming responses are supported.

Each MCP server supports a maximum of 50 tools. This limit includes all tool types: Cortex Search, Cortex Analyst, Cortex Agents, SQL execution, and custom (generic) tools. If you need more tools, create additional MCP servers. Higher tool counts can degrade tool-selection accuracy.

Tool responses are subject to size limits to prevent LLM context window saturation:

  • Generic tools: Responses are truncated at 250 KB.
  • SQL execution tool: Responses are truncated at 250 KB.

If a query result exceeds the size limit, the response is truncated. To work around this limit, use narrower queries that return fewer columns or rows.

Secondary roles aren’t supported in MCP OAuth sessions. The session uses the connecting user’s DEFAULT_ROLE. For details, see Role behavior in OAuth sessions.

MCP server objects aren’t replicated in failover groups. If you use replication, you must recreate MCP server objects on the secondary account. OAuth security integrations are replicated.