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, mcp:external, 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.
Grok Bot / Viktor coworker {#grok-bot-viktor-coworker}
Section titled “Grok Bot / Viktor coworker {#grok-bot-viktor-coworker}”External coworkers (Grok Bot on X, a Viktor-style background agent, or any Streamable HTTP MCP client) use the same /mcp gateway and shb_… tokens as Claude Code. The usual pairing for run queueing:
node scripts/mint-token.mjs --agent grok-bot --scopes sandbox:exec,runs:read --ttl-days 30 \ --host <worker-host> --namespace-id <shiba-agent-tokens-id> --writeRegister the connector with URL https://<worker-host>/mcp and header Authorization: Bearer shb_… (store the token in the client vault, not in chat). Smoke-test with list_runs (expect [], not 401). Queue work with queue_run — the response is { approvalId, runId: "agent-tool:<approvalId>", status: "pending_approval" } until a human approves in the dashboard or Slack. Poll with run_status and list_approvals. There is still no approve tool on /mcp.
Pair sandbox:exec with runs:read on tokens that both queue and poll. Run visibility is per-principal (grok-bot only sees runs it queued). Revoke by deleting the KV entry (tok_<sha256>) as in section 4 below.
Before minting, confirm npx wrangler whoami shows the Cloudflare account that owns your Worker host and that --namespace-id targets the live shiba-agent-tokens 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?, testCommand?} 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 memory banked by this verified token principal. |
memory_bank, memory_forget |
memory:write |
Write or forget facts in this verified token principal’s memory partition. |
Add an owner-reviewed external MCP server
Section titled “Add an owner-reviewed external MCP server”In Agents & MCP → External MCP servers, create a draft with an HTTPS Streamable HTTP endpoint and, when needed, the name of an already provisioned MCP_CREDENTIAL_* Worker secret. Shiba stores only that reference. No secret value is entered in the dashboard, sent to a model, or copied into the capability catalog. The deployment operator must explicitly set MCP_TRUSTED_HOSTS to comma-separated exact public hostnames before Shiba will contact them; an empty list is disabled by default.
Use Discover / retry to fetch a bounded tool schema snapshot. Read each remote description as untrusted text. For each namespaced capability, explicitly review its effect as either read-only or “may mutate” (which requires approval for every exact call), then enable it. Grant each enabled capability only to an active MCP principal that has the mcp:external scope. A changed schema disables the affected capability and clears its principal grants until it is reviewed and enabled again. A server health error disables its capabilities; retry discovery before reconnecting.
Discovery accepts a strict JSON Schema subset: objects, strings, numbers, integers, booleans, arrays, string enums, and supported length/item/numeric bounds. Unsupported assertion keywords such as pattern, format, uniqueItems, or $ref fail discovery rather than being ignored.
The inbound /mcp gateway lists only currently enabled capabilities granted to its verified bearer principal. Policy is reloaded at invocation, and the normal durable tool receipt records the result. Calls classified as potentially mutating first create an exact-argument human approval, visible on the external-server card. The owner’s Approve and dispatch action executes only that frozen payload and settles its invocation receipt; a model retry never dispatches a write. The tool response is marked untrusted. Shiba supports HTTPS Streamable HTTP with no redirects and optional bearer authentication from a preprovisioned secret reference. OAuth setup, SSE-only and stdio servers, private/local/metadata destinations, custom auth headers and self-hosted private transport are unsupported. No server is contacted unless an authenticated owner explicitly starts discovery or an enabled tool is invoked (or the owner approves a frozen write).
Memory ownership and legacy compatibility
Section titled “Memory ownership and legacy compatibility”MCP memory facts are partitioned by the verified token principal. memory_recall searches only that principal’s facts, and memory_sessions filters to the same exact principal; a caller cannot select another agent. Dashboard compatibility routes similarly expose legacy facts and sessions only when the legacy agent name exactly matches the authenticated user identity. Loopback-only development uses the default agent partition. Owner-scoped workspace memory sources use a separate hashed identity partition.
Older facts and sessions in the shared registry have no owner field beyond their legacy agent name. Shiba does not merge those rows across identities, infer ownership from content, or silently move them into a user’s workspace. Rows with an exact identity match remain readable through the compatibility routes; unmatched legacy rows stay stored but inaccessible through user-facing memory reads. There is no automatic migration or deletion. A future migration would require an operator-reviewed mapping from a legacy agent partition to exactly one owner before moving its data.
Dashboard users can save Projects in the private workspace memory view. A project stores its name, purpose, selected employee defaults, and up to eight references to existing sources in the same owner partition; reference URLs are metadata only and are never fetched. Project edits increment a version. At approval time Shiba freezes the selected project version and a bounded snapshot of each active linked source, with source IDs, titles, kinds, update timestamps, and reference URLs. Source text remains explicitly untrusted reference data. Editing or deleting a project after approval does not change that approval or its run. Disabling, deleting, or expiring a linked source blocks new approvals until the owner edits the project to remove or restore that source. Existing approved snapshots remain available to their already approved run. Data stays in the existing owner-partitioned SQLite-backed Memory Durable Object; there is no provider dependency or background source fetch.
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 repository/task/branch/publish/test-command 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.
Grok Bot bridge (founder skills)
Section titled “Grok Bot bridge (founder skills)”SaaS connectors that live in Grok Bot use the grokbot-bridge execution target and MCP tools queue_grokbot_bridge_task, grokbot_bridge_status, and complete_grokbot_bridge_task. See Grok Bot bridge for pairing, founder skill library ids, and the live-vs-blocked checklist.
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.
