The agent inside Cortex Code Desktop is good at working with what it can see — your local files, your Snowflake connection, your terminal. The moment a task requires context from somewhere else — a Jira ticket that defines the requirements, a GitHub PR that needs reviewing, an internal API that exposes your data catalog — the agent is operating blind, and you’re back to copying and pasting between tools.
Model Context Protocol (MCP) is how you close that gap. It’s an open standard for connecting AI agents to external tools and data sources, and Cortex Code Desktop implements it as a first-class capability. Once you configure an MCP server for a tool, its capabilities become available to the agent automatically in every session — no custom code, no prompt engineering, no middleware.
The configuration is not zero-effort, but it’s closer to writing a config file than to writing an integration. The main decisions are which transport type fits your tool, how to handle credentials safely, and what permissions to set so the agent can act on what it finds without requiring approval for every call.
What this doesn’t cover: the Snowflake-managed MCP server (which exposes Snowflake’s own capabilities as an MCP endpoint), account-level MCP connectors configured by administrators, or Cortex Code’s ability to run as an MCP server itself.
Before getting into configuration, it’s worth being precise about what MCP is and isn’t.
MCP is a protocol that defines how an AI agent communicates with a tool server. The server exposes a set of named tools — each with an input schema and a description — and the agent calls them the same way it calls any other tool: by name, with arguments. The protocol handles the plumbing: serialization, transport, error handling. What the tool actually does when called is entirely defined by the server implementation.
From the agent’s perspective, an MCP tool call looks identical to a built-in tool call. “Show me the open GitHub pull requests for this repo” → the agent calls mcp__github__list_pull_requests → the GitHub MCP server makes the API call → result comes back to the agent → agent incorporates it into the response.
The agent doesn’t need special prompting to know the tool exists; it reads the tool descriptions and uses them when they match the task.
The practical implication: once an MCP server is configured and running, you interact with the connected tool in plain language rather than remembering API parameters or switching applications.
Cortex Code Desktop supports two MCP transport types, and choosing the right one depends on where and how the server runs.
stdio is for local servers — tools that run as subprocesses on your machine. Cortex Code Desktop spawns the process, communicates with it over stdin/stdout, and manages its lifecycle with the session. Most open-source MCP servers (for Git, filesystem access, language-specific tooling) use stdio.
Configuration specifies the command to run, arguments, environment variables, and optionally a working directory or .env file:
{ "mcpServers": { "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" } } }}
HTTP is for remote or hosted servers — web services, internal APIs with MCP adapters, cloud-hosted integrations. Cortex Code Desktop makes streamable HTTP requests to the endpoint (with SSE fallback). Configuration specifies the URL, optional headers, and optional OAuth configuration:
{ "mcpServers": { "data-catalog": { "url": "https://catalog.internal.company.com/mcp", "headers": { "Authorization": "Bearer ${CATALOG_API_TOKEN}", "X-Team-ID": "data-engineering" } } }}
The choice between them is mostly determined by the server you’re integrating with. Hosted services provide HTTP endpoints; CLI tools use stdio. When building your own MCP server for an internal tool, stdio is simpler to start with and HTTP is worth the additional setup if the server needs to run centrally (shared by a team, running on infrastructure rather than each developer’s machine).
Configuration lives in JSON files at two scopes:
ScopePathGlobal~/.snowflake/cortex/mcp.jsonWorkspace<workspace>/.snowflake/cortex/mcp.json or <workspace>/.cortex/mcp.json
Global configuration applies across all sessions and workspaces. Workspace configuration applies only when that project is open — the right scope for project-specific integrations that you want to commit alongside the code.
When server names collide, Cortex Code Desktop merges from multiple sources in this order (later sources win):
This is a realistic mcp.json for a data engineering team that needs GitHub for PR context, Jira for ticket requirements, a private data catalog API for lineage lookups, and a local PostgreSQL inspector for ad-hoc schema checks:
{ "mcpServers": { "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" } }, "jira": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-atlassian"], "env": { "ATLASSIAN_API_TOKEN": "${JIRA_API_TOKEN}", "ATLASSIAN_EMAIL": "${JIRA_EMAIL}", "ATLASSIAN_SITE_URL": "https://yourcompany.atlassian.net" } }, "data-catalog": { "url": "https://catalog-api.internal.company.com/mcp", "headers": { "Authorization": "Bearer ${CATALOG_TOKEN}", "X-Service-Name": "cortex-code-desktop" } }, "postgres": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-postgres"], "env": { "POSTGRES_CONNECTION_STRING": "${POSTGRES_URI}" } } }}
For project-specific servers where credentials live in a .env file that's already in .gitignore:
{ "mcpServers": { "project-api": { "command": "python", "args": ["-m", "our_internal_mcp_server"], "envFile": "${workspaceFolder}/.env", "cwd": "${workspaceFolder}" } }}
You can also add servers through the Agent Settings panel:
The Browse MCP Servers gallery (accessible from + New) provides pre-built configurations for common services that you can install with a few clicks.
Note : You may add Server configuration in JSON format:
{ "my-new-server": { "type": "http", "url": "https://your-mcp-server-url" }}
The MCP Connectors panel displays each server’s status and lets you:
Tools follow the pattern mcp__<server-name>__<tool-name>. A search tool on a server named github becomes mcp__github__search. This namespacing means two servers can expose identically-named tools without collision.
Tool names are limited to 64 characters and must contain only alphanumeric characters, underscores, and hyphens. Servers exposing invalid tool names are rejected.
Cortex Code Desktop expands environment variables in configuration fields before connecting. Three syntaxes are supported:
SyntaxBehavior${VAR}Replaced with the value of VAR. If not set, the literal is preserved.${VAR:-default}Replaced with VAR if set, otherwise with default.$VARShort form of ${VAR}.
Additionally, ${workspaceFolder} references the current workspace root in paths like cwd and envFile.
The credential handling decision is where most MCP configurations make their biggest mistake: hardcoding API keys in mcp.json. The file sits in your home directory or project folder, is readable by anything with filesystem access, and gets accidentally committed to repos with regularity.
Three independent mechanisms for secure credential injection:
Export sensitive values from your shell profile (~/.bashrc, ~/.zshrc) and reference them in config with ${VAR_NAME}. The values never appear in any config file.
{ "mcpServers": { "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" } } }}
The inputs mechanism prompts for secrets when the server connects, avoiding the need to store them in plain text on disk. This is the right choice for API keys you'd rather not persist anywhere:
{ "mcpServers": { "production-api": { "url": "https://api.production.company.com/mcp", "headers": { "Authorization": "Bearer ${input:prod-api-key}" } } }, "inputs": [ { "id": "prod-api-key", "type": "promptString", "description": "Enter your Production API key", "password": true } ]}
For HTTP MCP servers that support OAuth 2.0, Cortex Code Desktop handles the full authorization flow — opening your browser, exchanging tokens, and refreshing automatically:
{ "mcpServers": { "enterprise-api": { "url": "https://api.enterprise.company.com/mcp", "oauth": { "client_id": "cortex-code-desktop-prod", "client_name": "Cortex Code Desktop", "redirect_port": 8585, "scope": "openid read:projects write:comments", "authorization_server_url": "https://auth.enterprise.company.com" } } }}
On first connection, Cortex Code Desktop opens your system browser for authentication. Tokens are stored securely and refreshed automatically before expiry.
Authorization headers in mcp.json are stored as plaintext on disk. If you're using HTTP transport with a static API key in the headers field, that key is in plain text in the config file:
{ "mcpServers": { "DONT-DO-THIS": { "url": "https://api.example.com/mcp", "headers": { "Authorization": "Bearer sk-live-ACTUAL-SECRET-VALUE-HERE" } } }}
This is documented honestly in the Snowflake docs. Use environment variables, the input prompt mechanism, or OAuth instead.
MCP tools participate in the standard Cortex Code permission system. Default permission rules are configured in:
~/.snowflake/cortex/settings.json
You can match individual tools by their full composed name, or match all tools from a server with a wildcard:
{ "permissions": { "allow": [ "mcp__github__get_pull_request", "mcp__github__list_pull_requests", "mcp__github__get_file_contents", "mcp__jira__get_issue", "mcp__jira__search_issues", "mcp__data-catalog__get_table_lineage", "mcp__data-catalog__get_column_metadata" ], "deny": [ "mcp__github__delete_repository", "mcp__github__merge_pull_request", "mcp__jira__delete_issue", "mcp__postgres__execute_query" ], "ask": [ "mcp__github__create_pull_request", "mcp__github__create_issue", "mcp__jira__create_issue", "mcp__jira__update_issue", "mcp__*" ] }}
Production strategy:
At runtime, permissions are requested on first use and can be remembered for the session.
Here’s how a configured MCP setup changes a typical data engineering workflow.
Without MCP:
With MCP configured:
You: "I'm working on DE-4521. Show me the ticket details, check if there's an open PR for it, and look up the lineage for dim_customers."Agent: [calls mcp__jira__get_issue with key DE-4521] [calls mcp__github__search_pull_requests with query "DE-4521"] [calls mcp__data-catalog__get_table_lineage with table "dim_customers"] "DE-4521 requires adding a customer_segment column to dim_customers. There's an open PR #847 with 2 approvals pending CI. The table is sourced from raw.stripe.customers and raw.salesforce.accounts, with downstream dependencies in analytics.reporting.monthly_revenue and analytics.reporting.customer_cohorts."
The agent makes three parallel tool calls, synthesizes the results, and gives you a complete picture in seconds. No application switching, no context loss.
The most useful MCP configurations for data engineering teams tend to be straightforward ones:
The pattern that works well: Use MCP for context retrieval and read-heavy operations. Use it more cautiously for write operations — creating tickets, merging PRs, publishing to external systems — and keep those tool calls behind explicit approval prompts rather than pre-approving them.
Tool result cap: MCP tool responses are capped at 50 KB. For tools that return large payloads — full document contents, large API responses — have the MCP server return a summary, a reference, or a pointer to a file that Cortex Code Desktop can read in a follow-up step. Responses truncated at the 50 KB limit will have a notice appended.
The surprise: The MCP gallery in Agent Settings (+ New → Browse MCP Servers) has a wider selection of pre-built integrations than most users expect. Additionally, Cortex Code Desktop can auto-discover MCP servers already configured in Claude Desktop, Cursor, and Windsurf — toggleable via the chat.mcp.discovery.enabled setting. If you're already using MCP with another tool, your servers may work out of the box.
The limitation: MCP servers installed as third-party packages are not cryptographically signed or verified by Snowflake. An MCP server you install gets network access, filesystem access (if the tool is designed to write), and the ability to return arbitrary content to the agent. For internal tooling this is usually fine; for external or community-maintained servers, review what the server does before giving it access to sessions that touch production systems.
The practical recommendation: Start with one MCP integration — whichever external tool your team needs most context from during development. Get it working and observe how the agent uses it for a week before adding more. MCP tools compound with each other, and understanding the behavior of one integration before layering others makes the whole system easier to reason about.
The timeout to know about: The default tool timeout is 60 seconds. If you have slow APIs, override it per-server with the timeout field (in milliseconds) or globally via the COCO_MCP_TOOL_TIMEOUT_MS environment variable.
| Symptom | Check / Resolution || ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- || Server not connecting | View the output log in the MCP Connectors panel. Verify environment variables are exported (`echo $VAR`). For `stdio` servers, confirm the command is available on the system `PATH`. || Tools not appearing | Confirm the server status shows Connected in the MCP panel. Verify tool names contain only alphanumeric characters, underscores (`_`), or hyphens (`-`), and are fewer than 64 characters. || Environment variables not expanding | Use the `${VAR}` syntax with braces. Variables are expanded from the process environment at launch time. || Output truncated | MCP responses have a 50 KB output limit. Configure the server to return summarized results or provide file references/paths for large payloads. || Server disabled unexpectedly | Check `~/.snowflake/cortex/mcp-disabled.json`. Servers can be disabled from this file without being removed from the configuration. || OAuth flow fails | Verify that port 8585 (or the configured `redirect_port`) is available. If authentication issues persist, remove and re-add the server to clear stored credentials and restart the OAuth flow. |
MCP is the mechanism that moves Cortex Code Desktop from a self-contained coding assistant to an agent with awareness of your full toolchain. Configuration is file-based and relatively lightweight — the main decisions are:
Start with one integration, understand how the agent uses it, then expand from there.
Article 6 covers dbt Cloud Mode — running dbt transformations inside Snowflake from Cortex Code Desktop without a local dbt installation.
👏 If this article added value, give it a clap!
🔄 Share it with your team and fellow data professionals.
🚀 Follow for more Snowflake insights, hands-on tutorials, and real-world implementations.
✍️ Medium: @SnowflakeChronicles
💼 LinkedIn: @satishkumar-snowflake
See you in the next one.
This article represents the author’s personal views and experience, not those of any employer.
Your Cortex Code Desktop Agent Can’t See Jira. Here’s How to Fix That. was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.