Skip to main content

Cortex Code Plugin

The Metatate Cortex Code plugin brings Metatate's structured context and decision layer into Snowflake-native developer workflows. Cortex Code remains the coding workspace. Metatate remains the source of truth for governed data context, intended-use validation, authorization decisions, explanations, and audit evidence.

The plugin is published as a public GitHub repository:

metatateai/metatate-cortex-code-plugin

It does not run a Metatate-hosted MCP gateway. Cortex Code connects directly to the Snowflake-managed MCP server installed by the Metatate Snowflake Native App.

How It Fits

Snowflake Intelligence, Claude Code, and Cortex Code use the same Metatate decision layer through different client surfaces:

ClientMetatate interfaceAuthentication
Snowflake Intelligencecore.agent_* wrappersActive Snowflake session
Claude Code pluginSnowflake-managed METATATE_MCP serverSnowflake OAuth with session:role:<role>
Cortex Code pluginSnowflake-managed METATATE_MCP serverRole-restricted PAT plus X-Snowflake-Role

Cortex Code uses PAT-based MCP authentication because managed MCP resource metadata can advertise session:role:all, which causes OAuth flows to request role ALL. The role-restricted PAT path keeps the MCP session explicit and avoids changing a user's default Snowflake role.

Prerequisites

  1. Metatate Snowflake Native App is installed.
  2. The managed MCP server exists, normally METATATE_APP.CORE.METATATE_MCP.
  3. Cortex Code is installed on the user's workstation.
  4. The user has a Snowflake connection configured in Cortex Code.
  5. A Snowflake administrator has issued a PAT restricted to the approved Metatate role.

Snowflake Administrator Setup

Choose a least-privilege Snowflake role for Cortex Code users. The examples below use:

METATATE_CORTEX_USER

Grant the role to each user:

GRANT ROLE METATATE_CORTEX_USER TO USER <snowflake_user>;

Grant the Metatate application role required for MCP use:

GRANT APPLICATION ROLE METATATE_APP.APP_USER TO ROLE METATATE_CORTEX_USER;

Create a role-restricted PAT for each user:

USE ROLE ACCOUNTADMIN;

ALTER USER <snowflake_user>
ADD PROGRAMMATIC ACCESS TOKEN metatate_cortex_code
ROLE_RESTRICTION = 'METATATE_CORTEX_USER'
DAYS_TO_EXPIRY = 30
COMMENT = 'Metatate Cortex Code MCP token';

If your account requires a network policy for PAT use and you are completing a first test before the policy is ready, use a short temporary bypass:

ALTER USER <snowflake_user>
ADD PROGRAMMATIC ACCESS TOKEN metatate_cortex_code
ROLE_RESTRICTION = 'METATATE_CORTEX_USER'
DAYS_TO_EXPIRY = 30
MINS_TO_BYPASS_NETWORK_POLICY_REQUIREMENT = 240
COMMENT = 'Metatate Cortex Code MCP token';

Snowflake shows the PAT secret once. Share it only through your approved secret handoff process.

PAT Policy

Use this rollout policy unless your organization has stricter controls:

  • Issue one PAT per user, restricted with ROLE_RESTRICTION.
  • Keep the PAT role aligned with the MCP header X-Snowflake-Role.
  • Use 30-day expiry for normal development access.
  • Use 7-day expiry for pilots, troubleshooting, and shared test accounts.
  • Rotate PATs before expiry and remove old tokens after the new token is verified.
  • Do not store PATs in GitHub, screenshots, tickets, Slack history, or shell history.
  • Prefer a password manager or enterprise secret store for local handoff.

Install The Plugin

Install from GitHub:

cortex plugin install metatateai/metatate-cortex-code-plugin

Confirm it is active:

cortex plugin list

Register The MCP Server

Clone the plugin repository locally if you do not already have it:

git clone https://github.com/metatateai/metatate-cortex-code-plugin.git
cd metatate-cortex-code-plugin

Export the PAT in the same shell where you run Cortex Code:

export METATATE_CORTEX_PAT='<snowflake-pat-secret>'

Register the managed MCP server:

./bin/metatate-cortex-mcp-add \
--account-url https://<account-url> \
--snowflake-role <snowflake-role> \
--write

The helper writes a user-level Cortex MCP entry to:

~/.snowflake/cortex/mcp.json

The generated entry references the environment variable and does not store the PAT secret:

{
"mcpServers": {
"metatate": {
"type": "http",
"url": "https://<account-url>/api/v2/databases/METATATE_APP/schemas/CORE/mcp-servers/METATATE_MCP",
"headers": {
"Authorization": "Bearer ${METATATE_CORTEX_PAT}",
"X-Snowflake-Authorization-Token-Type": "PROGRAMMATIC_ACCESS_TOKEN",
"X-Snowflake-Role": "<snowflake-role>"
}
}
}
}

Smoke Test

Start the MCP connection:

cortex mcp start

Expected result:

Started: 1/1 servers connected

Connected Servers:
metatate: 7 tools available

Start Cortex Code from the same shell:

cortex --connection <connection-name>

Inside Cortex Code, run:

/mcp

Then run:

/metatate:discover-context

Ask Metatate to find governed assets available in your environment:

Show governed assets I can inspect. If you need to narrow the search, ask me for a database, schema, domain, sensitivity level, or compliance tag.

Troubleshooting

Programmatic access token is invalid

Confirm METATATE_CORTEX_PAT is exported in the same shell:

echo "${METATATE_CORTEX_PAT:+set}"

Then confirm the token is still active and restricted to the expected role:

SHOW USER PROGRAMMATIC ACCESS TOKENS FOR USER <snowflake_user>;

Role or permission denied

Confirm the PAT ROLE_RESTRICTION matches the --snowflake-role used by the helper and the role has the Metatate app role:

SHOW GRANTS TO ROLE <snowflake-role>;

User tied to access token mismatch

If Cortex Code reports:

The user you were trying to authenticate as differs from the user tied to the access token.

Open ~/.snowflake/connections.toml and make sure the Cortex connection uses the canonical Snowflake user name shown by:

SELECT CURRENT_USER();

For example, Snowflake may resolve carlos@getmetatate.com to CARLOS; the Cortex connection should use CARLOS.

Cortex opens a Snowflake OAuth page for Metatate MCP

Remove the stale OAuth-based MCP registration and add it again with the PAT helper:

cortex mcp remove metatate
./bin/metatate-cortex-mcp-add \
--account-url https://<account-url> \
--snowflake-role <snowflake-role> \
--write