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:

The scope to pick, by what the agent is for.
ScopeGive it when the agent should…
readbrowse pipelines, templates, datasources and past executions
executealso run pipelines and read their results
authoralso 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.invalid or auth.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. /mcp takes 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.