Snowflake 管理的 MCP 服务器¶
概述¶
备注
Snowflake supports Model Context Protocol revision 2025-06-18.
模型上下文协议 (MCP) 是一项 开源标准 (https://modelcontextprotocol.io/docs/getting-started/intro),可让 AI 代理与业务应用程序和外部数据系统(例如数据库和内容存储库)安全地交互。MCP 帮助企业减少集成难题,并能快速地从模型中交付成果。自推出以来,MCP 已成为代理应用程序的基础,为调用工具和检索数据提供了一致且安全的机制。
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:
标准化集成: 用于工具发现和调用的统一接口,符合快速发展的标准。
全面身份验证: 利用 Snowflake 的内置 OAuth 服务,为 MCP 集成启用基于 OAuth 的身份验证。
稳健的治理: 对 MCP 服务器及工具实施基于角色的访问控制 (RBAC),用于管理工具发现与调用。
For information about the MCP lifecycle, see Lifecycle (https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle). For an example of an MCP implementation, see the Getting Started with Managed Snowflake MCP Server (https://quickstarts.snowflake.com/guide/getting-started-with-snowflake-mcp-server/index.html) Quickstart.
MCP server security recommendations¶
重要
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.
创建 MCP 服务器对象¶
创建一个对象,指定相关工具及其他元数据。经过必要的身份验证后,连接到 MCP 服务器的 MCP 客户端能够发现并调用这些工具。
导航到要在其中创建 MCP 服务器的数据库和架构。
创建 MCP 服务器:
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 text from SQL. Use the following code to specify the tool configuration.
备注
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"Using the Search tool requests, your client can perform unstructured search on their data.
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"For the SQL execution tool, your client can execute SQL queries on Snowflake. Use the following code to specify the tool configuration.
tools: - title: "SQL Execution Tool" name: "sql_exec_tool" type: "SYSTEM_EXECUTE_SQL" description: "A tool to execute SQL queries against the connected Snowflake database."For the Agent tool, your client passes a message to the agent. The agent processes the request and returns a response. Use the following code to specify the tool configuration.
tools: - title: "Agent V2" name: "agent_1" type: "CORTEX_AGENT_RUN" identifier: "db.schema.agent" description: "agent that gives the ability to..."For your custom tools, you must provide the user-defined function (UDF) or stored procedure signature in the tool configuration. The custom tool enables you to invoke UDFs and stored procedures as tools through the MCP server.
You need to specify the following in the tool configuration:
type:functionfor UDF,procedurefor stored procedure
Warehouse
Input schema: corresponds to the function signature
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))
$$;
The following examples demonstrate creating stored procedures that can be used as custom tools:
-- create a simple stored procedure
CREATE OR REPLACE PROCEDURE MULTIPLY_BY_TEN_SP(x FLOAT)
RETURNS FLOAT
LANGUAGE PYTHON
RUNTIME_VERSION = '3.8'
PACKAGES = ('snowflake-snowpark-python')
HANDLER = 'multiply_by_ten'
AS
$$
# The handler logic is identical to the UDF for a scalar return
def multiply_by_ten(x: float) -> float:
return x * 10
$$;
-- test return json/variant
CREATE OR REPLACE PROCEDURE CALCULATE_VALUES_SP(x FLOAT, y FLOAT)
RETURNS VARIANT
LANGUAGE PYTHON
RUNTIME_VERSION = '3.8'
PACKAGES = ('snowflake-snowpark-python')
HANDLER = 'calculate_values'
AS
$$
# The handler logic is identical to the UDF for a VARIANT return
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 PROCEDURE GET_NUMBERS_SP(x FLOAT, y FLOAT)
RETURNS ARRAY
LANGUAGE PYTHON
RUNTIME_VERSION = '3.8'
PACKAGES = ('snowflake-snowpark-python')
HANDLER = 'get_numbers'
AS
$$
def get_numbers(x: float, y: float) -> list:
"""
Returns a list of integers between x (exclusive) and y (inclusive).
The Python list will be converted to a Snowflake ARRAY.
"""
# 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
return list(range(start, end))
$$;
The following examples demonstrate configuring custom tools for UDFs and stored procedures:
CREATE MCP SERVER my_mcp_server
FROM SPECIFICATION $$
tools:
- title: "Custom Tool 1"
identifier: "EXAMPLE_DATABASE.AGENTS.MULTIPLY_BY_TEN"
name: "multiply_by_ten"
type: "GENERIC"
description: "Multiplied input value by ten and returns the result."
config:
type: "function"
warehouse: "COMPUTE_SERVICE_WAREHOUSE"
input_schema:
type: "object"
properties:
x:
description: "A number to be multiplied by ten"
type: "number"
- title: "Custom Tool 2"
identifier: "EXAMPLE_DATABASE.AGENTS.CALCULATE_PRODUCT_AND_SUM"
name: "calculate_product_and_sum"
type: "GENERIC"
description: "Calculates the product and sum of two numbers and returns them in a JSON object."
config:
type: "function"
warehouse: "COMPUTE_SERVICE_WAREHOUSE"
input_schema:
type: "object"
properties:
x:
description: "First number"
type: "number"
y:
description: "Second number"
type: "number"
- title: "Custom Tool 3"
identifier: "EXAMPLE_DATABASE.AGENTS.GET_NUMBERS_IN_RANGE"
name: "get_numbers_in_range"
type: "GENERIC"
description: "Returns a list of integers between two numbers."
config:
type: "function"
warehouse: "COMPUTE_SERVICE_WAREHOUSE"
input_schema:
type: "object"
properties:
x:
description: "Start number (exclusive)"
type: "number"
y:
description: "End number (inclusive)"
type: "number"
- title: "Custom Tool 4"
identifier: "EXAMPLE_DATABASE.AGENTS.MULTIPLY_BY_TEN_SP"
name: "multiply_by_ten_sp"
type: "GENERIC"
description: "Multiplied input value by ten and returns the result."
config:
type: "procedure"
warehouse: "COMPUTE_SERVICE_WAREHOUSE"
input_schema:
type: "object"
properties:
x:
description: "A number to be multiplied by ten"
type: "number"
- title: "Custom Tool 5"
identifier: "EXAMPLE_DATABASE.AGENTS.CALCULATE_PRODUCT_AND_SUM_SP"
name: "calculate_product_and_sum_sp"
type: "GENERIC"
description: "Calculates the product and sum of two numbers and returns them in a JSON object."
config:
type: "procedure"
warehouse: "COMPUTE_SERVICE_WAREHOUSE"
input_schema:
type: "object"
properties:
x:
description: "First number"
type: "number"
y:
description: "Second number"
type: "number"
- title: "Custom Tool 6"
identifier: "EXAMPLE_DATABASE.AGENTS.GET_NUMBERS_IN_RANGE_SP"
name: "get_numbers_in_range_sp"
type: "GENERIC"
description: "Returns a list of integers between two numbers."
config:
type: "procedure"
warehouse: "COMPUTE_SERVICE_WAREHOUSE"
input_schema:
type: "object"
properties:
x:
description: "Start number (exclusive)"
type: "number"
y:
description: "End number (inclusive)"
type: "number"
$$;
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 |
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 |
To drop an MCP server, use the following command:
DROP MCP SERVER <server_name>;
访问控制¶
You can use the following privileges to manage access to the MCP server and the underlying tools.
Privilege |
Object |
Description |
|---|---|---|
CREATE |
MCP SERVER |
Required to create the MCP server |
OWNERSHIP |
MCP SERVER |
必须拥有此权限才能更新对象配置 |
MODIFY |
MCP SERVER |
可对对象配置进行更新、删除、描述、显示和使用( |
USAGE |
MCP SERVER |
必须拥有此权限才能连接 MCP 服务器并发现工具 |
USAGE |
Cortex Search 服务 |
必须拥有此权限才能调用 MCP 服务器中的 Cortex Search 工具 |
SELECT |
语义视图 |
必须拥有此权限才能调用 MCP 服务器中的 Cortex Analyst 工具 |
USAGE |
Cortex Agent |
Required to invoke the Cortex Agent as a tool in the MCP server |
USAGE |
User-defined function (UDF) or stored procedure |
Required 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 (https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization) recommendation in the MCP protocol. The Snowflake-managed MCP server doesn't support dynamic client registration.
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>'
然后,调用系统函数,以检索客户端配置所需的客户端 ID 和密钥。集成名称区分大小写,并且必须为大写形式。
SELECT SYSTEM$SHOW_OAUTH_CLIENT_SECRETS('<integration_name>');
Interact with the MCP server using a custom MCP client¶
If you are building a custom MCP client, the following sections demonstrate the Snowflake endpoints that your client interacts with.
备注
The Snowflake MCP server currently only supports tool capabilities.
初始化 MCP 服务器¶
完成身份验证后,通过对以下 API 端点发出 GET 和 POST 调用来初始化服务器:
POST /api/v2/databases/{database}/schemas/{schema}/mcp-servers/{name}
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": { "protocolVersion": "2025-06-18" }
}
The following example shows the response:
{
"jsonrpc": "2.0", // passthrough from req
"id": 1, // passthrough from req
"result": {
"proto_version": "2025-06-18",
"capabilities": {
"tools": {
"listChanged": false
}
},
"server_info": {
"name": "<snowflake-mcp-name>",
"title": "Snowflake Server: <snowflake-mcp-name>",
"version": "1.0.0"
}
}
}
发现与调用工具¶
MCP 客户端可以通过 tools/list 和 tools/call 请求发现并调用工具。
要发现工具,请按 工具/列表请求 (https://modelcontextprotocol.io/specification/2025-06-18/server/tools#calling-tools) 中所示发出 POST 调用:
POST /api/v2/databases/{database}/schemas/{schema}/mcp-servers/{name}
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
The following example shows the response:
{
"jsonrpc": "2.0", // passthrough from req
"id": 1, // passthrough from req
"result": {
"tools": [ // search
{
"name":"product-search",
"description":"Test search tool",
"inputSchema": {
"type": "object",
"description": "A search query and additional parameters for search.",
"properties": {
"query": {
"description": "Unstructured text query. Exactly one of 'query' or 'multi_index_query' must be specified.",
"type": "string"
},
"columns": {
"description": "List of columns to return.",
"type": "array",
"items": {
"type": "string"
}
},
"filter": {
"description": "Filter query.",
"type": "object"
},
"limit": {
"description": "Max number of results to return.",
"type": "integer",
"default": 10
}
}
},
"outputSchema": {
"type": "object",
"description": "Search results.",
"properties": {
"results": {
"description": "List of result rows.",
"type": "array",
"items": {
"type": "object",
"additionalProperties": true,
"description": "Map of column names to values (as bytes)."
}
},
"request_id": {
"description": "ID of the request.",
"type": "string"
}
},
"required": ["results", "request_id"]
}
},
{ // analyst
"name":"revenue-semantic-view",
"description":"Test tool",
"inputSchema": {
"type": "object",
"description": "A message and additional parameters for Cortex Analyst.",
"properties": {
"message": {
"description": "The user’s question.",
"type": "string"
}
}
}
}
]
}
}
要调用工具,请按 工具/调用请求 (https://modelcontextprotocol.io/specification/2025-06-18/server/tools#calling-tools) 中所示发出 POST 调用。
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
filter
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,
"filter": json,
"limit": int
}
}
}
The following example shows the response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"results": {}
}
}
限制¶
Snowflake 管理的 MCP 在 MCP 协议中不支持以下结构:资源、提示、根、通知、版本协商、生命周期阶段和采样。
仅支持非流式传输响应。