# Connect an MCP client

> Step-by-step setup for Cursor, Claude Code, Claude Desktop, VS Code, the OpenAI Responses API, Anthropic's MCP connector and custom clients.

Source: https://dev.ody.co/mcp/connect

Every client needs the same two things:

| | Value |
|---|---|
| Server URL | `https://api.ody.co/v1/mcp` |
| Transport | Streamable HTTP |
| Header | `Authorization: Bearer ody_live_…` (or `ody_test_…`) |

Create the key in **Settings → Developer API** ([open it](https://app.ody.co/?settings=developer)). For a first try, use a **test key** with every scope. For a production assistant, grant only the scopes it needs (see [Safety](https://dev.ody.co/mcp/safety)).

> **Keep the key out of shared files:**
Anyone holding the key can act as you in the workspace. Use your client's environment-variable support where it has it, and don't commit config files that contain a key.

## Cursor

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

.cursor/mcp.json:

```json
{
  "mcpServers": {
    "ody": {
      "url": "https://api.ody.co/v1/mcp",
      "headers": { "Authorization": "Bearer ${env:ODY_API_KEY}" }
    }
  }
}
```

Open **Cursor Settings → MCP**, check that **ody** shows a green dot and 20 tools, then ask the agent: *"Give me a summary of my Ody workspace."*

## Claude Code

```bash
claude mcp add --transport http ody https://api.ody.co/v1/mcp \
  --header "Authorization: Bearer $ODY_API_KEY"
```

Run `claude mcp list` to confirm the server is connected, and type `/mcp` in a session to see the tools.

## Claude Desktop

Claude Desktop reads local servers from its config file, so bridge to the hosted server with [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) (needs Node.js 18+). Open **Settings → Developer → Edit Config**:

claude_desktop_config.json:

```json
{
  "mcpServers": {
    "ody": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote", "https://api.ody.co/v1/mcp",
        "--header", "Authorization:${ODY_AUTH}"
      ],
      "env": { "ODY_AUTH": "Bearer ody_live_…" }
    }
  }
}
```

Restart Claude Desktop. The tools appear under the tools icon in the chat box.

> **Claude.ai and ChatGPT custom connectors:**
The web connector UIs in Claude.ai and ChatGPT expect servers that sign in with **OAuth**. Ody's MCP server authenticates with API keys, so use the desktop or CLI setups on this page, or call it from the APIs below. OAuth sign-in for these connector directories is on the roadmap.

## VS Code (GitHub Copilot)

.vscode/mcp.json:

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

## OpenAI Responses API

Pass Ody as a remote MCP tool. OpenAI's servers call Ody directly:

Python:

```python
from openai import OpenAI
import os

client = OpenAI()
resp = client.responses.create(
    model="gpt-5",
    tools=[{
        "type": "mcp",
        "server_label": "ody",
        "server_url": "https://api.ody.co/v1/mcp",
        "headers": {"Authorization": f"Bearer {os.environ['ODY_API_KEY']}"},
        "require_approval": "never",  # or "always" / per-tool, see below
    }],
    input="Which conversations are still open? Summarise each in one line.",
)
print(resp.output_text)
```
TypeScript:

```ts
import OpenAI from "openai";

const client = new OpenAI();
const resp = await client.responses.create({
  model: "gpt-5",
  tools: [{
    type: "mcp",
    server_label: "ody",
    server_url: "https://api.ody.co/v1/mcp",
    headers: { Authorization: `Bearer ${process.env.ODY_API_KEY}` },
    require_approval: "never",
  }],
  input: "Which conversations are still open? Summarise each in one line.",
});
console.log(resp.output_text);
```

For write tools, keep approvals on (`"require_approval": "always"`, or `{"never": {"tool_names": ["list_conversations", "get_conversation", "search_messages", "workspace_summary"]}}`), or limit `allowed_tools`.

## Anthropic Messages API (MCP connector)

```python
import anthropic, os

client = anthropic.Anthropic()
resp = client.beta.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    betas=["mcp-client-2025-04-04"],
    mcp_servers=[{
        "type": "url",
        "name": "ody",
        "url": "https://api.ody.co/v1/mcp",
        "authorization_token": os.environ["ODY_API_KEY"],
    }],
    messages=[{"role": "user", "content": "Text +15125550123: 'Your order is ready for pickup.'"}],
)
```

`authorization_token` is sent as `Authorization: Bearer <token>`, which is exactly what Ody expects. Model names and beta flags change over time, so check Anthropic's current docs.

## Custom clients

Any client that speaks Streamable HTTP works. With the official TypeScript SDK:

```ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const transport = new StreamableHTTPClientTransport(new URL("https://api.ody.co/v1/mcp"), {
  requestInit: { headers: { Authorization: `Bearer ${process.env.ODY_API_KEY}` } },
});
const client = new Client({ name: "my-agent", version: "1.0.0" });
await client.connect(transport);

const { tools } = await client.listTools();
const summary = await client.callTool({ name: "workspace_summary", arguments: {} });
```

Or skip the SDK and send JSON-RPC yourself: see [Protocol details](https://dev.ody.co/mcp/protocol#raw-json-rpc).

## Troubleshooting

| Symptom | Fix |
|---|---|
| `401` / JSON-RPC error `-32001 Unauthorized` | The key is missing, mistyped or revoked. The header must be exactly `Bearer <key>` |
| Fewer than 20 tools listed | Expected when the key lacks some scopes. Tools are filtered by scope |
| A tool returns "Unauthorized: this API key does not have the '…' scope" | Create a key with that scope |
| Client tries to open an SSE stream and gets `405` | Expected: the server is stateless and answers each POST with JSON. Modern clients handle this automatically |
| `send_message` returns a 10DLC error | Live texting needs registration. See [Messaging (10DLC)](https://dev.ody.co/api/messaging) |
