CockroachDB MCP Server is a Model Context Protocol server that exposes CockroachDB to AI agents as a set of typed tools. Ships read tools by default; write and DDL tools opt in via env var.
Requires Go 1.26+ and a reachable CockroachDB cluster.
go install github.com/cockroachdb/cockroachdb-mcp-server@latestThe binary lands in $(go env GOPATH)/bin/cockroachdb-mcp-server.
Grab a tarball for linux/{amd64,arm64} or windows/{amd64,arm64} from
Releases,
available from the first release onwards.
Multi-arch images (linux/amd64, linux/arm64) are published to Google
Artifact Registry on every release:
docker pull us-docker.pkg.dev/releases-prod/cockroachdb-mcp-server/cockroachdb-mcp-server:<version>Replace <version> with a release listed on the Releases page, or list available image tags directly:
gcloud artifacts docker tags list us-docker.pkg.dev/releases-prod/cockroachdb-mcp-server/cockroachdb-mcp-serverThe image runs as nonroot on distroless.
macOS users on Apple Silicon can run the linux/arm64 image natively via Docker.
git clone https://github.com/cockroachdb/cockroachdb-mcp-server
cd cockroachdb-mcp-server
go build -o bin/cockroachdb-mcp-server .
./bin/cockroachdb-mcp-server --versionmacOS: use go install or build from source. Pre-built binaries do not cover
darwin because a CockroachDB parser dependency needs cgo on macOS.
Drop one of the following into your MCP client's config (Claude Desktop, Cursor,
VS Code, Copilot CLI, etc.). Each client reads an mcpServers block or its own
equivalent; see your client's docs for the file location.
GUI clients (e.g. Claude Desktop) often launch with a minimal PATH and do not expand
~, so a barecommandmay not resolve; use the absolute binary path instead, e.g./Users/<username>/go/bin/cockroachdb-mcp-server.
{
"mcpServers": {
"cockroachdb": {
"command": "cockroachdb-mcp-server",
"env": {
"CRDB_HOST": "my-cluster.crdb.io",
"CRDB_USERNAME": "ai_agent",
"CRDB_SSL_MODE": "verify-full",
"CRDB_SSL_CA_PATH": "/certs/ca.crt",
"CRDB_SSL_CERTFILE": "/certs/client.ai_agent.crt",
"CRDB_SSL_KEYFILE": "/certs/client.ai_agent.key"
}
}
}
}{
"mcpServers": {
"cockroachdb": {
"command": "cockroachdb-mcp-server",
"env": {
"CRDB_DATABASE_URL": "postgresql://ai_agent@my-cluster.crdb.io:26257/defaultdb?sslmode=verify-full&sslcert=/certs/client.ai_agent.crt&sslkey=/certs/client.ai_agent.key&sslrootcert=/certs/ca.crt"
}
}
}
}For a local cockroach start-single-node --insecure or cockroach demo --insecure
cluster, opt in to a TLS-free connection; no cert files are needed:
{
"mcpServers": {
"cockroachdb": {
"command": "cockroachdb-mcp-server",
"env": {
"CRDB_DATABASE_URL": "postgresql://root@localhost:26257/defaultdb?sslmode=disable",
"CRDB_MCP_ALLOW_INSECURE_DB": "true",
"CRDB_MCP_ENABLE_WRITE_QUERIES": "true"
}
}
}
}Run the server as a long-lived process, then point your MCP client at the URL with the bearer token:
export CRDB_DATABASE_URL="postgresql://..."
export CRDB_MCP_TRANSPORT=http
export CRDB_MCP_HTTP_LISTEN_ADDR=0.0.0.0:8443
export CRDB_MCP_BEARER_TOKEN="$(openssl rand -hex 32)"
export CRDB_MCP_TLS_CERT=/etc/mcp/tls.crt
export CRDB_MCP_TLS_KEY=/etc/mcp/tls.key
cockroachdb-mcp-serverSet CRDB_MCP_HTTP_LISTEN_ADDR to whatever host:port fits your deployment,
for example 127.0.0.1:9090 to serve only local traffic behind a
TLS-terminating reverse proxy (with CRDB_MCP_ALLOW_INSECURE_HTTP=true), or
10.0.0.5:8443 to bind a specific interface.
Then point your MCP client at the server:
{
"mcpServers": {
"cockroachdb": {
"type": "http",
"url": "https://mcp.example.com:8443",
"headers": {
"Authorization": "Bearer <token>"
}
}
}
}HTTP mode is TLS-by-default. Starting without
CRDB_MCP_TLS_CERTandCRDB_MCP_TLS_KEYis rejected unlessCRDB_MCP_ALLOW_INSECURE_HTTP=true(for deployments behind a TLS-terminating reverse proxy)./healthzand/readyare unauthenticatedGET/HEADprobes; all other paths require the bearer token.
All configuration is via environment variables.
Stdio mode: The server runs as a subprocess of the AI agent host.
Cert-based auth is recommended. The server can read CRDB_PWD,
a password embedded in CRDB_DATABASE_URL, PGPASSWORD, or ~/.pgpass
from its process environment.
To protect those credentials, password-based auth is rejected by default.
Set CRDB_MCP_ALLOW_PASSWORD_AUTH=true to opt in.
HTTP mode: Clients authenticate to the MCP server with a bearer token
(CRDB_MCP_BEARER_TOKEN) - see HTTPS setup
for token generation. TLS is required by default; cleartext HTTP
requires CRDB_MCP_ALLOW_INSECURE_HTTP=true (for deployments behind a
TLS-terminating reverse proxy). Organizations that handle auth upstream
(reverse proxy, gateway, mTLS) can set CRDB_MCP_ALLOW_NO_BEARER=true
to skip bearer enforcement.
CRDB_DATABASE_URL (a full libpq connection string) takes precedence over the
split vars below. In both auth modes sslmode must be require, verify-ca,
or verify-full; a CRDB_DATABASE_URL that omits sslmode is rejected at
startup, and the TLS-optional modes (disable, allow, prefer) require
CRDB_MCP_ALLOW_INSECURE_DB=true.
| Variable | Purpose | Default |
|---|---|---|
CRDB_HOST |
Hostname | required |
CRDB_PORT |
Port | 26257 |
CRDB_USERNAME |
SQL user | required |
CRDB_PWD |
Password (discouraged, see note above) | - |
CRDB_SSL_MODE |
require, verify-ca, or verify-full; disable, allow, prefer with CRDB_MCP_ALLOW_INSECURE_DB=true |
verify-full |
CRDB_SSL_CA_PATH |
CA cert path (required for verify-ca / verify-full) |
- |
CRDB_SSL_CERTFILE |
Client cert path | required |
CRDB_SSL_KEYFILE |
Client key path | required |
| Variable | Purpose | Default |
|---|---|---|
CRDB_MCP_QUERY_TIMEOUT |
Per-query timeout (Go duration, e.g. 30s) |
30s |
CRDB_MCP_MAX_ROWS_COUNT |
Cap on the max LIMIT list-style tools issue to CRDB | 10000 |
CRDB_MCP_MAX_CONNS |
Upper bound on the pgxpool connection count (≤ 100) | 10 |
CRDB_MCP_TXN_QOS |
Default transaction QoS: background, regular, or critical |
background |
CRDB_MCP_ENABLE_WRITE_QUERIES |
Gate for the write tools (create_database, create_table, insert_rows, update_rows, delete_rows) |
false |
CRDB_MCP_ALLOW_PASSWORD_AUTH |
Opt-in to password-based auth | false |
CRDB_MCP_ALLOW_INSECURE_DB |
Opt-in to the sslmode values that can run without TLS: disable, allow, prefer. Cert env vars are not required in these modes. Development only |
false |
MCP traffic runs at default_transaction_quality_of_service=background by
default so it does not contend with latency-sensitive foreground workloads.
Precedence for picking the value:
CRDB_MCP_TXN_QOSif set (background,regular, orcritical).- Otherwise, a
default_transaction_quality_of_service=...query param inCRDB_DATABASE_URL, if present. - Otherwise,
background.
| Variable | Purpose | Default |
|---|---|---|
CRDB_MCP_TRANSPORT |
stdio or http |
stdio |
CRDB_MCP_HTTP_LISTEN_ADDR |
Listen address in HTTP mode, any host:port. Omit the host to bind all interfaces. Examples: :8080, 0.0.0.0:8443, 127.0.0.1:9090 |
:8080 |
CRDB_MCP_BEARER_TOKEN |
Bearer token clients must send in Authorization: Bearer <token>. Required in HTTP mode unless CRDB_MCP_ALLOW_NO_BEARER=true; must be at least 16 chars |
- |
CRDB_MCP_TLS_CERT |
PEM-encoded server cert path. Required for HTTPS unless CRDB_MCP_ALLOW_INSECURE_HTTP=true |
- |
CRDB_MCP_TLS_KEY |
PEM-encoded private key path. Required for HTTPS unless CRDB_MCP_ALLOW_INSECURE_HTTP=true |
- |
CRDB_MCP_ALLOW_INSECURE_HTTP |
Opt-in to cleartext HTTP (for reverse-proxy deployments) | false |
CRDB_MCP_ALLOW_NO_BEARER |
Opt-in to skip bearer auth (for upstream-auth deployments). Startup warning logged | false |
| Variable | Purpose | Default |
|---|---|---|
CRDB_MCP_LOG_LEVEL |
debug, info, warn, error |
info |
CRDB_MCP_LOG_PATH |
Log file path, or - for stderr. No rotation; use logrotate or your orchestrator |
- |
Tracing is opt-in: with neither variable below set, no exporter is installed. When enabled, tool calls and their SQL statements are exported as spans, and server logs as OTel log records. Query text and errors are redacted before export so literals and user data never leave the server.
| Variable | Purpose | Default |
|---|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT |
OTLP gRPC endpoint; the standard OTEL_* env vars are honored |
- |
CRDB_MCP_OTEL_FILE |
Write traces and logs as JSON lines to this file instead (takes precedence) | - |
In stdio mode, add the variable to the env block of your
MCP client config; in HTTP mode, export it in
the server's environment:
{
"env": {
"CRDB_DATABASE_URL": "postgresql://...",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317"
}
}Grant the connecting SQL role only the privileges the registered tools need. Avoid admin and write privileges unless write tools are explicitly registered; see Security for a role recipe.
CRDB_MCP_ENABLE_WRITE_QUERIES enables all write tools together. For
per-operation control, grant the connecting role only the SQL privileges you
want, for example SELECT, INSERT, and UPDATE but not DELETE to allow
writes without deletes.
| Tool | Description |
|---|---|
list_databases |
List all databases. Optional limit (default 100, max 10000) and offset. |
list_tables |
List tables in a database. Required: database. Optional: limit, offset. |
get_table_schema |
Return the CREATE TABLE for a table. Required: database, table. Optional: schema (default public). |
get_cluster |
Cluster identity and version metadata: cluster_id, cluster_name, binary_version. Identity fields need crdb_internal access (restricted by default on v25.4+); when unavailable they are null with the reason under unavailable. |
list_sql_users |
SQL users in the cluster. Optional: limit, offset. |
list_cluster_nodes |
Cluster nodes with address, liveness, locality. Requires admin or VIEWCLUSTERMETADATA. |
show_running_queries |
Currently executing statements, ordered by start time descending. Optional: limit, offset. |
select_query |
Execute a SELECT statement. A default LIMIT of 100 is appended when none is supplied; cap is CRDB_MCP_MAX_ROWS_COUNT. |
explain_query |
Return the EXPLAIN plan for a statement without executing it. EXPLAIN ANALYZE (and EXPLAIN ANALYZE (DEBUG)) is rejected. Display options (VERBOSE, DISTSQL, TYPES, OPT, etc.) pass through. |
show_statement |
Execute a SHOW statement such as SHOW SCHEMAS, SHOW INDEXES, SHOW REGIONS, SHOW JOBS. Optional: limit, offset. |
| Tool | Description |
|---|---|
create_database |
Create a database. Required: name. |
create_table |
Execute a single CREATE TABLE statement. Required: statement. |
insert_rows |
Execute a single INSERT statement; returns rows affected. Required: statement. |
update_rows |
Execute a single UPDATE statement; a WHERE clause is mandatory. Returns rows affected. Required: statement. |
delete_rows |
Execute a single DELETE statement; a WHERE clause is mandatory. Returns rows affected. Required: statement. |
Any write tool that includes a RETURNING clause returns the affected rows instead of just the count.
go test ./...Interactive inspection via MCP Inspector:
npm install -g @modelcontextprotocol/inspector
mcp-inspector cockroachdb-mcp-serverSee CONTRIBUTING.md.
Report vulnerabilities via SECURITY.md.
The server validates statement shape (a single statement per call, a
mandatory WHERE clause on UPDATE and DELETE) but does not restrict
which databases, schemas, or tables a statement may target. Every tool call
runs with the full privileges of the connecting SQL role: the role, not the
server, is the security boundary.
Connect as a dedicated role scoped to just what the agent needs, never as
root or an admin member; see
CREATE ROLE,
GRANT, and the
authorization overview.
Grant SELECT on the tables the agent should see, add DML privileges per
table only when write mode is on, and GRANT SYSTEM VIEWACTIVITYREDACTED, VIEWCLUSTERMETADATA if the cluster introspection tools are needed.
Note that the server cannot tell an operator-intended tool call from one induced by attacker-controlled content the agent has read (prompt injection); the role scoping above is the containment for that. MCP tool annotations are hints to the client, not a server-side control.
