Chalk hosts a Model Context Protocol (MCP) server so that AI agents (Claude, Cursor, your own LangChain or agent code, or any MCP-compatible client) can interact with your Chalk deployment directly. Through the MCP server an agent can run online queries, execute ChalkSQL, read feature and resolver definitions, search logs and traces, and inspect query errors, all scoped to the permissions of the credentials it presents.

The MCP server is hosted alongside the Chalk API and requires no installation or self-hosting.

The MCP Server is distinct from the MCP Gateway. The MCP Server exposes Chalk itself to agents (run queries, execute ChalkSQL, inspect your deployment). The MCP Gateway sits in front of other MCP servers and governs your agents' access to them.


Connecting a client

Most MCP clients accept a remote server URL plus a set of headers. Point your client at https://api.chalk.ai/v1/mcp/sse using its streamable-HTTP or remote-server configuration. The snippets below read your credentials from chalk config, so they work as written once you are logged in. See Authentication for where those credentials come from, and Endpoint if you are on a dedicated or self-hosted deployment.

Claude Code

The CLI registers the server for you, using the credentials you are already logged in with:

chalk mcp configure-claude

This adds Chalk in Claude Code’s user scope, so it is available in every project. Pass --claude-scope local to limit it to the current directory, or --claude-scope project to write it to .mcp.json for your teammates. Start Claude Code and run /mcp to confirm the connection.

Under the hood this runs claude mcp add, which you can also call yourself:

claude mcp add --transport http chalk https://api.chalk.ai/v1/mcp/sse \
  --header "X-Chalk-Client-Id: $(chalk config --format json | jq -r .clientId.value)" \
  --header "X-Chalk-Client-Secret: $(chalk config --format json | jq -r .clientSecret.value)"

Codex

The CLI writes the Codex configuration for you:

chalk mcp configure-codex

This adds an [mcp_servers.chalk] block to ~/.codex/config.toml, leaving the rest of the file untouched. Codex has no per-project scope, so the server is available everywhere. Pass --env-headers to reference environment variables instead of writing your credentials into the file, and confirm the result with codex mcp list.

Codex’s own codex mcp add command covers stdio servers only, so you can also add Chalk by editing that file yourself:

[mcp_servers.chalk]
url = "https://api.chalk.ai/v1/mcp/sse"
env_http_headers = { "X-Chalk-Client-Id" = "CHALK_CLIENT_ID", "X-Chalk-Client-Secret" = "CHALK_CLIENT_SECRET" }

env_http_headers maps each header to the name of an environment variable Codex reads when it connects, which keeps the credentials out of the file. Export them first with eval "$(chalk config --format shell)". To write the values into the file instead, use http_headers, which takes the header values themselves.

JSON configuration

This is the format used by Cursor, Windsurf, and many other clients (mcp.json / mcpServers):

{
  "mcpServers": {
    "chalk": {
      "url": "https://api.chalk.ai/v1/mcp/sse",
      "headers": {
        "X-Chalk-Client-Id": "token-392c737aa1e467e42e85ae3e8417a003",
        "X-Chalk-Client-Secret": "ts-6307f46a00a68436b0f955b82b7fb30075d"
      }
    }
  }
}

Clients that only support stdio

For a client that cannot connect to a remote server directly, bridge to it with mcp-remote:

{
  "mcpServers": {
    "chalk": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://api.chalk.ai/v1/mcp/sse",
        "--header",
        "X-Chalk-Client-Id: ${CHALK_CLIENT_ID}",
        "--header",
        "X-Chalk-Client-Secret: ${CHALK_CLIENT_SECRET}"
      ],
      "env": {
        "CHALK_CLIENT_ID": "token-392c737aa1e467e42e85ae3e8417a003",
        "CHALK_CLIENT_SECRET": "ts-6307f46a00a68436b0f955b82b7fb30075d"
      }
    }
  }
}

Verifying the connection with curl

You can confirm your credentials are accepted by issuing an initialize request directly:

curl -sS https://api.chalk.ai/v1/mcp/sse \
  -H "X-Chalk-Client-Id: $(chalk config --format json | jq -r .clientId.value)" \
  -H "X-Chalk-Client-Secret: $(chalk config --format json | jq -r .clientSecret.value)" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'

A 401 with a WWW-Authenticate header means the credentials were missing or rejected.


Endpoint

GET/POST
https://api.chalk.ai/v1/mcp/sse

The server speaks the Streamable HTTP transport (MCP specification 2025-03-26). A single URL handles both the JSON-RPC POST requests and the Server-Sent Events (SSE) streams that the transport uses, so most clients only need this one URL.

Configure your client for a streamable-HTTP (or “HTTP”) remote server, not a legacy SSE server. The /sse suffix in the path is historical: this endpoint speaks the modern Streamable HTTP transport, not the deprecated HTTP+SSE transport.

If you are on a dedicated or self-hosted Chalk deployment, replace api.chalk.ai with your own API server host. You can find it in the apiServer field of chalk config --format json.


Authentication

The MCP server authenticates with the same service credentials used everywhere else in Chalk.

Getting your credentials

Generate or look up a service token in the Settings → Service Tokens tab of the Chalk dashboard, then retrieve the values from the CLI with chalk config:

chalk config
Name           Value                                    Description
client_id      token-392c737aa1e467e42e85ae3e8417a003   default token
client_secret  ts-6307f46a00a68436b0f955b82b7fb30075d   default token
environment    btfxgaqqxbt7z                            ...
api_server     https://api.chalk.ai                     ...

To pull the values out programmatically, use a machine-readable format:

# JSON object with clientId / clientSecret / apiServer fields
chalk config --format json

# Shell export statements: CHALK_CLIENT_ID / CHALK_CLIENT_SECRET / ...
chalk config --format shell

Presenting your credentials

Provide your client_id and client_secret as HTTP headers on every request:

HeaderValue
X-Chalk-Client-IdYour service token’s client_id
X-Chalk-Client-SecretYour service token’s client_secret

The server exchanges these for a short-lived access token internally, so you do not need to run the OAuth client-credentials flow yourself.

Treat these credentials as secrets
They can query your Chalk deployment and, depending on the permissions they carry, modify it. Prefer a scopedservice tokenover personal credentials.

Bearer tokens and OAuth

The server also accepts a standard Authorization: Bearer <access_token> header. If a request arrives without credentials, the server responds with 401 and a WWW-Authenticate challenge pointing at Chalk’s OAuth discovery endpoints (/.well-known/oauth-protected-resource), so MCP clients that implement the MCP authorization spec (including Dynamic Client Registration) can negotiate a token interactively. For headless and server-to-server use, the X-Chalk-Client-Id / X-Chalk-Client-Secret headers are the simplest option.

Interactive registration currently works for clients whose callback is a hosted web address, such as the claude.ai web app. A client that runs on your own machine, including Claude Code and other terminal or desktop clients, asks to be sent back to a local address on a random port, and Chalk does not yet accept those, so registration fails before a browser opens. Use the header-based setup in Connecting a client for those clients. As an alternative for Claude Code specifically, adding Chalk as a claude.ai custom connector, under Settings then Connectors, uses an allowlisted callback and syncs down into the CLI.

Selecting an environment

By default, requests run against the environment associated with your service token. To target a different environment, either:

  • send the X-Chalk-Env-Id: <environment_id> header, or
  • pass an environment_id argument to an individual tool call.

Environment overrides are only honored for user (personal) credentials. Use the list_environments tool to discover the environment IDs available to your team.


Available tools

The server currently advertises the following 66 tools. The tools/list response is the runtime source of truth for their input schemas and behavior annotations.

Every tool is authorized individually: it checks the permissions on the credentials that called it and returns a permission error if they fall short, so what a client can do is set by its token rather than by the server. run_online_query requires query.online. The observability and Kubernetes inspection tools require monitoring.read. Sandboxed Python execution and the deployment filesystem tools require deploy.redeploy, which is also the permission for running a notebook cell, so a token that can run notebook cells can also execute code against a deployment.

The deployment file tools provision or reuse a source sandbox, including tools that only read or search files. The server therefore marks those tools as destructive and non-idempotent.

