Getting started with the Cortex MCP

Audience: a coding agent (Claude Code, Codex, Cursor) working for a human. Everything here is verifiable from a terminal; the only browser step is the human signing in.

1. Connect

The MCP server of dev is https://mcp.dev.infra.doublex.ai/mcp: Streamable HTTP, with OAuth. In Claude Code:

claude mcp add --scope user --transport http cortex https://mcp.dev.infra.doublex.ai/mcp

--scope user registers the server for every folder. A cortex entry with local scope (what the command creates without the flag) wins over the user one, so if you ever added it wrong, remove it first: claude mcp remove cortex -s local.

On first use the server answers 401 with WWW-Authenticate: Bearer resource_metadata=...; the client discovers the authorization server through /.well-known/oauth-protected-resource and opens the browser for the human, who signs in with the same account as the console.

If cortex is listed but has no tools, or keeps asking for sign-in: in Claude Code type /mcp, choose cortex, then Authenticate.

Verify: call whoami. It answers with the organization, the plan and your scopes.

The cortex command. It is not on npm, and npx cortex installs an unrelated package with the same name: never run it. Build it from the platform checkout with make cli, which leaves cortex in ~/.local/bin. You need it for cortex deploy, not to talk to the MCP.

2. Authenticate the terminal

cortex login                       # opens the browser; the issuer is discovered from the API
cortex login --pat <token>         # CI, or when the browser cannot open
cortex whoami --json

The credential is validated before it is written to ~/.cortex/credentials.json with mode 0600. CORTEX_TOKEN in the environment wins over the file, so CI never needs a login step. Tokens are created on the console's Tokens page.

3. The tools

tools/list is always the truth. The groups, with the tools you will use first:

GroupTools
Accountwhoami, list_projects, get_project, create_project, delete_project
Sourcesupload_file, finalize_upload, add_source, test_source, list_sources, remove_source, set_secret
Pipelinesrun_pipeline, get_run, get_run_logs, list_runs, schedule_pipeline, cancel_run
Explorelist_tables, describe_table, sample_table, profile_table
Queryrun_sql, estimate_query, get_query_result
Modelingget_project_config, apply_project_config, propose_model, run_models, list_models, get_change_set, list_change_sets, approve_change_set, reject_change_set
Semantics and AIget_semantic_model, validate_semantic, query_metrics, explain_metric, ask, set_ai_provider, list_ai_providers
Appget_template, create_deployment, get_deployment, list_deployments, get_build_logs, get_app_logs, rollback_deployment, promote_deployment, set_env_var, list_env_vars, get_health, get_app_metrics
End usersinvite_end_user, list_end_users, set_end_user_roles, set_end_user_attrs, disable_end_user
Budgetget_usage, get_budget, get_limits, set_spend_cap

Most tools take a project_id (the ULID create_project returns, not the slug). Deploying from a folder is cortex deploy, which packs the folder and calls create_deployment for you.

4. Reading a result

Every result carries _meta["cortex/usage"] with cu_seconds, bytes_scanned, cost_estimate_usd and budget_remaining_usd. Watch it: cost is a requirement, not a report.

5. Reading an error

Errors are structured, in English, and tell you what to do:

{ "error": { "code": "limit.bytes_exceeded", "message": "query would scan 12 GB",
             "hint": "Filter by order_date, or upgrade the plan.",
             "details": { "bytes_estimated": 12884901888 } } }

Common codes: auth.unauthenticated, auth.scope_missing, validation.config_invalid, not_found, conflict.slug_taken, limit.bytes_exceeded, limit.spend_cap, approval.required, upstream.unavailable.

The CLI maps them to exit codes: 0 ok, 2 usage, 3 auth, 4 not found, 5 conflict, 6 limit, 7 validation, 9 not implemented yet, 1 anything else.

6. Approvals

A change to a protected environment never applies silently. approve_change_set asks the human through MCP, with a summary and a diff. You wait for the answer; you do not work around it.

Next

Quickstart goes from sign-up to a published URL; Bootstrap a project is the same path for a real data source.