Use Cortex Agents and MCP servers in an app¶
This topic describes how a Snowflake Native App can create Cortex Agents and Snowflake-managed MCP servers, and how a provider can register an SPCS service endpoint as an SPCS-hosted MCP server. With these capabilities, an app can offer a conversational experience over its shared data and functionality, and expose its tools to other agents inside or outside Snowflake.
Overview¶
A Snowflake Native App can include three kinds of AI objects:
- Cortex Agents
Agents that the app creates in its setup script or at runtime. App-created agents appear in Snowflake Intelligence and are callable from the REST, Python, and SQL APIs, just like standalone agents.
- Snowflake-managed MCP servers
MCP servers that wrap Snowflake-native objects (Cortex Search services, Cortex Analyst semantic views, Cortex Agents, UDFs, and stored procedures) as MCP tools. The app creates these by using CREATE MCP SERVER.
- SPCS-hosted MCP servers
MCP servers that register an SPCS service endpoint with the MCP client infrastructure used by Cortex Agents and Snowflake Intelligence. They let the app expose arbitrary code (in any language or framework) running in Snowpark Container Services as MCP tools. The app creates these by using
CREATE CUSTOM MCP SERVER.
These capabilities are separate from, and complementary to, sharing agents created in the provider account. For information about sharing standalone agents, see Share Cortex Agents.
Security model¶
Cortex Agents created by an app run under restricted caller’s rights (RCR). RCR enforces that an app’s agent can’t access consumer data without an explicit grant from the consumer.
Every tool invocation from an app-created agent requires both of the following:
Consumer privilege: a user in the consumer account has the privilege needed on the target object. This is the same caller’s-rights model used by standalone agents.
App caller grant: the consumer admin has performed a caller grant to the app for the object. For more information, see GRANT CALLER.
Key points:
The app gets implicit caller grants on objects that it owns. The provider doesn’t need to request explicit caller grants for in-app objects.
Consumer-owned objects require explicit
GRANT CALLER ... TO APPLICATIONfrom the consumer admin.When a tool runs in owner’s rights (for example, a procedure created with
EXECUTE AS OWNER), execution switches to the owner’s identity. RCR restrictions don’t apply within that tool’s scope.When a tool runs in restricted caller’s rights, for example a procedure created with
EXECUTE AS RESTRICTED CALLERand owned by a role other than the app, RCR restrictions compose by intersection. Each link in a chain makes the effective access stricter, never looser.Owner’s rights agents aren’t supported. A provider can still surface an agent through an owner’s-rights code entity (for example, a Streamlit app or an Snowpark Container Services service) that calls the agent using the app’s identity.
Snowflake-managed MCP servers created by an app are restricted to app-owned
tools. They can’t expose tools that aren’t owned by the app, and they can’t
include the SYSTEM_EXECUTE_SQL tool. This restriction prevents an installed
app’s MCP server from being used as a way to access consumer data or run
arbitrary SQL in the consumer’s account.
Before you begin¶
To use Cortex Agents in a Snowflake Native App, the consumer account must have both Cortex Agents and Snowflake Intelligence enabled. For more information, see Cortex Agents.
Cortex Agents in a Native App¶
This section describes the provider and consumer admin workflows for creating and using a Cortex Agent in a Snowflake Native App.
Provider: Create the agent¶
A provider creates an agent in the app’s setup script, or at runtime in a code entity. The following example creates an agent that includes a Cortex Analyst tool backed by an app-owned semantic view, a second Cortex Analyst tool backed by a consumer-owned semantic view, and a custom procedure tool that calls an app-owned procedure:
Notes:
Partially qualified identifiers (such as
core.my_semantic_view) are resolved relative to the agent’s database and schema. This is the recommended pattern inside a Snowflake Native App, because the app database name is only known at install time.Tool identifiers aren’t resolved when the agent is created. A provider can declare tools before the underlying objects are created or before the app has access to them.
We recommend using
orchestration: autoinstead of a specific model name. A specific model might not be available in the consumer’s region.
For information about Cortex Agent SQL commands, see Cortex Agent commands.
Provider: Create the tools and grant access¶
The application also creates the tools that the agent uses and grants access to them through application roles:
Consumer admin: Audit the agent before granting access¶
Before granting users access to an app-created agent, the consumer admin should review the agent’s full specification (model, tools, system prompt, and referenced objects) by using DESCRIBE AGENT or through the agent UI:
Consumer admin: Grant caller access on consumer objects¶
Without caller grants, the agent can’t use consumer objects, even if the consumer user has privileges on them. The following example grants the app the caller privileges that the agent needs:
Alternatively, grant access to individual objects:
For more information about caller grants, see GRANT CALLER.
Consumer admin: Delegate to user roles¶
After granting caller access to the app, delegate access to the underlying objects and the application role to the user roles that should be allowed to use the agent:
Use the agent¶
After the consumer admin grants the application role to a user role, the agent is available in all the same places as a standalone agent. For example:
Snowflake Intelligence. The agent appears automatically.
The Cortex Agents REST API. Send a request to
POST /api/v2/databases/{app}/schemas/{schema}/agents/{name}:run. For more information, see Cortex Agents REST API.SQL. Call DATA_AGENT_RUN (SNOWFLAKE.CORTEX).
MCP servers in a Native App¶
A Snowflake Native App can create two kinds of MCP servers:
Kind |
What it wraps |
Use when |
|---|---|---|
SPCS-hosted MCP server ( |
The app’s own SPCS service endpoint |
You need arbitrary compute, such as ML inference, proprietary algorithms, external API calls, or a custom language or framework. |
Snowflake-managed MCP server (CREATE MCP SERVER) |
Existing Snowflake objects (Cortex Search, Cortex Analyst, Cortex Agents, UDFs, and stored procedures) |
Your tools are expressible as Snowflake-native objects. |
The following sections describe how to create each kind. For a detailed breakdown of when to use each, see When to use SPCS-hosted or Snowflake-managed MCP.
SPCS-hosted MCP servers¶
An SPCS-hosted MCP server is a metadata object that links an SPCS service endpoint to the MCP client infrastructure used by Cortex Agents and Snowflake Intelligence. It doesn’t deploy a service. It registers an existing SPCS endpoint as MCP-discoverable. For information about how to deploy SPCS services in a Snowflake Native App, see Tutorial 2: Create an app with containers.
Provider: Write the MCP server¶
The following example shows a minimal MCP echo server that uses the Streamable HTTP transport on port 8080, with a separate health check endpoint on port 8081 for SPCS readiness probes:
Provider: Create the SPCS service¶
In the app’s setup script, create the SPCS service that hosts the MCP server, and grant access to its endpoint:
For more information about SPCS in a Snowflake Native App, see Add services to an app.
Provider: Create the SPCS-hosted MCP server object¶
After the SPCS service is created, create the SPCS-hosted MCP server object
that points to the service endpoint, and grant USAGE to the application
role:
Verify the MCP server:
Use the SPCS-hosted MCP server from a Cortex Agent¶
To reference the SPCS-hosted MCP server from a Cortex Agent specification,
include it under mcp_servers:
When a Cortex Agent calls an SPCS-hosted MCP server, the role that runs the
agent must have USAGE on the CUSTOM MCP SERVER object and access to
the SPCS service endpoint that backs the MCP server. For the service endpoint,
grant a service role that provides access to the endpoint.
Snowflake authorizes access in two places:
When resolving the backing ingress URL. Snowflake checks the invoking role’s privileges on the
CUSTOM MCP SERVERobject, and checks that both the invoking role and theCUSTOM MCP SERVERowner role have access to the SPCS service endpoint. This check occurs at the start of eachagent:runrequest.When sending the request to the ingress URL. Snowflake checks that the invoking role has access to the SPCS service endpoint. This check occurs at each tool discovery call (
tools/list) and tool invocation (tools/call).
If the required privileges are revoked before a request starts, the request can’t use the MCP server. If privileges are revoked after the ingress URL has already been resolved for an in-progress request, the change applies to subsequent requests.
External MCP clients can interact with an SPCS-hosted MCP server directly through the SPCS ingress URL, but OAuth isn’t supported yet for this path.
Snowflake-managed MCP servers¶
A Snowflake-managed MCP server (created with CREATE MCP SERVER) wraps Snowflake-native objects as MCP tools. For general information about Snowflake-managed MCP servers, see Snowflake-managed MCP server.
Restrictions in a Native App¶
App-created Snowflake-managed MCP servers have stricter rules than standalone Snowflake-managed MCP servers:
Tools must reference objects that are owned by the app. The MCP server can’t expose tools that the app doesn’t own.
The
SYSTEM_EXECUTE_SQLtool isn’t supported.
These restrictions ensure that an installed app’s MCP server can only expose the app’s own capabilities. The MCP server can’t be used as a way to access consumer data or run arbitrary SQL in the consumer’s account.
Provider: Create the MCP server¶
The following example creates a Snowflake-managed MCP server in the app that exposes an app-owned Cortex Search service and an app-owned Cortex Analyst semantic view as tools:
Use the Snowflake-managed MCP server¶
After the consumer admin grants the application role to a user role, the MCP server is available the same way as a standalone Snowflake-managed MCP server. External MCP clients (with OAuth) and Cortex Agents in the consumer account can use it through the following endpoint:
For more information about the endpoint and how MCP clients connect, see Snowflake-managed MCP server.
When to use SPCS-hosted or Snowflake-managed MCP¶
The following table compares the two kinds of MCP servers in a Snowflake Native App:
Criteria |
SPCS-hosted MCP server |
Snowflake-managed MCP server |
|---|---|---|
Tool implementation |
Arbitrary code (any language, any framework) running in Snowpark Container Services. |
Snowflake-native objects: UDFs, stored procedures, Cortex Search, Cortex Analyst, Cortex Agents. |
Compute |
Runs on your Snowpark Container Services compute pool. |
Runs on a warehouse or Snowflake-managed compute. |
Use when |
You need ML inference, proprietary algorithms, external API calls, stateful services, or custom protocols. |
Your tools map cleanly to SQL functions, search services, or semantic views. |
Consumer access in a Snowflake Native App |
Primarily for Cortex Agents. External MCP clients can interact directly with the Snowpark Container Services ingress URL, but OAuth isn’t supported yet. |
Both external MCP client usage with OAuth and Cortex Agent usage are supported. |
Start with a Snowflake-managed MCP server if your app’s MCP tools are wrappers around Snowflake objects that you already have, such as search services, semantic views, or procedures. This option requires less infrastructure and simpler deployment. Use an SPCS-hosted MCP server when your tools require arbitrary compute, an external dependency, or a custom protocol.
Best practices for providers¶
When you build agents and MCP servers in a Snowflake Native App, follow these practices:
Scope tools minimally. Declare only the tools that the agent needs. Each tool widens the agent’s access surface.
Write tool descriptions carefully. Agent orchestration uses tool names and descriptions to decide when to call tools. Keep descriptions specific, accurate, and limited to the tool’s intended use.
Validate inputs to custom tools. If the agent calls stored procedures or user-defined functions (UDFs), validate arguments. Prompt injection can cause unexpected inputs.
Don’t embed secrets in system prompts. Consumers can inspect the full agent specification by using
DESC AGENT.Use RBAC to protect app objects and intellectual property. Even if an agent is manipulated through prompt injection, restricted caller’s rights prevent it from exceeding its granted privileges on Snowflake objects. Don’t use prompt instructions, such as “do not reveal internal data,” as a security control.
Use owner’s rights objects when needed. Cortex Agents don’t run with owner’s rights. If an agent needs access to internal app objects that aren’t exposed to consumers, wrap the agent call in an owner’s-rights stored procedure or Snowpark Container Services service.
Use event logging and event sharing for observability. For more information, see Logging messages from functions and procedures and Use logging and event tracing for an app.
For best practices that apply to consumers (auditing, granting caller privileges, monitoring, and feature policies), see Use app-created Cortex Agents and MCP servers.
SQL reference¶
The following SQL commands are used to manage Cortex Agents and MCP servers in a Snowflake Native App: