# Connect to the MCP server with an access token
> Authenticate to the remote MotherDuck MCP server with an access token to connect as a service account or from clients that can't use OAuth.
By default, MCP clients sign in to the remote MCP server with OAuth, so the assistant acts as your MotherDuck user. To connect as a [service account](/key-tasks/service-accounts-guide/), or from an agent that can't complete an OAuth sign-in, send a MotherDuck access token in the `Authorization` header instead:

```text
Authorization: Bearer <your_motherduck_token>
```

The MCP server runs every tool call as the user who owns the token. A service account token gives the assistant that service account's databases, shares, and Duckling settings. A [read scaling token](/key-tasks/authenticating-and-connecting-to-motherduck/read-scaling/) works the same way and limits the assistant to read-only queries.

Use this when you want to:

- Give a shared agent, bot, or automation its own identity instead of a person's account.
- Run the MCP server from a headless environment, such as a CI job or a cloud agent, where no one can complete a browser sign-in.
- Enforce read-only access with a [read scaling token](/key-tasks/authenticating-and-connecting-to-motherduck/read-scaling/). See [Restricting to read-only access](/key-tasks/ai-and-motherduck/mcp-workflows/securing-read-only-access/).

## Prerequisites

- A MotherDuck access token. Create a [personal access token](/key-tasks/authenticating-and-connecting-to-motherduck/authenticating-to-motherduck#creating-an-access-token), or a [service account token](/key-tasks/service-accounts-guide/create-and-configure-service-accounts/#create-an-access-token).
- An MCP client that can send a custom header to a remote server. The tabs below cover the clients that support it.

## Configure your client

Most configurations read the token from the `MOTHERDUCK_TOKEN` environment variable, so the token stays out of the config file. Set it in the shell that starts your client:

```bash
export MOTHERDUCK_TOKEN='<your_motherduck_token>'
```

Then select your client:

### Claude

On Claude web and Claude Desktop, add MotherDuck as a custom connector that sends the token as a request header.

:::note
[Request header authentication](https://claude.com/docs/connectors/custom/add-unlisted#authenticate-with-request-headers) is in beta for a limited set of Claude organizations. If you don't see **Request headers** in the **Add custom connector** dialog, use the Claude Desktop config below.
:::

1. Open the **Add custom connector** dialog:
   - On Free, Pro, and Max plans, go to **Customize** → **Connectors** and click **Add custom connector**.
   - On Team and Enterprise plans, an Owner goes to **Organization settings** → **Connectors**, clicks **Add**, and selects **Custom**.
2. Enter `https://api.motherduck.com/mcp` as the server URL.
3. Under **Authentication**, choose **No sign-in**.
4. Under **Request headers**, select `authorization` as the header name and enter `Bearer <your_motherduck_token>` as the value. Claude sends the value exactly as entered, so include the `Bearer ` prefix.
5. Click **Add**.

Claude doesn't let you edit request headers after you add the connector. To rotate the token, remove the connector and add it again.

**Claude Desktop config**

If your organization doesn't have request headers, connect Claude Desktop through [`mcp-remote`](https://www.npmjs.com/package/mcp-remote), which bridges the remote server into a local server and adds the header. Go to **Settings** → **Developer** → **Edit Config** and add:

```json
{
  "mcpServers": {
    "MotherDuck": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://api.motherduck.com/mcp",
        "--header",
        "Authorization:${AUTH_HEADER}"
      ],
      "env": {
        "AUTH_HEADER": "Bearer <your_motherduck_token>"
      }
    }
  }
}
```

Keep the header argument without spaces. Claude Desktop on Windows doesn't escape spaces inside `args`, so the space after `Bearer` goes in the `env` value. Restart Claude Desktop after you save the file. This method requires [Node.js](https://nodejs.org/) for `npx`.

### ChatGPT

[Custom MCP servers](https://help.openai.com/en/articles/12584461) with full MCP support are available on ChatGPT Business, Enterprise, and Edu plans, on the web. On Business, only admins and owners can add them. On Enterprise and Edu, admins can grant the **Create plugins with MCPs** permission to selected members.

1. Go to [ChatGPT Plugins](https://chatgpt.com/plugins), click **+**, and select **Add custom MCP server**.
2. Enter `MotherDuck` as the name.
3. Under **Connection**, select **Server URL** and enter `https://api.motherduck.com/mcp`.
4. Under **Authentication**, select **Access token / API key** and enter your MotherDuck token.
5. Review the risk warning, select **I understand and want to continue**, and select **Create as a plugin**.

Access token authentication isn't available on every plan. If **Authentication** only offers **OAuth** and **No Auth**, you can't connect ChatGPT with a token. To give ChatGPT users access through a service account anyway, run your own MCP server that signs users in with OAuth and calls MotherDuck with the service account token on the backend. See [White-label the MotherDuck MCP server](/key-tasks/ai-and-motherduck/mcp-workflows/white-label-mcp-server/).

### Cursor

Add the server to `~/.cursor/mcp.json` for all projects, or `.cursor/mcp.json` for one project:

```json
{
  "mcpServers": {
    "MotherDuck": {
      "url": "https://api.motherduck.com/mcp",
      "headers": {
        "Authorization": "Bearer ${env:MOTHERDUCK_TOKEN}"
      }
    }
  }
}
```

Cursor reads `MOTHERDUCK_TOKEN` from the environment it starts in. If you launch Cursor from the Dock or Start menu, set the variable in your shell profile or system environment, then restart Cursor.

> [Cursor MCP documentation](https://cursor.com/docs/context/mcp)

### Claude Code

Run this command in your terminal:

```bash
claude mcp add --transport http --scope user MotherDuck \
  https://api.motherduck.com/mcp \
  --header 'Authorization: Bearer ${MOTHERDUCK_TOKEN}'
```

The single quotes keep your shell from expanding the variable, so Claude Code stores `${MOTHERDUCK_TOKEN}` and reads the token from the environment each time it connects.

Run `claude mcp get MotherDuck` to check the connection. When an `Authorization` header is set, Claude Code doesn't fall back to OAuth, so a missing or invalid token shows as a failed connection.

> [Claude Code MCP documentation](https://code.claude.com/docs/en/mcp)

### Codex

Run this command in your terminal:

```bash
codex mcp add motherduck \
  --url https://api.motherduck.com/mcp \
  --bearer-token-env-var MOTHERDUCK_TOKEN
```

Or add the server to `~/.codex/config.toml` directly:

```toml
[mcp_servers.motherduck]
url = "https://api.motherduck.com/mcp"
bearer_token_env_var = "MOTHERDUCK_TOKEN"
```

Codex reads the token from `MOTHERDUCK_TOKEN` and sends it as a Bearer token. The Codex CLI, IDE extension, and desktop app share this configuration.

> [Codex MCP documentation](https://learn.chatgpt.com/docs/extend/mcp?surface=cli)

### VS Code

Add this configuration to `.vscode/mcp.json`. VS Code prompts for the token when the server starts and stores it in its secret store:

```json
{
  "inputs": [
    {
      "type": "promptString",
      "id": "motherduck-token",
      "description": "MotherDuck access token",
      "password": true
    }
  ],
  "servers": {
    "motherduck": {
      "type": "http",
      "url": "https://api.motherduck.com/mcp",
      "headers": {
        "Authorization": "Bearer ${input:motherduck-token}"
      }
    }
  }
}
```

> [VS Code MCP documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers)

### Gemini CLI

Add this server to `~/.gemini/settings.json`, or your project's `.gemini/settings.json`:

```json
{
  "mcpServers": {
    "motherduck": {
      "httpUrl": "https://api.motherduck.com/mcp",
      "headers": {
        "Authorization": "Bearer ${MOTHERDUCK_TOKEN}"
      }
    }
  }
}
```

Run `gemini mcp list` and confirm that **motherduck** is connected.

> [Gemini CLI MCP documentation](https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md)

### Copilot Studio

Follow the [Copilot Studio setup](/key-tasks/ai-and-motherduck/mcp-workflows/mcp-setup/?mcp-client=copilot-studio) and choose **API key** authentication. Set **Type** to `Header` and **Header name** to `Authorization`. When you create the connection, enter the token with the `Bearer ` prefix:

```text
Bearer <your_motherduck_token>
```

All users of the agent share this token.

### Others

For clients that support remote HTTP servers with custom headers, use this configuration and check your client's documentation for how it reads environment variables:

```json
{
  "mcpServers": {
    "MotherDuck": {
      "url": "https://api.motherduck.com/mcp",
      "type": "http",
      "headers": {
        "Authorization": "Bearer <your_motherduck_token>"
      }
    }
  }
}
```

For clients that only support local (stdio) servers, bridge the connection with [`mcp-remote`](https://www.npmjs.com/package/mcp-remote):

```json
{
  "mcpServers": {
    "MotherDuck": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://api.motherduck.com/mcp",
        "--header",
        "Authorization:${AUTH_HEADER}"
      ],
      "env": {
        "AUTH_HEADER": "Bearer <your_motherduck_token>"
      }
    }
  }
}
```

## Verify the connection

Start a new chat and ask "List all my databases on MotherDuck". The assistant should call a MotherDuck tool and return the databases of the token's owner. For a service account token, you see the service account's databases, not your own.

## Troubleshooting

| Error | Cause and fix |
|-------|---------------|
| `Authentication required. Please authenticate using OAuth or provide a Bearer token.` | The client sent no token, or an empty one. Check that `MOTHERDUCK_TOKEN` is set in the environment that starts the client, then restart the client. |
| `Invalid token format: not a valid JWT` | The header value isn't a MotherDuck token. Check that the variable expanded and that the value is `Bearer ` followed by the full token. |
| A message that starts with `Invalid token:` | MotherDuck rejected the token. Check that you copied the full token and that it hasn't been revoked. |

## Related content

- [Connect to the MotherDuck MCP server](/key-tasks/ai-and-motherduck/mcp-workflows/mcp-setup/)
- [Restricting to read-only access](/key-tasks/ai-and-motherduck/mcp-workflows/securing-read-only-access/)
- [Proxy filtering](/key-tasks/ai-and-motherduck/mcp-workflows/securing-read-only-access/#proxy-filtering)
- [White-label the MotherDuck MCP server](/key-tasks/ai-and-motherduck/mcp-workflows/white-label-mcp-server/)
- [Service accounts guide](/key-tasks/service-accounts-guide/)


---

## Docs feedback

MotherDuck accepts optional user-submitted feedback about this page at `GET https://motherduck.com/docs/api/feedback/agent`.
For agents and automated tools, feedback submission should be user-confirmed before sending.

URL-encode query parameter values and send a GET request:

```text
GET https://motherduck.com/docs/api/feedback/agent?page_path=%2Fkey-tasks%2Fai-and-motherduck%2Fmcp-workflows%2Fconnect-with-access-token%2F&page_title=Connect%20to%20the%20MCP%20server%20with%20an%20access%20token&text=<url-encoded user feedback, max 2000 characters>
```

Optionally append `&source=<url-encoded interface identifier>` such as `claude.ai` or `chatgpt`.

`page_path` and `text` are required; `page_title` and `source` are optional. Responses: `200 {"feedback_id": "<uuid>"}`, `400` for malformed query parameters, and `429` when rate-limited.
