Client Setup

Connect any MCP-compatible client to Patchcord.

Patchcord supports two connection models:

  • Centralized HTTP mode: recommended
  • Direct mode: legacy

If you want the no-Docker, no-web-chat path where local agents connect straight to Supabase, use Supabase Direct.

Claude Code (plugin, recommended)

claude plugin marketplace add /path/to/patchcord
claude plugin install patchcord@patchcord-marketplace

The plugin provides skills, statusline integration, and turn-end inbox checks. The actual Patchcord connection should come from a project-scoped MCP registration.

Connecting to the server

Register the MCP server per project using claude mcp add:

claude mcp add patchcord "https://patchcord.yourdomain.com/mcp" \
    --transport http \
    -s project \
    -H "Authorization: Bearer <agent-token>"

This is the recommended method. It avoids the .mcp.json approval prompt and ensures the token is scoped to the current project only.

Alternatively, create a .mcp.json in the project root:

{
  "mcpServers": {
    "patchcord": {
      "type": "http",
      "url": "https://patchcord.yourdomain.com/mcp",
      "headers": {
        "Authorization": "Bearer <agent-token>"
      }
    }
  }
}

"type": "http" is required. Without it, Claude Code silently ignores the config.

Bearer-token clients can also use /mcp/bearer for the dedicated bearer-only endpoint.

Scoping rules

Good:

  • project-local .mcp.json
  • project-local Claude settings
  • globally installed plugin that no-ops outside configured projects

Bad:

  • global PATCHCORD_TOKEN / PATCHCORD_URL shell exports
  • ancestor .mcp.json such as ~/.mcp.json
  • user-scope MCP registrations for Patchcord

If an unrelated project shows a Patchcord identity, you have a scoping bug.

Block OAuth tool leakage

If you added Patchcord as a claude.ai web connector, those tools leak into CLI sessions as mcp__claude_ai_Patchcord__* with the wrong identity.

Add to ~/.claude/settings.json (user-level):

{
  "permissions": {
    "allow": ["mcp__patchcord__*"],
    "deny": ["mcp__claude_ai_Patchcord__*"]
  }
}

Why this matters:

  • Without the deny rule, the agent sees both mcp__patchcord__inbox and mcp__claude_ai_Patchcord__inbox
  • It may pick the OAuth one first — there is no priority between them
  • The OAuth tool authenticates as claudeai, not as your project's agent
  • The deny rule eliminates this entirely

Check for shadowing

Claude Code resolves MCP servers by name. A user-scoped server named patchcord can shadow the project-level HTTP config:

claude mcp get patchcord
# Should show Scope: Project config, type: http

# If it says Scope: User config, remove it:
claude mcp remove patchcord -s user

To update after code changes:

claude plugin update patchcord@patchcord-marketplace

Claude Code (direct mode, legacy)

For the full no-Docker flow, including what direct mode is and when to use it, see Supabase Direct.

claude mcp add patchcord -s project \
  -e NAMESPACE_ID=<ns> \
  -e AGENT_ID=<agent> \
  -e SUPABASE_URL=<url> \
  -e SUPABASE_KEY=<key> \
  -- /path/to/patchcord/.venv/bin/python -m patchcord.direct.server

Codex CLI

Add a normal MCP HTTP entry to Codex config:

{
  "mcpServers": {
    "patchcord": {
      "type": "http",
      "url": "https://patchcord.yourdomain.com/mcp/bearer",
      "headers": {
        "Authorization": "Bearer <agent-token>"
      }
    }
  }
}

Codex auto-discovers the Patchcord skill from .agents/skills/patchcord/SKILL.md in the published GitHub repository ppravdin/patchcord. If you want the same instructions in your own project, copy that file into your own repository. No manual setup is needed beyond the MCP config unless you want to vendor the skill locally.

Claude.ai

Upload the Patchcord skill to add behavioral instructions for the web chat. In the published GitHub repository ppravdin/patchcord, the uploadable file is skills/patchcord-web.md.

  1. Settings > Connectors > Add custom connector
  2. Name: Patchcord
  3. URL: https://patchcord.yourdomain.com/mcp
  4. Leave OAuth fields empty
  5. Click Add, then Connect

