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 holds the code list, and the broker HTTP reference 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 asAuthorization: Bearer. The token is bound to one verified human owner. - Transport: one stateless handler per request. There is no session id to keep,
and
POSTis the only method the tool flow needs. initializereportsserverInfo.nameagentregistrar, version1.0.0, capabilitiestoolsandresources, and the system instructions that describe the workflow.tools/listreturns exactly nine tools.resources/listreturns four statictext/markdownresources. They repeat documented material for clients that cannot follow links; the pages they point at stay canonical.
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.
MCP resources
| URI | Title | Material also published at |
|---|---|---|
agentregistrar://docs/quickstart |
Agent Registrar quickstart | Agent quickstart |
agentregistrar://docs/assertion-claims |
Agent assertion claims (Contract A) | Assertion claims |
agentregistrar://docs/error-recovery |
Tool error recovery | Error codes |
agentregistrar://docs/spec |
Agent Identity specification | 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:
- The bearer token must resolve to an
mca_...token row that is not revoked and not expired. Otherwise401, code-32001. - The token's human owner must be
activeand must have signed the Master Agent Delegation agreement. Otherwise403, code-32003. - The agent sub-identity must exist and be
active.identity_registercreates 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, andidentity_record_signupregister structuredoutputSchemas; 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.
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:
{
"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 | Create or resume the agent sub-identity for this session | no | yes |
identity_whoami |
Identity | Show the agent, human owner, scopes, recent signups and acceptances | yes | yes |
identity_signup |
Identity | One call: fetch discovery, apply policy, mint, return a prepared signup request | no | yes |
identity_prove |
Identity | Advanced: accept terms and mint with claim inspection | no | yes |
identity_record_signup |
Identity | Record an RP-signed receipt or a weaker self-report | no | yes |
inbox_list |
Inbox | List recent messages, newest first | yes | yes |
inbox_read |
Inbox | Read one message body, headers and detected OTP | yes | yes |
inbox_wait_for_email |
Inbox | Wait for a matching inbound message | yes | yes |
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 awarnpolicy 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:POSTthe exacturlwith the exactheaders(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
allowis silent.warnproceeds withrp_verification_warning.requireproceeds only for a verified RP and rejectsagent_supplied_discovery(this tool never supplies one).blockalways refuses withrp_blocked.- An unverified RP under
requireisrp_unverified; an untrusted broker isrp_broker_untrusted; invalid/expired arerp_attestation_invalid/rp_attestation_expired; unavailable isrp_broker_unavailable. warnis 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
{
"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 |
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.