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.
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). For a first try, use a test key with every scope. For a production assistant, grant only the scopes it needs (see Safety).
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:
{
"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
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 (needs Node.js 18+). Open Settings → Developer → Edit Config:
{
"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.
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)
{
"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:
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)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)
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:
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.
#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) |