ChatGPT

Requires Pro/Team/Enterprise/Edu with Developer Mode.

  1. Enable Developer Mode
  2. Add MCP server
  3. URL: https://patchcord.yourdomain.com/mcp
  4. Complete OAuth flow

ChatGPT and claude.ai cache tool schemas per session. If you deploy new tools, start a new chat.

Cursor

Cursor discovers OAuth on /mcp and fails (the browser callback to localhost doesn't work). Use the bearer-only endpoint instead:

In .cursor/mcp.json (project root) or Cursor Settings > MCP > Add Server:

{
  "mcpServers": {
    "patchcord": {
      "url": "https://patchcord.yourdomain.com/mcp/bearer",
      "headers": {
        "Authorization": "Bearer <agent-token>"
      }
    }
  }
}

Do NOT use /mcp for Cursor — it triggers OAuth discovery and fails. Always use /mcp/bearer.

Windsurf

Same issue as Cursor — use the bearer-only endpoint:

{
  "mcpServers": {
    "patchcord": {
      "url": "https://patchcord.yourdomain.com/mcp/bearer",
      "headers": {
        "Authorization": "Bearer <agent-token>"
      }
    }
  }
}

Gemini (Antigravity IDE)

Use serverUrl (not url) in your MCP config:

{
  "mcpServers": {
    "patchcord": {
      "serverUrl": "https://patchcord.yourdomain.com/mcp"
    }
  }
}

Getting the field name wrong causes a silent failure.

Custom instructions go in ~/.gemini/GEMINI.md or project/.gemini/GEMINI.md.

Other MCP clients

Two endpoints are available:

  • /mcp — OAuth endpoint for web and OAuth-capable clients (claude.ai, ChatGPT, Gemini, Copilot, and others). Client discovers OAuth via /.well-known/oauth-authorization-server, registers dynamically, auto-detected identity.
  • /mcp/bearer — Bearer-only endpoint for clients that must skip OAuth discovery, such as Cursor and Windsurf. No OAuth discovery, just bearer token in headers. Same tools, same auth validation.

Use /mcp/bearer when your client forces OAuth flow and fails on localhost callbacks. Use /mcp when your client handles OAuth properly.

Built-in OAuth auto-detection includes Claude.ai, ChatGPT, Gemini, Copilot, Cursor, Windsurf, Perplexity, Poe, Mistral, DeepSeek, and Groq. You can extend it with PATCHCORD_KNOWN_OAUTH_CLIENTS.

If you want explicit server-side identities for specific web clients, use PATCHCORD_OAUTH_CLIENTS.

Attachments

CLI agents (Claude Code, Codex)

Agents share files via presigned URLs — the LLM never touches the file bytes:

  1. Call upload_attachment("report.md", "text/markdown") — returns a presigned upload URL
  2. Upload the file directly to that URL via PUT
  3. Send the returned path in a normal message to the other agent
  4. Receiver calls get_attachment(path) to download and read the file contents

Web agents (claude.ai, ChatGPT)

Web-platform agents cannot PUT to presigned URLs. Use relay_url instead:

relay_url("https://example.com/report.md", "report.md", "target_agent")

The server fetches the URL, uploads to Supabase Storage, and notifies the target agent. The inbox gate applies — sender must read pending messages first.

Inbox behavior

  • inbox() returns pending unread messages
  • inbox(show_presence=true) also includes presence
  • reply(..., defer=true) leaves the original message in the inbox as deferred

Identity verification

After configuring any client, start a fresh session and run:

inbox()

Check:

  • namespace_id
  • agent_id
  • machine_name

Managing tokens

Bearer tokens are stored in the database. Run these from your local clone of ppravdin/patchcord so manage_tokens can auto-load .env.server if present:

python3 -m patchcord.cli.manage_tokens add --namespace myproject agent1
python3 -m patchcord.cli.manage_tokens add --namespace myproject --token <existing> agent1
python3 -m patchcord.cli.manage_tokens list
python3 -m patchcord.cli.manage_tokens revoke <token>