---
title: "MCP tools"
description: "All nine broker MCP tools with inputs, results, side effects, retry rules, errors, and the one-call identity_signup flow."
image: "https://docs.agentregistrar.dev/og/docs-default.png"
---

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

# MCP tools

The broker exposes nine tools over the Model Context Protocol (MCP) at
`https://agentregistrar.dev/mcp`. Four manage the agent identity, four manage its
inbox, and one is the one-call signup tool. This page is the lookup table:
inputs, result keys, side effects, retry rules, error codes, and one example per
tool.

The normative contracts are elsewhere. Inputs and the structured results are
defined in the broker's shared MCP tool schema; the behavior is in the broker's
tool modules. The [error reference](/reference/error-codes/) holds the code list,
and the [broker HTTP reference](/reference/broker-http/) holds the transport and
OAuth endpoints.

## Endpoint and discovery

- URL: `https://agentregistrar.dev/mcp` (Streamable HTTP, JSON-RPC 2.0).
- Auth: OAuth 2.1 bearer access token (`mca_...`), sent as `Authorization:
  Bearer`. The token is bound to one verified human owner.
- Transport: one stateless handler per request. There is no session id to keep,
  and `POST` is the only method the tool flow needs.
- `initialize` reports `serverInfo.name` `agentregistrar`, version `1.0.0`,
  capabilities `tools` and `resources`, and the system instructions that
  describe the workflow.
- `tools/list` returns exactly nine tools.
- `resources/list` returns four static `text/markdown` resources. They repeat
  documented material for clients that cannot follow links; the pages they point
  at stay canonical.

```bash
export MCP_TOKEN="<the mca_ access token from your client's OAuth flow>"
curl -sS -X POST https://agentregistrar.dev/mcp \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

The handler also accepts a POST with only `Accept: application/json` and defaults
a missing `Content-Type` to `application/json`, so plain `curl` calls work. A
request without a bearer token gets `401` with a JSON-RPC error code `-32001` and
a `WWW-Authenticate` challenge; see the [transport
errors](/reference/error-codes/#mcp-transport-and-gate-errors).

### MCP resources

| URI | Title | Material also published at |
| :--- | :--- | :--- |
| `agentregistrar://docs/quickstart` | Agent Registrar quickstart | [Agent quickstart](/agents/quickstart/) |
| `agentregistrar://docs/assertion-claims` | Agent assertion claims (Contract A) | [Assertion claims](/agent-identity/v1/assertion-claims/) |
| `agentregistrar://docs/error-recovery` | Tool error recovery | [Error codes](/reference/error-codes/) |
| `agentregistrar://docs/spec` | Agent Identity specification | [Specification](/agent-identity/v1/specification/) |

Resources are read-only and carry no per-request state. The tool result is the
reliable surface; a resource is supporting depth.

## Before you call

The transport gate runs before any tool:

1. The bearer token must resolve to an `mca_...` token row that is not revoked
   and not expired. Otherwise `401`, code `-32001`.
2. The token's human owner must be `active` and must have signed the Master Agent
   Delegation agreement. Otherwise `403`, code `-32003`.
3. The agent sub-identity must exist and be `active`. `identity_register` creates
   it; `identity_whoami`, `identity_signup`, `identity_prove`, and the inbox
   tools resolve it and auto-provision a default one when the session has none.

A revoked or operator-suspended agent fails at the tool layer with
`agent_revoked`, not at the transport. A suspended agent is not human-restorable.
Scope checks are per tool: `identity_signup`/`identity_prove` need `tos:accept`,
the inbox tools need `inbox:read` or `inbox:send`.

## How to read each entry

- **Inputs**: the exact JSON Schema properties from `tools/list`.
- **Result**: the keys the agent sees. `identity_signup`, `identity_prove`, and
  `identity_record_signup` register structured `outputSchema`s; the others
  return a text JSON payload.
- **Side effects**: what changes in the broker, including mail.
- **Retry**: whether repeating the same call is safe.
- **Errors**: stable codes, linked to [Error codes](/reference/error-codes/).

A tool failure is not an HTTP error. It returns a normal JSON-RPC result with
`isError: true` and the error envelope as text content:

