# Connect an MCP client

> Set up Claude Code, Codex CLI, Cursor, VS Code, Claude Desktop, and other MCP clients to use PacketStream's remote MCP server with your API key.

**Early beta.** Fields, limits, and availability may change during the beta. These pages describe what the API serves today. Questions or problems? [Contact support](https://packetstream.io/contact-us/).

Any MCP client that supports remote Streamable HTTP servers and lets you set an `Authorization` header can use the tools. Replace `YOUR_API_KEY` with your key from the [MCP page of the dashboard](https://app.packetstream.io/dashboard/mcp). No account or key yet? See [these steps](https://packetstream.io/docs/mcp/#no-account-or-key-yet).

The server connects without a key and checks the key only when your agent calls a tool. A client that shows the server as connected has therefore not checked your key. Use the free [key check](https://packetstream.io/docs/mcp/#check-your-key) for that.

What we tested on October 7, 2026:

- **Tested against the live server:** Claude Code 2.1.284, Codex CLI 0.159.0, and the `mcp-remote` 0.14.2 bridge that the Claude Desktop setup runs.
- **Tested without a valid key:** the same three clients connect, list the tools, and pass the steps from each [key error](https://packetstream.io/docs/mcp/reference/#key-errors) on to the user.
- **Not tested by us:** the Claude Desktop app itself, Cursor, VS Code, and the other clients below. Their steps follow each vendor's documentation as of October 2026. Check your client's current documentation if a step does not match.

## Claude Code

Run this in a terminal:

```bash
export PACKETSTREAM_API_KEY="YOUR_API_KEY"
claude mcp add --transport http --scope user packetstream https://api.packetstream.io/v1/mcp \
  --header 'Authorization: Bearer ${PACKETSTREAM_API_KEY}'
claude mcp list
```

- The single quotes store the variable name, not the key, in Claude Code's settings. Add the `export` line to your shell profile so the variable is set wherever Claude Code starts.
- Keep `--header` after the URL. Placed before the server name, the command fails with `missing required argument 'name'`.
- `--scope user` makes the server available in every project. Without it, the server is added to the current project only.
- `claude mcp list` should show `packetstream` as connected. That does not prove the key works.

To share the server with a team, commit a `.mcp.json` file at the repository root. Each person sets `PACKETSTREAM_API_KEY`, and Claude Code asks them to approve the server:

```json
{
  "mcpServers": {
    "packetstream": {
      "type": "http",
      "url": "https://api.packetstream.io/v1/mcp",
      "headers": { "Authorization": "Bearer ${PACKETSTREAM_API_KEY}" }
    }
  }
}
```

## Codex CLI

Codex reads the key from an environment variable and sends it as the bearer token, so set the variable to the bare key:

```bash
export PACKETSTREAM_API_KEY="YOUR_API_KEY"
codex mcp add packetstream --url https://api.packetstream.io/v1/mcp \
  --bearer-token-env-var PACKETSTREAM_API_KEY
```

The command writes this to `~/.codex/config.toml`, which you can also edit by hand:

```toml
[mcp_servers.packetstream]
url = "https://api.packetstream.io/v1/mcp"
bearer_token_env_var = "PACKETSTREAM_API_KEY"
```

- Add the `export` line to your shell profile. The variable must be set wherever Codex starts. While it is unset, Codex refuses to start the server, so your agent has no PacketStream tools and no error that explains why.
- Codex needs approval to run an MCP tool. With `approval_policy = "never"` it cannot ask, so it refuses every PacketStream call before the call reaches the server, with the error `MCP tool call requires approval, but approval policy is never`. To let the tools run without asking, add `default_tools_approval_mode = "approve"` to the `[mcp_servers.packetstream]` table. Every successful call is billed.
- `codex mcp list` shows the saved configuration but does not test the connection. To check the key, use the free [key check](https://packetstream.io/docs/mcp/#check-your-key).
- Apps that read the same file, such as the ChatGPT desktop app, see the variable only if it is in their own launch environment. An app opened from the Dock, the Start menu, or a desktop launcher usually does not see variables exported in a shell profile.

## Cursor

Add this to `~/.cursor/mcp.json` for every project, or to `.cursor/mcp.json` for one project:

```json
{
  "mcpServers": {
    "packetstream": {
      "url": "https://api.packetstream.io/v1/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}
```

In a project file that you commit, write `"Bearer ${env:PACKETSTREAM_API_KEY}"` instead, so the key stays in your environment.

## VS Code

Add this to `.vscode/mcp.json` in a workspace, or run **MCP: Open User Configuration** to add it for every workspace. VS Code asks for the key once and stores it securely:

```json
{
  "inputs": [
    {
      "type": "promptString",
      "id": "packetstream-api-key",
      "description": "PacketStream API key",
      "password": true
    }
  ],
  "servers": {
    "packetstream": {
      "type": "http",
      "url": "https://api.packetstream.io/v1/mcp",
      "headers": { "Authorization": "Bearer ${input:packetstream-api-key}" }
    }
  }
}
```

## Claude Desktop

Claude Desktop's configuration file starts local servers only, so it connects through the community [`mcp-remote`](https://github.com/geelen/mcp-remote) bridge, which needs Node.js. Open **Settings > Developer > Edit Config**, add this to `claude_desktop_config.json`, and restart Claude Desktop:

```json
{
  "mcpServers": {
    "packetstream": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.packetstream.io/v1/mcp",
        "--transport",
        "http-only",
        "--header",
        "Authorization:${PACKETSTREAM_AUTH_HEADER}"
      ],
      "env": { "PACKETSTREAM_AUTH_HEADER": "Bearer YOUR_API_KEY" }
    }
  }
}
```

- The header argument has no space after the colon on purpose, because some systems split arguments at spaces. `mcp-remote` fills in the variable from `env`.
- When it starts, `mcp-remote` looks for OAuth metadata on the server, with or without a key. The server has none and answers 404, so `mcp-remote` connects with your header and never opens a browser.
- The Code tab in Claude Desktop uses Claude Code's settings instead. Set it up as in [Claude Code](https://packetstream.io/docs/mcp/clients/#claude-code).

## Other clients

Clients that support remote HTTP servers with custom headers usually take a configuration like this. Key names vary by client:

```json
{
  "mcpServers": {
    "packetstream": {
      "type": "http",
      "url": "https://api.packetstream.io/v1/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}
```

Choose the client's Streamable HTTP transport, not SSE: the server never streams, and a GET returns 405. Two clients that default to SSE:

- **Cline** needs `"type": "streamableHttp"`. Without `type`, it uses SSE.
- **Gemini CLI** needs `httpUrl` instead of `url`. In Gemini CLI, `url` selects SSE.

If your client runs as a local (stdio) server only, use the `mcp-remote` bridge shown under [Claude Desktop](https://packetstream.io/docs/mcp/clients/#claude-desktop).

## Clients that cannot use the tools

- **ChatGPT on the web** cannot send an API key, so every tool call returns `missing_api_key`, even if it adds the server and lists its tools. We have not tested it.
- **Claude custom connectors** (added under Customize > Connectors on claude.ai, Claude Desktop, or mobile) can send your key only through Anthropic's request-header authentication. Anthropic offers it as a beta that is not available to every organization, and we have not tested it. Without it, a connector can list the tools, but every tool call returns `missing_api_key`. Use one of the setups above instead.
- **Web pages and other browser-based clients** cannot call the server: it sends no CORS headers. Never put your key in a web page.

## Troubleshooting

A tool call without a valid key returns an error result instead of search results or a page. It is not billed. Its message asks the agent to tell you so and gives the steps to fix the key. Retrying fails until you fix the key:

- **`missing_api_key`.** The client sent no key, or the variable that should hold the key is empty where the client starts. Add the `Authorization` header to its configuration as shown above, or set the variable, then restart the client.
- **`invalid_api_key`.** The header does not hold a PacketStream key, which is `ps_` followed by 64 lowercase hexadecimal characters. Often the variable meant to hold it, such as `PACKETSTREAM_API_KEY`, is not set where the client starts, or the configuration still has the `YOUR_API_KEY` placeholder. Fix it so the header reads `Authorization: Bearer <key>`, then restart the client.
- **`unauthorized`.** The key was revoked or replaced, or it was copied wrongly. Rotating or revoking a key on the dashboard disables the old key at once. Create a new key on the [MCP page of the dashboard](https://app.packetstream.io/dashboard/mcp), put it in the client's configuration, and restart the client.

Other problems:

- **The PacketStream tools stopped running or ask for approval again after an update.** Version 1.3.0 renamed `web_search` and `web_fetch` to `packetstream_search` and `packetstream_fetch`. Change any tool allowlist, per-tool approval or permission rule that names the old tools. See the [reference](https://packetstream.io/docs/mcp/reference/).
- **Codex shows no PacketStream tools.** The variable named in `bearer_token_env_var` is not set where Codex starts. See [Codex CLI](https://packetstream.io/docs/mcp/clients/#codex-cli).
- **Codex says `MCP tool call requires approval, but approval policy is never`.** Codex refused the call itself, so it never reached PacketStream and was not billed. See [Codex CLI](https://packetstream.io/docs/mcp/clients/#codex-cli).
- **HTTP 403 "Invalid Origin header".** The client sent a malformed `Origin` header. See the [Origin rules](https://packetstream.io/docs/mcp/reference/#origin-header).
- **HTTP 405.** The client is using SSE or GET. Switch it to Streamable HTTP.
- **Check the key on its own** with the free [key check](https://packetstream.io/docs/mcp/#check-your-key).
