- Home
- SQL MCP server
- Add to Claude Code
One endpoint · 41 tools · API keys only
Client setup
Add an MCP server to Claude Code, Cursor or Copilot
This page sets up one particular MCP server — datapipelines.co's, the one that puts your
SQL databases behind scoped, audited, read-only-by-default credentials. It is not a general directory of
MCP servers. If you came looking for how the mcp add mechanics work, they are the same either
way, and the four steps below are the whole job.
Step 1
Have a server to point at
Self-hosted, so the first step is yours. The quickstart brings up the app, Postgres, Redis and a seeded demo with real NYC taxi data in one command:
./app.sh --start --demo nyc,trade,lake
For your own databases, register a datasource per engine — Postgres, SQL Server, SQLite, DuckDB, H2 and dp-lake ship in the published image; the MySQL and Oracle drivers you supply, because of their licenses. Engine-by-engine details.
Step 2
Mint a key for that one agent
Sign in and open the API section — /api-console, where the endpoints a key may
call and the MCP connection block live beside the keys themselves. New key asks in this order:
the kind (an agent's key is the user kind — the same credential a program uses over REST),
the scope, a name for you to recognise it by, and an expiry. Copy the secret — the plaintext is shown
once, in a panel that stays put rather than a toast that does not. Afterwards the list shows the prefix
only.
Scopes are hierarchical, and the smallest one that does the job is the right one:
| Scope | Give it when the agent should… |
|---|---|
read | browse pipelines, templates, datasources and past executions |
execute | also run pipelines and read their results |
author | also create and update pipelines and templates, and introspect schemas |
There is no admin scope to pick: administration is for signed-in people, and a key that asked for it would be refused at issuance. The three above are the whole list.
A key's scopes can never exceed the scopes of whoever issued it, and the select you see is filtered to your own — the server refuses a superset regardless, so the filter is convenience rather than the guard. Revoking is per-key and takes effect within about a minute; an expiry does the same thing on a date you set. No shared password to rotate.
Step 3
Paste one config block
Every client needs the same two facts: the endpoint POST {host}/mcp, over Streamable HTTP, and
an API key in DP-API-Key — or in Authorization: Bearer dpk_…, for clients that can
only set the standard header. Both route through the identical validation path. Browser session cookies are
rejected on /mcp, deliberately.
Claude Code
claude mcp add --transport http datapipelines https://your-host/mcp \
--header "DP-API-Key: dpk_<id>.<secret>"
Cursor — ~/.cursor/mcp.json
{
"mcpServers": {
"datapipelines": {
"url": "https://your-host/mcp",
"headers": { "DP-API-Key": "dpk_<id>.<secret>" }
}
}
}
GitHub Copilot in VS Code — .vscode/mcp.json
{
"servers": {
"datapipelines": {
"type": "http",
"url": "https://your-host/mcp",
"headers": { "DP-API-Key": "dpk_<id>.<secret>" }
}
}
}
Claude Desktop and other JSON-configured clients
{
"mcpServers": {
"datapipelines": {
"url": "https://your-host/mcp",
"headers": { "Authorization": "Bearer dpk_<id>.<secret>" }
}
}
}
The URL and the header are ours, and specified above. The file names and the JSON shape around them belong to each client and change when its vendor changes them — check the client's own documentation if a block here is refused, and tell us so we can fix the page.
Step 4
Check that the tools came back
Ask the agent to list its tools. A working connection reports 41 from this
server, starting with pipelines_list and datasources_list. Nothing else needs
configuring: capabilities come from the standard initialize handshake.
If it does not connect
401 auth.api_key.missing— the header did not arrive. Check the header name, and that the client sends headers at all on HTTP transports.401 auth.api_key.invalidorauth.api_key.expired— wrong, revoked, expired, or the owning user is deactivated.403 auth.scope.insufficient— the key is real and too small for what the agent tried. Mint one at the next scope up rather than widening the one you have.- Silent rejection of a browser session — expected.
/mcptakes API keys only; a cookie will never work there.
The MCP server specification → · Authentication and scopes →
Asked before
Client setup, in questions
Which MCP client should I use?
Any client that speaks MCP over Streamable HTTP: Claude Code, Cursor, GitHub Copilot and JSON-configured clients like Claude Desktop all take the same two facts — the POST /mcp endpoint and an API key header. The transport and authentication are docs/mcp-server.md §3.2.
What scope should the agent's key carry?
The smallest one that does the job: read to browse pipelines and schemas, execute to also run them, author to also create and edit drafts. The key can never exceed its creator's scopes at issue time. The scope table is docs/auth.md §7.5.
Which database drivers ship in the image?
Postgres, SQL Server, SQLite, DuckDB, H2 and dp-lake are bundled; the MySQL and Oracle drivers are user-supplied for license reasons, and registering a datasource whose driver is absent fails at save time. The driver matrix is docs/deployment.md §3.5.
The tools did not come back — what now?
Read the refusal: auth.api_key.missing means the header did not arrive; invalid or expired means wrong, revoked or the owner is deactivated; auth.scope.insufficient means the key is real but too small. A silently ignored browser session is expected — /mcp takes API keys only. The troubleshooting list is docs/mcp-server.md §4.2.
Do the whole loop on the demo
The demo stack is one command, and every step on this page works against it: mint the key, paste the config, list the tools, run a pipeline. Connecting to your own databases is the same ritual with real stakes.