phbeks.com API config mcp configuration
// tools / configuring mcp

Configuring MCP — Claude Code & the API

Model Context Protocol lets Claude reach your tools, data, and APIs. This is the end-to-end config reference: wiring servers into Claude Code (claude mcp add, .mcp.json, scopes, OAuth) and onto the Anthropic API (the Messages-API MCP connector and Managed Agents). Generators emit the exact command and JSON.

One protocol, a client and a server

An MCP server exposes tools (callable functions), resources (readable data), and prompts (slash commands) over a transport. An MCP client — Claude Code, or the Anthropic API's connector — connects and surfaces those capabilities to the model.

Claude (client) transport MCP server tools · resources · prompts

Transports

TransportWhere the server runsUse it for
HTTP (Streamable HTTP) Remote URLCloud services — the recommended default; supports OAuth
stdioLocal process on your machineLocal tools, custom scripts, direct system access
SSERemote URLLegacy remote — deprecated, prefer HTTP
WebSocketRemote URL (push)Servers that push events unprompted; .mcp.json only
Trust before you connect A server that fetches external content can expose you to prompt-injection. Only add servers you trust; project-scoped servers require explicit approval before first use.

Adding servers with claude mcp add

One command per transport. The server's name is how you reference it everywhere else.

# claude mcp add --transport http <name> <url>
claude mcp add --transport http notion https://mcp.notion.com/mcp

# with a bearer token header
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
  --header "Authorization: Bearer YOUR_PAT"
# claude mcp add [opts] <name> -- <command> [args...]   (everything after -- runs the server)
claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
  -- npx -y airtable-mcp-server

# the -- is REQUIRED: it separates Claude's flags from the server's own args
# deprecated — use HTTP where available
claude mcp add --transport sse asana https://mcp.asana.com/sse \
  --header "X-API-Key: your-key-here"
The -- rule for stdio Everything after -- is the server command, passed untouched. Without it, Claude tries to parse the server's flags (like --port) as its own. Also: put at least one option between --env and the server name, or the CLI reads the name as another KEY=value pair.

Managing servers

claude mcp list                 # all configured servers + status
claude mcp get github           # details for one server
claude mcp remove github        # remove it
claude mcp add-json db '{"type":"stdio","command":"/path","args":[],"env":{}}'
claude mcp add-from-claude-desktop   # import from Claude Desktop (macOS/WSL)
# inside a session:  /mcp   # status, OAuth login, clear auth

Where the config lives — and who shares it

The --scope flag decides which projects a server loads in and whether it's shared.

ScopeLoads inShared w/ teamStored in
local (default)Current project onlyNo — private to you~/.claude.json
projectCurrent project onlyYes — via version control.mcp.json in project root
userAll your projectsNo — private to you~/.claude.json

Precedence when the same name is defined twice (whole entry wins, fields are not merged): localprojectuser → plugins → claude.ai connectors.

The .mcp.json format (project scope)

{
  "mcpServers": {
    "shared-server": {
      "command": "/path/to/server",
      "args": [],
      "env": {}
    }
  }
}
{
  "mcpServers": {
    "api-server": {
      "type": "http",
      "url": "https://mcp.example.com/mcp",
      "headers": { "Authorization": "Bearer TOKEN" }
    }
  }
}
// ${VAR} and ${VAR:-default} expand in command, args, env, url, headers
{
  "mcpServers": {
    "api-server": {
      "type": "http",
      "url": "${API_BASE_URL:-https://api.example.com}/mcp",
      "headers": { "Authorization": "Bearer ${API_KEY}" }
    }
  }
}
Commit secrets safely Check in .mcp.json with ${API_KEY} placeholders, and keep the real values in each developer's environment. A missing required variable with no default fails the config parse (loud, not silent).

Claude Code server config generator

Fill this in and copy the matching claude mcp add command and the .mcp.json entry.

Three ways servers authenticate in Claude Code

OAuth knobs (when auto-setup isn't enough)

# fixed callback port (server pre-registers a redirect URI)
claude mcp add --transport http --callback-port 8080 my-server https://mcp.example.com/mcp

# pre-configured OAuth client (no dynamic registration); --client-secret prompts masked
claude mcp add --transport http \
  --client-id your-client-id --client-secret --callback-port 8080 \
  my-server https://mcp.example.com/mcp
Pin OAuth scopes Restrict a server to an approved subset by setting oauth.scopes (a single space-separated string) in .mcp.json — it overrides whatever the server advertises. For non-OAuth schemes (Kerberos, SSO, short-lived tokens), generate headers at connect time with headersHelper.
MCP auth tokens ≠ REST API keys Hosted MCP servers usually want an OAuth bearer token, not the service's native API key. A Notion ntn_ integration token works against Notion's REST API but not as the MCP server credential.

Connecting MCP servers from the Messages API

The MCP connector lets a raw API call reach a remote MCP server with no separate MCP client. Two pieces: mcp_servers (the connection) and an mcp_toolset in tools (which tools to enable).

Current beta header anthropic-beta: mcp-client-2025-11-20  (the older mcp-client-2025-04-04 is deprecated). Remote HTTP/SSE only — no local stdio. Not available on Bedrock/Vertex; not ZDR-eligible.

Server + toolset shape

FieldInNotes
type:"url"mcp_serversOnly "url" is supported
urlmcp_serversMust start with https://
namemcp_serversReferenced by exactly one toolset
authorization_tokenmcp_serversOptional OAuth bearer; you obtain & refresh it
mcp_server_namemcp_toolsetMust match a server name
default_config / configsmcp_toolsetenabled, defer_loading — allow/deny tools
MCP connector request builder
Local servers, prompts, or resources? The connector handles remote tools only. For local stdio servers, MCP prompts, or resources, run your own MCP client and use the SDK helpers (mcpTools, mcpMessages, mcpResourceToContent) to convert them for the Messages API.

MCP on a Managed Agent — server on the agent, auth in a vault

Managed Agents split MCP config across two objects so secrets stay out of the reusable agent definition:

# 1. Agent declares the server (no auth here)
agent = client.beta.agents.create(
    name="MCP Agent", model="claude-opus-4-8",
    mcp_servers=[{"type": "url", "name": "linear", "url": "https://mcp.linear.app/mcp"}],
    tools=[{"type": "agent_toolset_20260401"},
           {"type": "mcp_toolset", "mcp_server_name": "linear"}],
)

# 2. Vault holds the credential, attached to the session by id
session = client.beta.sessions.create(
    agent=agent.id, environment_id=env.id,
    vault_ids=["vlt_..."],   # contains the Linear MCP OAuth credential
)
Invalid credentials don't block session creation A bad vault credential still lets the session start; the MCP auth failure surfaces as a session.error event and retries on the next idle→running transition.

Things that bite

Connector is remote-only The Messages-API connector can't reach a local stdio server. Use a remote HTTP server, or run your own client + the SDK MCP helpers.
Project servers need approval Servers from a committed .mcp.json show as ⏸ Pending approval until you accept them interactively. Reset choices with claude mcp reset-project-choices.
Tool names are namespaced A server's tools are callable as mcp__<server>__<tool> (plugin servers: mcp__plugin_<plugin>_<server>__<tool>). Use that full form in permission rules and subagent tools lists.
Large outputs are managed Claude Code warns past 10K tokens of MCP output and caps at 25K by default; raise with MAX_MCP_OUTPUT_TOKENS. Tool search (on by default) defers tool schemas so adding many servers barely touches your context window.

Back to API & Claude Code config