General and discovery

ToolDescription
echoReturn a supplied message. This is primarily useful for testing a connection.
whoamiReturn the authenticated identity and selected Chalk environment.
next_stepsPropose a follow-up action for the user without executing it.
list_environmentsList environments available to your team, including their IDs.
list_environment_secretsList environment secret names and metadata without returning secret values.
search_docsSearch the Chalk documentation, or read one exact documentation page.
search_docs_functionsSearch exact Chalk function signatures and API reference entries.

Queries and SQL

ToolDescription
run_online_queryRun an online query for one or more features.
execute_sql_queryExecute a ChalkSQL query, with preview support.
search_offline_queriesSearch offline queries with filters, or fetch one complete query by operation ID.
search_sql_catalogBrowse catalogs and schemas, or search tables and columns.
lint_sql_queryPlan ChalkSQL against the catalog without executing it.
propose_sql_worksheet_editReturn a complete SQL worksheet edit for review in the Chalk dashboard.

Feature graph, deployments, and functions

ToolDescription
search_graphSearch deployed features and resolvers, or fetch one exact definition.
list_branchesList the deployment’s branches.
get_deploymentReturn metadata for a deployment.
list_functionsList external functions in the environment.
inspect_functionInspect an external function’s metadata, schemas, configuration, readiness, and source when available.
invoke_functionInvoke an external function with JSON or Arrow IPC input.
deploy_chalk_functionCreate an external function or deploy a new revision from Python source.
deployment_readRead one file from a deployment source sandbox.
search_deployment_filesSearch deployment source files by regular expression or glob.
write_deployment_fileWrite a complete deployment file or replace exact text in one.
deployment_bashRun a shell command in a deployment source sandbox.

Notebooks

These tools create, edit, and run Chalk Notebooks and their cells.

Several of them propose a change instead of making it. A proposal renders in the notebook as a pending card at the position the agent chose, showing the new or rewritten source as a diff with Confirm and Undo controls, and the notebook is unchanged until someone confirms. Confirming inserts the cell but does not run it.

That review step only exists in the Chalk dashboard, where a notebook is open to display it. A client connecting over this endpoint has no reviewer, so a proposal it returns is never shown to anyone and nothing is written.

add_notebook_cell and delete_notebook_cell take persist=true, which applies the change directly and requires deploy.redeploy. edit_notebook_cell has no such argument: to change an existing cell from a client like this, use edit_and_run_notebook_cell, which persists the new source but also executes the cell. That path covers python and sql cells only.

ToolDescription
create_notebookCreate a notebook.
list_notebooksList the notebooks in the environment.
read_notebookRead a notebook’s ordered cells and optionally their most recent execution results. SQL and query results include the column schema, a row count, and a capped sample rather than the full dataframe, and the sampled rows are referenced rather than inlined in the response.
add_notebook_cellPropose adding a python, sql, text, markdown, or input cell. Returns a proposal for the user to confirm rather than persisting; pass persist=true to apply it directly.
edit_notebook_cellPropose a rewrite of a cell’s source. Returns a before/after diff for the user to confirm rather than persisting.
move_notebook_cellMove a cell to a new position. Persists immediately.
delete_notebook_cellPropose deleting a cell. Returns a proposal for the user to confirm rather than persisting; pass persist=true to apply it directly.
run_notebook_cellsExecute cells and wait for them to finish, provisioning the kernel if needed. Omit the cell ids to run every runnable cell in document order.
add_and_run_notebook_cellAdd a python or sql cell and execute it in one call, returning the run output. Persists immediately, so it requires deploy permission.
edit_and_run_notebook_cellReplace a python or sql cell’s source and execute it in one call. Persists immediately, so it requires deploy permission.
install_python_dependenciesInstall python packages into a notebook’s kernel by adding and running a !uv pip install cell. The cell persists immediately, so this requires deploy permission. Packages last for the kernel’s lifetime, and rerunning the notebook reinstalls them.
attach_secrets_to_notebookAttach existing environment secrets to a notebook by reference, without values passing through the conversation.

Sandboxes

