---
title: "Use from Claude Code"
description: "Connect Claude Code (or any MCP client) to the Worker's /mcp gateway with a scoped bearer token and queue approval-gated coding runs."
---

> Documentation Index
> Fetch the complete documentation index at: https://tryshiba.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 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

From the repo root:

```bash
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>` | Grant only needed scopes. MCP scopes include `gmail:read`, `email:read`, `email:draft`, `email:send`, `email:delete`, `memory:read`, `memory:write`, `runs:read`, `sandbox:exec`, `mcp:external`, `integrations:read`, `integrations:execute` and `admin:tokens`. `--help` lists all accepted scopes, including the separate API-key scopes. |
| `--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

```bash
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.

## External coworkers

External coworkers (a 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:

```bash
node scripts/mint-token.mjs --agent scout --scopes sandbox:exec,runs:read --ttl-days 30 \
  --host <worker-host> --namespace-id <shiba-agent-tokens-id> --write
```

Register 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 (`scout` 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

| 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. |
| `list_skills`, `get_skill_instructions` | `integrations:read` | Discover readable, enabled extension skills and load one skill's instructions by ID and version. Instructions do not grant tools or approval. |
| `integrations.search_actions` | `integrations:read` | Discover actions for an `employeeId` with current integration grants and an exact `toolkitSlug`. A scope alone does not grant an app connection. |
| `integrations.execute` | `integrations:execute` | Request an employee-authorized action with exact arguments; execution requires the separate human approval and current connection/resource grants. |

### Select a skill as an MCP prompt

Clients that support MCP prompts can use `prompts/list` and `prompts/get` to select enabled extension skills without writing files into the client's skill folders. The bearer needs `integrations:read`. The list contains only skills readable by that verified principal in its organization, with the skill name as the display title and no instruction body. Private skills belonging to another principal, disabled skills and archived skills are excluded. Team-workspace skills remain unavailable through this bearer surface because it does not establish native workspace membership.

Each prompt name includes the skill ID and version, such as `shiba_skill_<id>_v1`. Refresh the client's prompt list after editing a skill: selecting an old version fails instead of silently loading changed instructions. Retrieval checks the principal, scope, current visibility, enabled state and version again. Names remain distinct even when two skills share a display title. The picker offers up to 100 skills; `list_skills` and `get_skill_instructions` remain available for directory search and on-demand reads.

Selecting a prompt returns untrusted guidance, not permission to act. It cannot grant tools, approve a run or bypass any approval gate. No external tool or sandbox runs when a prompt is read. If the skill directory is unavailable, prompts are withheld while the other MCP tools remain available.

### Add an owner-reviewed external MCP server

In **MCP → External MCP servers**, create a draft with an HTTPS Streamable HTTP endpoint. Choose a Worker credential reference (the name of an already provisioned `MCP_CREDENTIAL_*` secret) or **Custom OAuth public client**. Custom public hosts must be exact hostnames in the deployment's comma-separated `MCP_TRUSTED_HOSTS`. The eight curated hosts for Stripe, Notion, Sentry, PostHog, Figma, Atlassian, GitHub and Linear are also trusted by the registry; an empty custom allowlist does not disable those presets. Trusting a host permits the explicit connection flow; it does not connect an account, enable a tool or grant access.

**Integrations → MCP servers** provides those eight presets with account labels and only the authentication methods supported for each preset. Six retain the OAuth path; GitHub and Linear use restricted bearer tokens and vendor-documented read-only endpoints. OAuth requires the deployment's credential encryption key (`MODEL_CREDENTIAL_KEY`), a vendor-registered client ID in `MCP_OAUTH_CLIENT_<CATALOG_ID>` (uppercase, with hyphens changed to underscores), and the exact Shiba callback URL registered with the vendor: `https://<worker-host>/api/v1/mcp/oauth/callback`. For example, Atlassian uses `MCP_OAUTH_CLIENT_JIRA_ATLASSIAN`. The preset is not proof that the vendor accepts the deployment's client, requested scopes or account tier. Unsupported or missing vendor metadata, client configuration or consent leaves the connection unavailable. There is no automatic vendor-client registration. A token submitted through the dedicated bearer form is stored encrypted by the Worker; credentials are not model context or capability-catalog content. Never paste credentials into chat.

The **GitHub (read-only)** preset pins `https://api.githubcopilot.com/mcp/readonly`. Supply a fine-grained personal access token restricted to selected repositories and read permissions. The **Linear (read-only)** preset pins `https://mcp.linear.app/mcp/readonly`; use a key with only Read permission and limited team access. Both use the existing encrypted bearer form and HTTPS Streamable HTTP transport. GitHub client-secret OAuth and Linear dynamic client registration are not implemented by these presets. See [GitHub's endpoint documentation](https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md), [GitHub's authentication requirements](https://github.com/github/github-mcp-server/blob/main/docs/host-integration.md) and [Linear's official setup guide](https://linear.app/docs/mcp).

These two entries were checked against vendor documentation on November 7, 2026, not through live authenticated calls. Tools still start disabled and unreviewed; the recommendation defaults to approval-required until the owner reviews the exact schema and effect. A read-only endpoint is not a grant of access to every repository or team. No deployment token is reused automatically.

For a **custom OAuth** draft, enter the provider's exact issuer URL, a pre-registered **public** client ID, and optional space-separated scopes, then choose **Start custom OAuth**. The operator must explicitly list **both** the MCP host and issuer host in `MCP_TRUSTED_HOSTS`; curated host defaults do not substitute for this custom-flow trust. Register the callback shown on the card with the provider and configure `MODEL_CREDENTIAL_KEY`. Follow the sign-in link in a new tab, then return and refresh connection status. Disable the server to cancel pending sign-in or revoke an existing connection. A fresh connection is required to replace an authorized account.

This custom lane discovers RFC 9728 resource metadata and RFC 8414/OIDC authorization metadata, pins the exact resource URL and chosen issuer, requires S256 PKCE and advertised public-client authentication (`none`), and keeps authorization, token and revocation endpoints on the issuer's origin. Resource metadata must remain on the MCP origin. All requests reject redirects, URL credentials, IP literals and private/local hostname forms, and authorization metadata candidates are validated before fetching. The operator remains responsible for allowlisted domains and their public DNS: this is an explicit hostname trust boundary, not general DNS/IP pinning for arbitrary domains. Credential egress rechecks current host trust, so removing a host blocks exchange and refresh; local revocation still deletes stored credentials if the provider cannot be contacted. OAuth consent does not enable tools or waive approval.

Dynamic client registration, client secrets/confidential clients, cross-origin OAuth endpoints, and providers that lack the required metadata are unsupported in the custom lane. Compatibility is verified with local fixtures, not live provider accounts. Tokens and PKCE verifiers are encrypted at rest and remain in the Worker; no credential is sent to an agent container. Revocation attempts the advertised provider endpoint and always deletes local credentials; remote revocation cannot be guaranteed when that endpoint is absent, blocked or unavailable.

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. Employee use additionally requires the selected employee's capability and exact resource grants in **Employee tools**; an account connection or workspace-visibility label does not grant those permissions.

Shiba supports HTTPS Streamable HTTP, with redirects rejected, and no-auth, bearer-reference or curated/custom public-client OAuth authentication. SSE-only and stdio servers, private/local/metadata destinations, custom auth headers and private-network transport are unsupported. Network requests occur during an authenticated owner's explicit sign-in, bearer revocation, discovery or approved invocation flow, including OAuth metadata discovery and token refresh when needed. A saved draft alone does not execute tools. These supported code paths still require live verification against each configured vendor and deployment.

### 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

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.

```bash
node scripts/mint-token.mjs --agent scout --scopes email:read,email:draft,email:send \
  --host <worker-host> --namespace-id <agentTokensNamespace> --write
```

Give 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)

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](/docs/claude-code/). 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). Dashboard run reads resolve the verified user's own session; shared operator runs additionally require the configured approver authority. Slack and shared-room views enforce their own source and audience checks. A dashboard login does not grant access to every user's runs. Pair `sandbox:exec` with `runs:read` on tokens that queue and poll runs.


## 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 plain `401` before 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.

For clients using OAuth instead of a minted static token, Shiba also implements authorization-server and protected-resource metadata, public-client registration, owner consent, authorization code with PKCE, rotating refresh tokens and revocation. These authenticate the incoming MCP client; they are separate from the curated vendors' outgoing OAuth connections above. OAuth clients still receive scoped principals and cannot approve their own actions. Client and deployment compatibility require their own live check.

See [Security](/docs/security/) for the Access bypass policy and [Approval Gates](/docs/approval-gates/) for how a human resolves a queued run.

## Revoke a token

Delete its KV entry:

```bash
npx wrangler kv key delete --binding AGENT_TOKENS tok_<sha256> --config apps/backend/wrangler.jsonc --remote
```

The next request with that token gets a `401`.

Source: https://tryshiba.dev/docs/mcp/index.mdx
