Documentation
MCP for AI agents
Connect Claude, ChatGPT, Codex, Cursor and other MCP clients with OAuth or an API key.
DuckHouse runs a Model Context Protocol server, so Claude, ChatGPT, Codex, Cursor and any other MCP client can explore and query your databases directly. There is nothing to install or host: it is one URL, and a sign-in the first time a tool uses it.
| URL | https://duckhouse.co/api/mcp |
| Transport | Streamable HTTP |
| Authentication | OAuth (sign in when the tool asks), or Authorization: Bearer dhk_… with an API key |
Connect with OAuth
OAuth is the easiest way in, and the one to use for any tool that has a browser nearby. Give the tool the URL above and nothing else. The first time it connects, DuckHouse opens in your browser: sign in, pick the organization the tool should work in and whether it may write, and approve. There is no key to create, copy or rotate, and the consent screen shows you the application's name before you agree to anything.
Behind the scenes the tool registers itself, walks the standard authorization-code flow with PKCE, and gets a short-lived access token plus a refresh token it renews on its own. Any client that follows the MCP authorization spec finds all of this by discovery, so most of the sections below are a single command or a single URL.
Claude Code
claude mcp add --transport http duckhouse https://duckhouse.co/api/mcp
# then, inside Claude Code:
/mcp # pick duckhouse → AuthenticateClaude.ai and Claude Desktop
Under Settings → Connectors, choose Add custom connector, name it DuckHouse and paste the URL. Claude asks you to connect it, which opens the DuckHouse consent screen. Once connected it is available in every chat where you enable it.
ChatGPT
ChatGPT adds MCP servers as apps. Turn on Developer mode under Settings → Security and login (it is available on Plus, Pro, Business, Enterprise and Education plans, on the web). Then open chatgpt.com/plugins, press the plus button and choose Create an app. Give it a name, paste the URL as the MCP server URL and choose OAuth for authentication. Leave the client id and secret empty; ChatGPT registers itself and sends you to the DuckHouse consent screen. Once the app is created, enable it in a chat and ask away.
https://duckhouse.co/api/mcpCodex
codex mcp add duckhouse --url https://duckhouse.co/api/mcp
codex mcp login duckhouse # opens the browser for the OAuth sign-inThe same thing in ~/.codex/config.toml, if you would rather write the file:
[mcp_servers.duckhouse]
url = "https://duckhouse.co/api/mcp"Cursor
Add DuckHouse to .cursor/mcp.json in a project, or ~/.cursor/mcp.json for every project, then press Connect next to it in Cursor's MCP settings to complete the sign-in.
{
"mcpServers": {
"duckhouse": { "url": "https://duckhouse.co/api/mcp" }
}
}VS Code and GitHub Copilot
Run MCP: Add Server from the command palette, choose HTTP and paste the URL, or write .vscode/mcp.json yourself. VS Code handles the browser sign-in when the server first starts.
{
"servers": {
"duckhouse": { "type": "http", "url": "https://duckhouse.co/api/mcp" }
}
}Gemini CLI
gemini mcp add --transport http duckhouse https://duckhouse.co/api/mcp
# then, inside Gemini CLI:
/mcp auth duckhousePi
Pi has no MCP client of its own, on purpose, but the community pi-mcp-adapter extension adds one behind a single proxy tool and supports OAuth. Install it, restart Pi, and describe DuckHouse in .mcp.json in your project or ~/.config/mcp/mcp.json for every project.
pi install npm:pi-mcp-adapter{
"mcpServers": {
"duckhouse": { "url": "https://duckhouse.co/api/mcp", "auth": "oauth" }
}
}Anything else
Windsurf, Zed, Cline, Goose and the rest of the field take the same URL, usually in a JSON file shaped like Cursor's. If a client asks for OAuth details rather than discovering them, these are the facts it wants:
| Authorization server metadata | https://duckhouse.co/.well-known/oauth-authorization-server |
| Protected resource metadata | https://duckhouse.co/.well-known/oauth-protected-resource/api/mcp |
| Client registration | Dynamic (RFC 7591), no pre-registration needed |
| Grant types | Authorization code with PKCE (S256), refresh token |
| Scopes | read or full; you confirm the choice on the consent screen |
| Redirect URIs | Any https URL, http on localhost or 127.0.0.1 on any port, or an app scheme such as cursor:// |
| Token lifetime | Access tokens last an hour; refresh tokens rotate on use and expire after 30 days idle |
To check a client's connection without an agent in the loop, the MCP Inspector (npx @modelcontextprotocol/inspector) speaks the same OAuth flow and lists the tools it sees.
For scripts and servers
Anything without a browser, such as a cron job, a CI step or an agent running on a server, uses an API key instead. Create one under Settings → Organization, and choose the read scope unless the agent genuinely needs to change data. A key is bound to one organization, so there is no organization to pick and no switch_organization.
claude mcp add --transport http duckhouse https://duckhouse.co/api/mcp \
--header "Authorization: Bearer dhk_your_key"export DUCKHOUSE_KEY=dhk_your_key
codex mcp add duckhouse --url https://duckhouse.co/api/mcp --bearer-token-env-var DUCKHOUSE_KEY{
"mcpServers": {
"duckhouse": {
"type": "http",
"url": "https://duckhouse.co/api/mcp",
"headers": { "Authorization": "Bearer dhk_your_key" }
}
}
}Organizations and scope
A connection works in one organization at a time, the one you picked when you signed in. Two ways to change it: under Settings → Profile → Connected applications, or by asking the agent, which has list_organizations and switch_organization tools. Either way it applies to the very next request. The same page changes a connection between read-only and full access, and disconnects it, which ends every token it holds.
Then ask in plain language: “What tables are in my analytics database?” or “Which customers paid the most last quarter?”
Tools
| Tool | Does | Needs |
|---|---|---|
list_databases | Lists your databases with their status. | read |
get_database | One database, including whether it is running yet. | read |
describe_schema | Every table and view with its columns and types. Agents call this before writing SQL. | read |
query | Runs DuckDB SQL. Read-only unless the agent asks for writes. | read |
list_engines | The database types that can be created. | read |
create_database | Provisions a database, optionally temporary. | full |
list_organizations | The organizations this connection can work in, and which one is current. | read |
switch_organization | Makes another of your organizations current. OAuth connections only. | read |
Built to be safe around an agent
- Read-only by default. The
querytool refuses anything that is not a plain query unless the agent setsallowWrites, and that only works with a full-scope key. With a read-scoped key, no prompt can make it write. - Results are capped at 500 rows, so an agent that asks for a whole table does not flood its own context. It is told when a result was cut, and to aggregate instead.
- No tool deletes a database. Deleting is permanent, so it is left to a person, on the database's page in the dashboard.
- Errors come back as text the model can read, so a typo in its SQL is something it can fix on the next try.
- One connection, one organization. A key is bound to its organization for good. An OAuth connection sees only the organization it is switched to, and only while you are still a member of it.
- You always see who is asking. Every OAuth sign-in shows a consent screen with the application's name and where the authorization will be delivered, and asks you to choose the organization and the scope. Tokens are short-lived and rotate, and disconnecting an application revokes them at once.
Good to know
- Queries run on the server, so schema names and joins work as written, including synced Connections data such as
stripe.invoices. - A new database takes about a minute to start. After
create_database, agents are told to pollget_databaseuntil it is running. - Connections are not managed over MCP yet. Use the dashboard or the REST API.
Agent skill
MCP gives an agent tools. The DuckHouse skill gives it the know-how for everything else: attaching from DuckDB, which statements need wh.query(), loading data and the REST API. Coding agents such as Claude Code, Codex and Cursor load it when a task mentions DuckHouse.
npx skills add https://duckhouse.coIt is published at /.well-known/agent-skills/index.json, so any client that discovers skills from a URL finds it. The whole documentation is also available to agents as llms.txt, and every page has a Markdown copy at its URL plus .md.