These tools run commands or Python in a general-purpose sandbox.

ToolDescription
start_sandboxStart a general-purpose sandbox and return its id, for reuse across exec_in_sandbox calls. Defaults to the python:3.12-slim image.
exec_in_sandboxRun a command in an existing sandbox.
eval_pythonExecute Python in a fresh ephemeral sandbox and return its output. Bare expressions produce nothing, so print what you want back. For repeated work, start_sandbox and exec_in_sandbox reuse one container.

Observability and Kubernetes

ToolDescription
get_query_errorsList recorded query errors, with filtering and pagination.
get_query_plan_jsonReturn a chalk://query-plans/... resource URI for a query plan. Plans can run to hundreds of kilobytes, so the tool hands back the URI and the client reads the resource.
get_perf_summary_jsonReturn a chalk://performance-summaries/... resource URI for a query’s performance summary, read the same way as a query plan.
search_logsSearch application logs for the environment.
inspect_log_facetsList log facets, or inspect the observed values and counts for one facet.
search_tracesSearch distributed traces and their spans.
search_kube_eventsSearch Kubernetes cluster events (scheduling, OOM kills, crashes).
list_kube_events_in_namespaceList recent Kubernetes events in one namespace.
get_kube_podInspect a pod’s specification, status, and recorded events.
inspect_kube_deploymentsList Kubernetes deployments or inspect one deployment in full.
inspect_kube_capacityList or inspect Karpenter NodePools and NodeClasses.
get_unschedulable_workloadsDiagnose workloads that Kubernetes cannot schedule.

Datasets, dashboards, monitors, and volumes

ToolDescription
list_datasetsList datasets and their latest revision metadata.
inspect_datasetFetch one dataset’s metadata and optionally its revision history.
get_dashboard_authoring_contextReturn the dashboard JSON contract and metric authoring catalog.
find_dashboardsSearch dashboards, or fetch one complete dashboard definition.
validate_dashboardValidate a dashboard definition without saving it.
create_dashboardCreate a dashboard from a validated definition.
get_chartFetch one saved metric chart.
get_monitor_authoring_contextReturn the monitor JSON contract, metric catalog, and alert channels.
find_monitorsList monitors, or fetch one complete monitor definition.
validate_monitorValidate a monitor definition without saving it.
create_monitorCreate a monitor from a validated definition.
list_volumesList Chalk volumes, optionally filtering by name prefix.
create_volumeCreate a versioned Chalk volume.
create_volume_from_github_repoCopy a GitHub repository into a Chalk volume.
create_github_pr_from_volumeOpen a GitHub pull request that makes a repository match a Chalk volume.

Resources and prompts

Alongside tools, the server exposes MCP resources, which a client reads by URI rather than calling. Two tools hand back a resource URI instead of the payload itself, because a query plan or performance summary can run to hundreds of kilobytes.

Two resources are available directly:

URIContents
chalk://sql/catalogsThe ChalkSQL catalogs for the environment, including the built-in chalk catalog, offline_store, and any connected data sources. Use these names when writing ChalkSQL.
chalk://server/infoBasic information about the Chalk server.

Others are addressed by filling in a template:

URI templateContents
chalk://environments/{environment_id}An environment’s name, project, cloud provider, and region.
chalk://sql/schemas/{catalog}The schemas within a ChalkSQL catalog.
chalk://query-plans/{query_plan_id}A query plan, as JSON. Call get_query_plan_json first to obtain a valid URI.
chalk://performance-summaries/{operation_id}A query’s performance summary, as JSON. Call get_perf_summary_json first to obtain a valid URI.

The server also advertises resource subscriptions, so a client that supports them can be notified when a resource changes.

One prompt is available, help, which takes a topic argument and returns guidance on Chalk operations.


See also

  • MCP Gateway: register and govern the external MCP servers your agents reach.
  • AI Router: an OpenAI-compatible LLM gateway for your Chalk deployment.
  • Authentication: service credentials and RBAC for the Chalk API.
  • Development with LLMs: prompts for writing Chalk code with AI assistants.
  • ChalkSQL: the SQL dialect available through execute_sql_query.