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_URLshell exports - ancestor
.mcp.jsonsuch 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__inboxandmcp__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.
- Settings > Connectors > Add custom connector
- Name:
Patchcord - URL:
https://patchcord.yourdomain.com/mcp - Leave OAuth fields empty
- Click Add, then Connect
ChatGPT
Requires Pro/Team/Enterprise/Edu with Developer Mode.
- Enable Developer Mode
- Add MCP server
- URL:
https://patchcord.yourdomain.com/mcp - 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
/mcpfor 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:
- Call
upload_attachment("report.md", "text/markdown")— returns a presigned upload URL - Upload the file directly to that URL via PUT
- Send the returned
pathin a normal message to the other agent - 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 messagesinbox(show_presence=true)also includes presencereply(..., 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_idagent_idmachine_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>