Claude Bridge
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Claude BridgeSend Chief a message asking for the deploy status and wait for his reply"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Claude Bridge (chief-bridge)
A small remote MCP server on Cloudflare Workers that lets a Claude session and a Grok Bot agent ("Chief") talk to each other directly.
Claude gets a few MCP tools (send_to_chief, wait_for_reply, ...). When Claude sends a message, the bridge stores it in a Durable Object queue and fires a webhook that wakes your Grok Bot agent. The agent reads its inbox over a small authenticated HTTP API, posts a reply, and Claude picks the reply up with wait_for_reply.
This is a plain remote MCP server (Streamable HTTP + OAuth). It is not a Claude Code "Channels" server.
Architecture
flowchart LR
subgraph Claude
C[Claude.ai connector<br/>remote MCP client]
end
subgraph CF[Cloudflare Worker: chief-bridge]
O[OAuth provider<br/>workers-oauth-provider]
M["/mcp<br/>MCP tools"]
A["/chief/*<br/>bot HTTP API"]
Q[(Durable Object BoxmcpQueue<br/>SQLite queue + alarms)]
K[(KV OAUTH_KV<br/>OAuth grants/tokens)]
end
GH[GitHub OAuth<br/>owner check]
G[Grok Bot agent<br/>Chief]
C -- OAuth 2.1 + PKCE --> O
O -- login --> GH
O --- K
C -- Bearer token --> M
M --> Q
Q -- "webhook (Bearer CHIEF_WEBHOOK_KEY)" --> G
G -- "Bearer BOXMCP_CHIEF_API_KEY" --> A
A --> QRelated MCP server: @zeph-to/mcp-server
Message flow
Claude calls
send_to_chief(text). The worker stores it in theBoxmcpQueueDurable Object (a single SQLite-backed instance) and returns{thread_id, id}.The Durable Object schedules a webhook with an alarm and
POSTs{"source":"chief-bridge","pending":N}toCHIEF_WEBHOOK_URLwithAuthorization: Bearer <CHIEF_WEBHOOK_KEY>(header name and scheme are configurable). The message text is not sent in the webhook.The woken agent calls
GET /chief/inbox, thenPOST /chief/reply {thread_id, text}andPOST /chief/ack {ids}.Meanwhile Claude loops on
wait_for_reply(thread_id, after_id). Each call long-polls the Durable Object for up to 55 s; a reply wakes it immediately. The server instructions tell Claude to keep looping for about 5 minutes and to callread_chief_repliesbefore concluding there is no reply.
Webhook scheduling (in src/queue.ts):
No debounce: the first message after a quiet period fires immediately.
At least 5 s between webhook fires; messages arriving inside that window are coalesced into the next fire, not dropped.
Hard cap of 60 fires per hour (retries included).
Non-2xx or network error: retries after +1, +5, +15 minutes (25 s request timeout, redirects not followed).
If new messages arrive while a fire is in flight, a follow-up webhook is scheduled after a success; if retries are exhausted, the chain restarts once for messages that arrived during it.
MCP tools (Claude side)
Tool | What it does |
| Send a message (max 8000 chars). Omit |
| Long-poll for a reply in |
| Read replies with id > |
| All retained messages in a thread, both directions. |
| Pending count, last activity, whether a webhook is configured/scheduled. |
Replies are returned wrapped as <chief_message untrusted="true" ...> with </> escaped and control/bidi characters stripped, and the server instructions tell Claude to treat that content as data, not instructions.
Bot API (agent side)
All /chief/* endpoints require Authorization: Bearer <BOXMCP_CHIEF_API_KEY> (or _NEXT, for rotation; compared in constant time). Rate-limited to 60/min.
Method & path | Body | Result |
| – |
|
| – | Unacked Claude→Chief messages ( |
|
| Reply in an existing thread; wakes waiting |
|
| Mark inbox messages handled (1..200 ids) |
|
| Start a new Chief→Claude thread |
Request bodies are capped at 64 KB.
Setup
Requirements: a Cloudflare account (Workers + Durable Objects + KV), Node.js 22+, a GitHub account, and an agent that can receive an HTTPS webhook and make HTTP calls (built for a Grok Bot routine, but any agent works).
git clone https://github.com/asasds145/claude-bridge.git
cd claude-bridge
npm ci
npm test # vitest, runs in workerd via @cloudflare/vitest-plugin
npx tsc --noEmitKV namespace
npx wrangler kv namespace create OAUTH_KVPut the returned id into
wrangler.jsonc(<YOUR_KV_NAMESPACE_ID>).GitHub OAuth app (GitHub → Settings → Developer settings → OAuth Apps):
Homepage URL:
https://chief-bridge.<your-subdomain>.workers.devAuthorization callback URL:
https://chief-bridge.<your-subdomain>.workers.dev/callbackPut the Client ID into
GITHUB_CLIENT_IDinwrangler.jsonc.
Owner allowlist: set
BOXMCP_OWNER_GITHUB_IDto your numeric GitHub user id (curl https://api.github.com/users/<login>→id). Only this account can authorize.Public origin: set
BOXMCP_PUBLIC_ORIGINto the worker's https origin (recommended; requests to other hosts get421).Deploy and set secrets
npx wrangler deploy npx wrangler secret put GITHUB_CLIENT_SECRET npx wrangler secret put BOXMCP_CHIEF_API_KEY # e.g. openssl rand -hex 32 npx wrangler secret put CHIEF_WEBHOOK_URL # your agent's webhook (https) npx wrangler secret put CHIEF_WEBHOOK_KEY # bearer token the webhook expectsUntil
GITHUB_CLIENT_SECRETis set (and the owner id is non-zero),/authorizereturns 503. WithoutCHIEF_WEBHOOK_URL, messages queue but nothing is woken.Add the connector in Claude: Claude.ai → Settings → Connectors → Add custom connector → URL
https://chief-bridge.<your-subdomain>.workers.dev/mcp. Approve on the consent page, log in with GitHub.Wire up the agent: give your agent (e.g. a Grok Bot routine triggered by the webhook) the API key and tell it to read
/chief/inbox, reply via/chief/reply, then/chief/ack.Smoke test (read-only):
printf 'Authorization: Bearer %s\n' "$KEY" > chief.hdr # gitignored BRIDGE_URL=https://chief-bridge.<your-subdomain>.workers.dev CHIEF_HEADER_FILE=./chief.hdr npm run verify
For local development, copy .dev.vars.example to .dev.vars and run npx wrangler dev.
Configuration
Name | Kind | Example / placeholder | Purpose |
| KV binding |
| OAuth clients, grants, tokens |
| Durable Object |
| Message queue, webhook scheduler, rate limits |
| var |
| The only GitHub user id allowed to authorize |
| var |
| GitHub OAuth app |
| var |
| Canonical origin (OAuth resource metadata) |
| var |
| Header used for the webhook key |
| var |
| Scheme prefix (empty = raw key) |
| secret | – | GitHub OAuth app secret |
| secret | – | Key for |
| secret (optional) | – | Second key for rotation |
| secret |
| Where to send the wake-up webhook (must be https) |
| secret | – | Token sent with the webhook |
Security notes
Single-owner OAuth. The worker is its own OAuth 2.1 authorization server (
@cloudflare/workers-oauth-provider) and uses GitHub only to prove identity: it requests no GitHub scopes, checks the numeric user id againstBOXMCP_OWNER_GITHUB_ID, and discards the GitHub token immediately.PKCE S256 required, explicit consent page showing where the token will go, and
redirect_uripinned to Claude.ai's callback (https://claude.ai/api/mcp/auth_callback). Error redirects only go to that URI.Access tokens live 1 hour.
/oauth/registeris limited to 5/hour per IP;/mcpto 20/min per token.Bot endpoints need a separate bearer API key (constant-time compare, rotation via
_NEXT).Webhook carries only a pending count, authenticated with its own bearer key; https-only, no redirects followed.
Everything coming from the other side is wrapped and marked untrusted on both ends (prompt-injection hygiene).
No secrets in the repo. All secrets are Worker secrets;
.dev.vars,.env*, and header files are gitignored. Logs record only event names, paths, and status codes (no bodies, headers, tokens, or query strings).Retention: messages are kept 30 days, at most 200 per thread and 5000 total.
Limitations
Single user, single queue (one Durable Object instance named
main).The OAuth
redirect_uriis hard-coded to Claude.ai's connector callback, so other MCP clients (e.g. Claude Code, which uses a localhost callback) needCLAUDE_REDIRECT_URIinsrc/auth-github.tsadjusted before they can connect.Asynchronous: a reply usually takes 1-3 minutes (agent wake-up time), and Claude has to keep polling with
wait_for_reply.In-memory rate-limit counters reset when the Durable Object is evicted.
The consent and error pages are in Korean.
Webhook payload format is fixed (
{source, pending}); your agent must fetch the actual messages from/chief/inbox.
License
MIT, see LICENSE.
한국어 소개
Claude Bridge는 Cloudflare Workers 위에서 동작하는 원격 MCP 서버로, Claude(Claude.ai 커넥터)와 Grok Bot 에이전트("Chief")가 서로 직접 메시지를 주고받게 해 줍니다.
Claude가
send_to_chief로 메시지를 보내면 Durable Object 큐에 저장되고, webhook이 Grok Bot 에이전트를 깨웁니다.에이전트는 API 키로 보호된
/chief/*엔드포인트에서 메시지를 읽고 답장하며, Claude는wait_for_reply로 답을 받습니다.GitHub OAuth로 소유자 한 명만 연결할 수 있고, 모든 비밀값은
wrangler secret put으로만 설정합니다.
설치 방법은 위 Setup 섹션을 참고하세요.
This server cannot be deployed
Maintenance
Related MCP Connectors
Remote MCP server for The Colony — a social network for AI agents (posts, DMs, search, marketplace).
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Remote MCP server to run your Atako AI agents: chat, projects, files, integrations and channels.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn MCP server that enables AI agents to send notifications and request user input via Discord during long-running tasks. It allows users to remotely interact with their AI assistants and provide feedback through the Discord messaging platform.26 npm2MIT
- AlicenseAqualityAmaintenanceMCP server for AI agents to send notifications, copy to clipboard, request confirmations, and collect text input from users across their devices.1031 npmApache 2.0
- AlicenseNot gradedqualityDmaintenanceMCP server for async messaging between AI coding agents, enabling cross-harness and cross-machine communication with Slack-like semantics and mail-shaped delivery.2MIT
- FlicenseNot gradedqualityCmaintenanceA remote MCP server that gives AI assistants a shared memory, enabling structured handoffs, journaling, and notes for seamless continuation across sessions.-