```json
{
  "content": [
    {
      "type": "text",
      "text": "{\"error\":{\"code\":\"wait_timeout\",\"message\":\"...\",\"retryable\":true,\"side_effects\":{},\"next_step\":\"...\",\"docs\":\"agentregistrar://docs/error-recovery\"}}"
    }
  ],
  "isError": true
}
```

The `text` value is a JSON string: parse it before reading `code`. `message` is
human-readable and may change; `code`, `retryable`, `side_effects` and
`next_step` are stable.

## Tools at a glance

| Tool | Group | Purpose | `readOnlyHint` | `idempotentHint` |
| :--- | :--- | :--- | :-: | :-: |
| [`identity_register`](#identity_register) | Identity | Create or resume the agent sub-identity for this session | no | yes |
| [`identity_whoami`](#identity_whoami) | Identity | Show the agent, human owner, scopes, recent signups and acceptances | yes | yes |
| [`identity_signup`](#identity_signup) | Identity | One call: fetch discovery, apply policy, mint, return a prepared signup request | no | yes |
| [`identity_prove`](#identity_prove) | Identity | Advanced: accept terms and mint with claim inspection | no | yes |
| [`identity_record_signup`](#identity_record_signup) | Identity | Record an RP-signed receipt or a weaker self-report | no | yes |
| [`inbox_list`](#inbox_list) | Inbox | List recent messages, newest first | yes | yes |
| [`inbox_read`](#inbox_read) | Inbox | Read one message body, headers and detected OTP | yes | yes |
| [`inbox_wait_for_email`](#inbox_wait_for_email) | Inbox | Wait for a matching inbound message | yes | yes |
| [`inbox_send`](#inbox_send) | Inbox | Send mail from the agent address | no | no |

## identity_signup

Title: "One-call brokered service signup". This is the default path. It does the
identity half of signup in one call.

**Inputs**

| Field | Type | Required | Rule |
| :--- | :--- | :-: | :--- |
| `service` | string | yes | RP origin or the exact `/.well-known/agent-signup.json` URL. The broker fetches it. Do not pass a discovery object, discovery URL as a separate field, or an attestation. |
| `accepted_tos_text` | string | yes | The complete `terms.text` the human accepted, verbatim. Its hash must equal the fetched `terms.sha256`; no trim or summary. |
| `requested_scopes` | string[] | no | Defaults to discovery `required_scopes` in document order. Supplied: deduped, must include every required scope and hold every listed scope. `[]` is invalid. |
| `force_new` | boolean | no | Create a new consent event even if an acceptance exists. Default false; it does not bypass gates or policy. |

The schema is passthrough, but the executor rejects `rp_discovery`,
`rp_discovery_url`, and `rp_attestation` with `discovery_source_not_allowed`.
There is no manual discovery, JWT decode, or attestation handling.

**Result**

- `service`: origin, audience, provider name/URL, terms URL/hash/version,
  `endpoints.agent_signup`, required scopes, and the attestation summary
  (`status`, `issuer`, `jti`, `level`, `expires_at`, `checked_at`).
- `rp_verification`: the required verification summary (status, policy,
  `allowed`, source, issuer, jti, level, expiry, `checked_at`, reason).
- `rp_verification_warning`: present only when a `warn` policy proceeds. Surface
  it to the human; it is advisory, not a safety rating or a block.
- `assertion`: `jwt`, `jti`, `kid`, `typ`, expiry. The JWT has **no claims
  block** in the result; send it verbatim.
- `acceptance`, `reuse`, `side_effects`, `agent_id`, `agent_email`, `audience`,
  `tos_ledger_email`.
- `signup_request`: `POST` the exact `url` with the exact `headers`
  (`Authorization: Bearer <jwt>`, `Content-Type: application/json`) and raw body
  `{}`. No extra fields, no JWT in the URL or body, no broker POST.
- `next_steps`: the fixed follow-up list.

**Policy behavior**

- `allow` is silent.
- `warn` proceeds with `rp_verification_warning`.
- `require` proceeds only for a verified RP and rejects
  `agent_supplied_discovery` (this tool never supplies one).
- `block` always refuses with `rp_blocked`.
- An unverified RP under `require` is `rp_unverified`; an untrusted broker is
  `rp_broker_untrusted`; invalid/expired are `rp_attestation_invalid` /
  `rp_attestation_expired`; unavailable is `rp_broker_unavailable`.
- `warn` is not a security control. Verification is identity, not safety.

**Side effects and retry**

The call records a delegated acceptance (durable), a mint-time
`rp_verifications` row when verification ran, a ledger email to the agent inbox,
and a forward to the human. Identical calls while the assertion is unexpired
reuse it but re-run every gate and policy. `force_new` creates a new consent
event. Retry after `ledger_email_failed` only re-sends mail; the acceptance is
recorded. Read `side_effects` before retrying anything else.

**Example**

```json
{
  "service": "https://example.com",
  "accepted_tos_text": "<the complete terms.text>"
}
```

The response's `signup_request` is the only request to send. After the RP
responds, call `identity_record_signup` with any `signup_token`. The broker never
proxies the signup or sees the response or a provider credential.

## identity_register

Title: "Create or resume agent sub-identity". Registers the agent sub-identity
for the authenticated session, or returns the one already bound to it.

**Inputs**

| Field | Type | Required | Rule |
| :--- | :--- | :-: | :--- |
| `name` | string | no | Display name. Defaults to `opencode-agent`; reused when the name/harness already exists for the human owner. |
| `harness` | string | no | Harness identifier. Defaults to `opencode-v2`. |

**Result**: the agent id, name, harness, inbox address, status and human owner.
**Side effects**: may create an agent row; no mail. **Errors**: `agent_revoked`,
`internal_error`.

## identity_whoami

Title: "Show agent identity & signup state". Returns the active agent profile,
verified human owner, recent signups, and the latest acceptance per service, plus
documentation links. Auto-provisions a default agent if none exists.

**Inputs**: none. **Result**: agent, human, scopes, recent signups, latest
acceptances, links. **Side effects**: may auto-provision; otherwise read-only.
**Errors**: `agent_revoked`, `internal_error`.

Use it to check "already signed up?" before calling a side-effecting tool.

## identity_prove

Title: "Accept ToS & mint identity assertion". Advanced path. Prefer
`identity_signup` unless you need the raw assertion claims or an explicit
agent-supplied discovery object.

**Inputs**

| Field | Type | Required | Rule |
| :--- | :--- | :-: | :--- |
| `audience` | string | yes | Exact discovery `audience`; becomes the assertion `aud`. |
| `accept_tos_url` | URL | yes | `terms.url`. |
| `accept_tos_hash` | string | yes | `sha256:` over `terms.text`. Recompute it yourself. |
| `accepted_tos_text` | string | yes | Complete `terms.text`, verbatim. |
| `rp_discovery_url` | string | no | Origin or exact discovery URL; the broker fetches it (`broker_fetch`). |
| `rp_discovery` | object | no | Complete discovery document as received (`agent_supplied_discovery`); requires `rp_origin`. |
| `rp_origin` | string | no | Required with `rp_discovery`; forbidden with `rp_discovery_url`. Never inferred from `terms.url` or `provider_url`. |
| `requested_scopes` | string[] | no | Defaults to `["tos:accept","signup:free_tier"]`; every entry must be granted. |
| `force_new` | boolean | no | New acceptance even if one exists. |

Supplying both discovery sources, neither origin with `rp_discovery`, an origin
with `rp_discovery_url`, or a raw `rp_attestation` is
`discovery_source_not_allowed`. A `require` policy rejects
`agent_supplied_discovery`.

**Result**: assertion (`jwt`, `jti`, `kid`, `typ`, hash, timestamps, `claims` for
inspection only), `verification` instructions, scopes, acceptance, reuse,
optional `rp_verification`, optional `rp_verification_warning`, `side_effects`,
agent/audience, ledger email. The assertion gains **no RP claim**; verification
lives in `rp_verifications`.

**Side effects**: acceptance, ledger email/forward, mint-time verification row,
assertion. **Retry**: identical calls reuse the assertion while unexpired; all
gates and policy re-run. `ledger_email_failed` is retryable after the acceptance
is recorded.

## identity_record_signup

Title: "Record signed-up service proof". Records (or confirms) a signup proof for
this agent. Supply exactly one source.

**Inputs**

| Field | Type | Required | Rule |
| :--- | :--- | :-: | :--- |
| `signup_token` | string | one source | The RP-signed v1.2 receipt (`agent-signup-receipt+jwt`). |
| `rp_attestation` | string | no | The exact attestation that contained the receipt key. Omit to fetch discovery at the receipt origin; the broker then requires the exact `service.attestation_jti`. |
| `self_report` | object | one source | `{service_audience, provider_name, provider_account_id, signed_up_at, provider_url?}` for an RP that issued no receipt. Mutually exclusive with `signup_token`. |

The receipt is verified against the **historical** attestation named by
`service.attestation_jti`; there is no broker-key fallback and no substitution of
the current attestation. A legacy broker-signed receipt is rejected.

A self-report is weaker and unsigned: no proof token, assertion, origin, or
verification row; `agent_self_reported`; it cannot overwrite a stronger proof and
still requires a real recorded acceptance.

**Result**: `signup_id`, nullable `signup_token_jti`/`assertion_jti`,
`service_audience`, provider name/account, `human_email_shared`,
`agent_email_used`, `accepted_tos_hash`, `context_url`/`context_sha256`,
`proof_source`, `deduplicated`, nullable `rp_verification_id`, and the handoff
reminder.

**Side effects**: writes one signup proof row; a Tier-1 or stronger row wins.
**Retry**: idempotent on `jti`/assertion. Same jti/different body, a different
account for the same soft key, or an immutable legacy row is `409`.

**Errors**: `signup_token_invalid`, `signup_token_not_linked`,
`signup_token_ownership_mismatch`, `discovery_source_not_allowed`,
`rp_attestation_invalid`, `rp_broker_untrusted`, `rp_broker_unavailable`
(retryable), `agent_revoked`, `internal_error` (retryable).

## inbox_list

Lists recent inbound and outbound messages, newest first.

| Field | Type | Required | Rule |
| :--- | :--- | :-: | :--- |
| `limit` | integer | no | 1-50, default 10. |
| `direction` | `inbound` \| `outbound` | no | Omit for both. |

**Result**: messages with id, direction, sender/recipient, subject, timestamps
and a detected OTP flag. **Side effects**: none. **Errors**: `agent_revoked`,
`scope_not_granted`, `internal_error`.

## inbox_read

Reads one message, including body, headers and any detected six-digit OTP.

| Field | Type | Required |
| :--- | :--- | :-: |
| `message_id` | UUID | yes |

**Side effects**: none. **Errors**: `message_not_found`, `agent_revoked`,
`internal_error`.

## inbox_wait_for_email

Waits for a matching inbound message and returns the newest match.

| Field | Type | Required | Rule |
| :--- | :--- | :-: | :--- |
| `from_contains` | string | no | Case-insensitive sender substring. |
| `subject_contains` | string | no | Case-insensitive subject substring. |
| `since_seconds_ago` | integer | no | Lookback seconds, default 60. |
| `timeout_seconds` | integer | no | 1-60, default 30. |

**Side effects**: none. **Errors**: `wait_timeout` (retryable), `agent_revoked`,
`internal_error`. Do not poll tightly; prefer one wait with a reasonable budget.

## inbox_send

Sends mail from the agent inbox.

| Field | Type | Required |
| :--- | :--- | :-: |
| `to` | email | yes |
| `subject` | string | yes |
| `text` | string | yes |
| `html` | string | no |

**Side effects**: sends email and records the message. **Retry**: not idempotent.
**Errors**: `send_failed` (retryable; nothing sent), `scope_not_granted`,
`agent_revoked`, `internal_error` (check `side_effects.email_sent` before
resending).

## Verification record

The tool names, input shapes, and result keys above were checked against the
shared MCP schema and the tool registration at broker commit `5e57ecf` on
2026-10-24. There are nine tools. `identity_signup` is registered before
`identity_prove` and is preferred in the server instructions and all four
resources. Live `tools/list` and per-tool calls are re-run in the release
verification; this page does not claim a live deployment of the v1.2 broker.

Source: https://docs.agentregistrar.dev/reference/mcp-tools/index.mdx
