Use from Claude Code
The Worker serves an MCP gateway at https://<worker-host>/mcp (streamable HTTP). Claude Code connects with a per-agent bearer token. It can queue coding runs, read run and approval state, and use the mailbox and memory tools its token’s scopes allow. It cannot approve anything. A queued run waits until a human approves it in the dashboard or in Slack.
1. Mint a token
Section titled “1. Mint a token”From the repo root:
node scripts/mint-token.mjs --agent claude-code --scopes sandbox:exec,runs:read --ttl-days 30 --host <worker-host>| Flag | Meaning |
|---|---|
--agent <name> |
Principal recorded on every audit row. No whitespace, max 128 chars. |
--scopes <a,b> |
Comma list from: email:read, email:draft, email:send, email:delete, memory:read, memory:write, runs:read, sandbox:exec, admin:tokens. |
--ttl-days N |
Optional. The KV entry expires after N days, and the token stops working then. |
--host <host> |
Your Worker host, used in the printed claude mcp add line. |
--write |
Also runs the printed wrangler kv key put … --remote for you. Without it, nothing is written. |
The script prints the raw shb_… token once, the KV key (tok_<sha256(token)>), the record value, the wrangler command and the claude mcp add line. Only the hash is stored, so a lost token cannot be recovered. Mint a new one instead.
--binding AGENT_TOKENS --config apps/backend/wrangler.jsonc writes to the namespace id in wrangler.jsonc. If you deploy with Alchemy, first check that this id matches the shiba-agent-tokens namespace (npx wrangler kv namespace list). If it doesn’t, run the command with --namespace-id <id> in place of --binding AGENT_TOKENS.
2. Add the server to Claude Code
Section titled “2. Add the server to Claude Code”claude mcp add --transport http shiba https://<worker-host>/mcp --header "Authorization: Bearer shb_…"Run claude mcp list to confirm that shiba connects. A 401 means the token is missing, malformed, revoked, expired, or was written to a different namespace.
3. Tools and scopes
Section titled “3. Tools and scopes”| Tool | Scope | What it does |
|---|---|---|
queue_run |
sandbox:exec |
Queues {repoUrl, task, baseBranch?, publishPullRequest?} as a pending approval on the shared default orchestrator, the same route as POST /api/runs. Returns approvalId and runId (agent-tool:<approvalId>). It never starts a run. |
run_status |
runs:read |
Returns one run record by runId. |
list_runs |
runs:read |
Lists run records, newest first (limit, default 20). |
list_approvals |
runs:read |
Lists pending and recently decided run approvals. Email approvals are left out. |
list_mailboxes, list_emails, get_email, get_thread, search_emails, mark_email_read, extract_otp, latest_verification |
email:read |
Mailbox reads. |
create_draft, update_draft, draft_reply, move_email |
email:draft |
Draft and organize. |
send_email, send_reply |
email:send |
Queue an email send for human approval. |
delete_email |
email:delete |
Queue a delete for human approval. |
memory_recall, memory_sessions |
memory:read |
Read shared memory. |
memory_bank, memory_forget |
memory:write |
Write shared memory. |
Pair a cloud agent with its mailbox
Section titled “Pair a cloud agent with its mailbox”The --agent token principal is also the mailbox assignment key. In the dashboard Inbox settings, register an address with Cloud agent token principal set to that exact name (for example, scout). You can re-enter an existing address to change its assignment, or leave the field blank to unassign it. An unassigned mailbox is dashboard-only; MCP email tools do not see it. This is Shiba’s mailbox-scoped analogue to Goshen Email’s mailbox keys, without adding a second email service or moving mail out of your Cloudflare account.
node scripts/mint-token.mjs --agent scout --scopes email:read,email:draft,email:send \ --host <worker-host> --namespace-id <agentTokensNamespace> --writeGive the resulting token only to that cloud agent and connect it to /mcp as above. list_mailboxes returns only addresses assigned to scout; direct mailbox calls and ID-based email/draft/thread tools also refuse other agents’ or unassigned mailboxes. The token cannot approve its own send or delete request. Agents can poll list_emails/search_emails for new mail; inbound mail does not automatically start a sandbox or execute instructions from a message. Existing mailboxes without an agent assignment must be paired before their MCP email tools can see them; dashboard access is unchanged.
For a first read-only test, grant only email:read. Configure Cloudflare Email Routing separately, send a message from another address, and verify it appears both in the Inbox and in the agent’s list_emails result. Add draft/send scopes later if needed; they still cannot bypass human approval.
The built-in chat agent also calls these tools: its run_code tool executes model-written JavaScript in an isolated Worker that dispatches back through this same gateway as the reserved principal orchestrator-agent (every scope except admin:tokens). To let the chat agent work a mailbox, register the address with Cloud agent token principal set to orchestrator-agent — no token minting needed. The same scoping rules apply: orchestrator-agent sees only mailboxes assigned to it, and sends or deletes still queue for human approval.
Agent mailbox identity (OTP + magic links)
Section titled “Agent mailbox identity (OTP + magic links)”Two read-only tools serve the sign-in flow: extract_otp pulls a one-time code and magic links out of one email by id, and latest_verification scans the newest inbound mail for either — its mailbox arg defaults to the deployment’s agent identity address (AGENT_MAILBOX, or dev@tryshiba.dev when unset). Register that address in the Inbox and assign it to the agent principal (orchestrator-agent for the built-in chat agent, or the token principal of an external agent) and the agent can log into third-party apps end-to-end: it reads the code or link with sender and timestamp attached, while the raw body stays out of the response. Sends still queue for approval.
The gateway has no approve tool. This MCP tool accepts only repository/task/branch/publish inputs, not a per-run harness or model; queued runs use the deployment’s configured defaults (AGENT_HARNESS, CODING_MODEL, and the selected harness’s model default) when approved. Harness implementation and verification status are documented in Coding Harnesses. No cloud end-to-end run is recorded; the dated local OpenCode exercise did not reach successful model inference.
Run visibility is per-principal: run_status, list_runs, and list_approvals only return records the calling token’s principal queued (queuedBy is stamped at intake). Operator surfaces — dashboard, Slack, /api/runs with an Access identity — still see everything. Pair sandbox:exec with runs:read on tokens that queue and poll runs.
4. How /mcp is authenticated
Section titled “4. How /mcp is authenticated”/mcp and /mcp/* are bypassed in Cloudflare Access, because an MCP client cannot complete an Access login. The Worker authenticates these requests itself with the bearer token:
- The Worker checks the token’s shape, then looks up its SHA-256 hash in
AGENT_TOKENS. A missing, unknown, revoked, or expired token gets a plain401before any MCP traffic is served, and so does a KV outage. - The verified record reaches the gateway in a Worker-set header. Client copies of that header are stripped.
- Every tool call is checked against the token’s scopes and writes a row to the audit log (
GET /api/audit). The row holds the principal, the tool, a hash of the arguments and the outcome, never the arguments themselves.
See Security for the Access bypass policy and Approval Gates for how a human resolves a queued run.
Revoke a token
Section titled “Revoke a token”Delete its KV entry:
npx wrangler kv key delete --binding AGENT_TOKENS tok_<sha256> --config apps/backend/wrangler.jsonc --remoteThe next request with that token gets a 401.
