# A202 (oci · ghcr.io/a202-protocol/a202-mcp:0.1.0)

Verifiable agreements for agent-led commerce: mandates, obligations, evidence, transaction records.

- Trust score: 41/100 (low)
- Change this week: +7
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-22

## Components

- oci · `ghcr.io/a202-protocol/a202-mcp:0.1.0`: 41/100 (this document), [markdown](https://verifymcp.io/servers/a202-protocol-a202-mcp/ghcr-io-a202-protocol-a202-mcp-0-1-0.md), [page](https://verifymcp.io/servers/a202-protocol-a202-mcp/ghcr-io-a202-protocol-a202-mcp-0-1-0)

## Channel facts

- Registry: `oci`
- Package: `ghcr.io/a202-protocol/a202-mcp:0.1.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-22.

- **Supply Chain Security**: 0/100
  - Malware scan not yet available for this package.
  - Known CVEs could not be checked: this artifact ships no SBOM, so there is no dependency list to read. Publishing one would let us assess it.
  - Install-script risk not yet assessed.
  - Dependency health could not be checked: this artifact ships no SBOM, so there is no dependency list to read. Publishing one would let us assess it.
- **Provenance & Transparency**: 35/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - License check failed: no license is declared.
  - Actively maintained (last published 14 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 59/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 4114 tokens (~587/item across 7 items; 7 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 47/100
  - Stability observed for 14 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
- **Capabilities**: 100/100
  - Implements a current MCP spec version (2026-07-28).

**Unverified: 1 category.** A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### Claude

```bash
claude mcp add a202-protocol-a202-mcp -- docker run --rm -i ghcr.io/a202-protocol/a202-mcp:0.1.0
```

### Codex

```bash
codex mcp add a202-protocol-a202-mcp -- docker run --rm -i ghcr.io/a202-protocol/a202-mcp:0.1.0
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "a202-protocol-a202-mcp": {
      "type": "local",
      "command": [
        "docker",
        "run",
        "--rm",
        "-i",
        "ghcr.io/a202-protocol/a202-mcp:0.1.0"
      ],
      "enabled": true
    }
  }
}
```

### Hermes

```yaml
mcp_servers:
  a202-protocol-a202-mcp:
    command: "docker"
    args: ["run", "--rm", "-i", "ghcr.io/a202-protocol/a202-mcp:0.1.0"]
```

### Other

```json
{
  "mcpServers": {
    "a202-protocol-a202-mcp": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "ghcr.io/a202-protocol/a202-mcp:0.1.0"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-22 (score 41, +1)

No change was recorded against any check on this day. Stability & Change Management went from 43 to 47. That category is still filling its 30-day observation window: 13 days of observed history at the previous scan, 14 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-08-20 (score 40, +1)

No change was recorded against any check on this day. Stability & Change Management went from 37 to 40. That category is still filling its 30-day observation window: 11 days of observed history at the previous scan, 12 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-08-18 (score 39, +1)

No change was recorded against any check on this day. Stability & Change Management went from 30 to 33. That category is still filling its 30-day observation window: 9 days of observed history at the previous scan, 10 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-08-16 (score 38, +4)

- [functional improvement] Stability: unverified → 0.27

### 2026-08-11 (score 34, +1)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-08-08 (score 33)

First indexed and scored.

## MCP tools (7)

### `issue_mandate` (~703 tokens)

Issue a commercial mandate

Issue and sign a commercial mandate: the document stating which organisation an agent represents, which acts it may take, under which limits, for which transaction or category, and for how long. Call this once per acting agent before anything else. Every other tool names the mandate an agent acts under.

A spending_limit becomes two explicit constraints, an amount ceiling and a currency, both visible in the audit record.

The mandate is checked before it is signed, so a refused one never receives a signature that would make it look issued. Refusals: no constraint at all (A202-MANDATE-UNBOUNDED), a scope naming neither a transaction nor a category (A202-MANDATE-SCOPE-TOO-BROAD), an inverted validity interval (A202-MANDATE-INTERVAL-INVALID), a status endpoint that is not HTTPS (A202-MANDATE-STATUS-INSECURE), a subject naming both an agent and a principal (A202-MANDATE-SUBJECT-AMBIGUOUS).

Returns the mandate identifier and the signed document.

Input parameters:

- `actions` (array, required): The acts the subject may take, for example offer.submit, offer.accept, agreement.sign. Deny by default: an omitted act is not allowed.
- `approval_rules` (array): Optional. Each rule carries id, a when predicate of path, operator, and value, an approver of organization_id and role, and expires_after_seconds. A matching act is held until an approval from that a…
- `constraints` (array): Optional further constraints, each with id, type, path, operator, value, and on_failure of deny or require_approval. At least one constraint must exist in total, counting those a spending limit gener…
- `delegation` (object): Optional, defaults to no delegation. allowed false requires maximum_depth 0; allowed true requires at least 1. An incoherent pair is refused rather than interpreted.
- `evidence_refs` (array): Optional identity, role, or authorisation evidence supporting the issue.
- `issuer` (object, required): The principal issuing the authority, and the key it signs with.
- `mandate_id` (string): Optional explicit identifier, prefixed mnd_. One is minted when absent.
- `parent_mandate_id` (string|null): The mandate this one is delegated from, or null for a root mandate.
- `represented_organization_id` (string, required): The organisation the subject represents in its acts, prefixed org_.
- `scope` (object, required): The boundary of the authority. Must carry transaction_ids, categories, or both. Counterparty and geography narrow an existing boundary and cannot establish one, so a scope naming only a country is re…
- `spending_limit` (object): Optional. Becomes an amount ceiling and a currency constraint. A ceiling with no currency would be satisfied by that number of any currency, so both are written.
- `status_endpoint` (string, required): HTTPS URL where this mandate's current status is published. HTTPS only: cached status is the only channel a revocation reaches a relying party through.
- `subject` (object, required): Who acts under the mandate: exactly one of an agent or a delegated principal, never both.
- `valid_from` (string, required): RFC 3339 UTC instant. Must be strictly earlier than valid_until.
- `valid_until` (string, required): RFC 3339 UTC instant. The mandate authorises nothing at or after it.

### `verify_mandate` (~413 tokens)

Verify a mandate and decide on an act

Check a mandate and decide whether an act is permitted under it. Call this before every act, on your own mandate or on one a counterparty presented.

It checks the document against the published schema and the rules the schema cannot express, verifies the issuer signature, checks the validity interval, and, when proposed_action is given, checks the act against the mandate's actions, its four scope axes, its constraints in stable order, and its approval rules.

Returns one decision, allow, deny, or require_approval, with the registered reason codes behind it, the per-constraint outcomes, and action_hash, the hash of the exact act evaluated.

On require_approval: pass that action_hash to issue_approval, then call this tool again with the returned approval_id and the identical proposed_action. The decision becomes allow. A deny is never approvable.

This server makes no network call. Resolve the mandate's status_endpoint yourself and pass the result as status. An absent result, one older than 60 seconds, or any status other than active denies with A202-MANDATE-STATUS-UNRESOLVED or A202-MANDATE-INACTIVE: unavailability is not permission.

Input parameters:

- `approval` (object): An approval object presented directly, instead of approval_id.
- `approval_id` (string): An approval this server holds, from issue_approval, that releases a require_approval hold.
- `at` (string): RFC 3339 instant to check against. Defaults to now.
- `mandate` (object): The mandate document, when it came from a counterparty.
- `mandate_id` (string): A mandate this server holds, as returned by issue_mandate.
- `proposed_action` (object): The act to evaluate against the mandate. Constraint paths address this document from $, so a spending limit reads $.proposed_terms.core.total.amount.
- `status` (object): What you retrieved from the mandate's status endpoint, and when. Omit it and the decision is deny.

### `issue_approval` (~373 tokens)

Approve one exact act

Record a named principal's approval of one exact act, bound to the action_hash verify_mandate reported. Call this only after verify_mandate answered require_approval, then call verify_mandate again passing approval_id and the identical proposed_action.

The approval is signed by the approving principal's own key, not by the agent's, because the control is that somebody other than the acting agent said yes. It binds one action hash and one transaction and is reusable across neither: change one byte of the act and the next verify_mandate returns A202-APPROVAL-HASH-MISMATCH. It also expires, after which it authorises nothing.

An approval never releases a deny. A denied constraint is a limit, not a question.

Returns the approval identifier, the action hash it binds, and when it expires.

Input parameters:

- `action_hash` (string, required): The action_hash verify_mandate returned for this act. 64 lowercase hexadecimal characters.
- `approver` (object, required): The principal giving the approval, and the key that principal signs with.
- `conditions` (array): Optional conditions the approver attached. They are part of the signed approval and travel with it.
- `decision`: Defaults to approved. A rejected approval releases nothing and is recorded as the refusal it is.
- `expires_after_seconds` (integer): How long the approval is good for, from now. Defaults to 3600.
- `expires_at` (string): RFC 3339 instant the approval expires, when you would rather state it than count from now. Overrides expires_after_seconds.
- `requested_by` (object, required): The agent whose act is being approved. The approver is a principal of this same organisation.
- `transaction_id` (string, required): The transaction the approved act belongs to, prefixed txn_.

### `create_agreement` (~752 tokens)

Form an agreement with a known counterparty

Form an agreement between two parties who already know each other, with no marketplace and no negotiation room. Call this once per transaction.

Both parties present the allow decision their own mandate produced. The offeror verifies {"action_type": "offer.submit", "transaction_id": ..., "counterparty_organization_id": <the offeree's org>, "proposed_terms": <the same terms>} and the offeree verifies the same document with action_type offer.accept and the offeror's organisation. Pass each result as buyer_decision and supplier_decision. A decision over a different act, a different mandate, or an amount the mandate did not allow refuses the whole call and records nothing.

It writes the whole formation in one call: the offeror's signed offer carrying a session identifier it mints, the offeree's acceptance over the exact offer hash, the agreement carrying both parties' signatures over the same bytes, the supplier's commitment, and two events, agreement.direct (draft to agreement_pending) and agreement.committed (agreement_pending to committed), each countersigned by the other party.

The transaction ends this call in state committed. Follow with record_obligation act=issue.

Refusals: a transaction that already left draft (A202-STATE-TRANSITION-DENIED), an unregistered profile (A202-PROFILE-UNKNOWN), terms the profile does not allow (A202-PROFILE-TERMS-INVALID), an offer expiring before it was made (A202-OFFER-EXPIRED).

Input parameters:

- `buyer` (object, required): The buying party: organisation, agent, mandate, and signing key.
- `buyer_decision` (object, required): The result verify_mandate returned for this exact act, passed through unchanged. It must be an allow, made under this party's own mandate, over the act document this tool builds, and made within the…
- `offer_evidence_refs` (array): Optional evidence the offer relies on, such as an accreditation.
- `offer_valid_until` (string, required): RFC 3339 instant the offer expires. Must be later than now.
- `offeror_role`: Which party makes the offer. Defaults to supplier.
- `rules_version` (string): The rule set version the record is written under. Defaults to 1.3, the version that registers direct formation. Earlier versions never registered it and refuse the path.
- `session_id` (string): Optional session identifier, prefixed ses_. The offeror mints one when absent. Bilaterally this names the relationship; nothing orders it.
- `supplier` (object, required): The supplying party: organisation, agent, mandate, and signing key.
- `supplier_decision` (object, required): The result verify_mandate returned for this exact act, passed through unchanged. It must be an allow, made under this party's own mandate, over the act document this tool builds, and made within the…
- `terms` (object, required): The commercial terms. core is identical for every transaction profile; profile_terms is validated against the schema the profile names.
- `transaction_id` (string, required): The transaction, prefixed txn_. Choose one per deal; it is the key everything else is recorded under.

### `record_obligation` (~1010 tokens)

Issue, assert, or answer an obligation

Record one act in the obligation exchange. Three acts, in this order, each signed by a different party, and each carrying that party's own allow decision from verify_mandate.

act=issue: the obligee derives an obligation from a committed agreement and activates it. Needs agreement_id, obligor, obligee, term_path, quantity, unit_code, due_condition, and a decision the obligee obtained for {"action_type": "obligation.activated", "transaction_id": ..., "counterparty_organization_id": <the obligor's org>, "proposed_terms": {"core": {"quantity": ..., "unit_code": ..., "total": <the consideration>}}, "agreement_id": ...}. The transaction moves to in_performance.

act=assert: the obligor asserts it performed. Needs obligation_id, obligor, obligee, asserted_quantity, at least one evidence entry, and a decision the obligor obtained for action_type performance.declared naming the obligee as counterparty, the asserted quantity and unit as proposed_terms, and the obligation_id. An assertion with no evidence is refused with A202-OBLIGATION-ASSERTION-UNEVIDENCED. The transaction moves to acceptance_pending.

act=respond: the obligee accepts or rejects, bound to the exact assertion hash. Needs assertion_id, responder, counterparty, response_type, and a decision the responder obtained for action_type acceptance.granted or acceptance.rejected naming the counterparty and the assertion_id. A response signed by anyone but the obligee is refused with A202-OBLIGATION-RESPONSE-UNAUTHORIZED; accepting less than is owed without naming a remainder obligation is refused with A202-OBLIGATION-REMAINDER-MISSING. Accept moves the transaction to settlement_pending, reject back to in_performance, where the obligor may assert again.

Input parameters:

- `accepted_quantity` (string): act=respond with accept. Defaults to the asserted quantity. Below what is owed, a remainder_obligation_id is required.
- `act` (required): Which act to record. Which other fields are required depends on it.
- `agreement_id` (string): act=issue. The committed agreement the obligation derives from, prefixed agr_.
- `asserted_quantity` (string): act=assert. Base-10 string of how much was performed.
- `assertion_id` (string): act=respond. The assertion being answered, prefixed prf_.
- `commitment_id` (string): act=issue. Optional. Defaults to the agreement's first commitment.
- `consideration` (object|null): act=issue. The money attached to this obligation as currency and amount, or null.
- `counterparty` (object): act=respond. The other party, which countersigns the event.
- `decision` (object, required): The result verify_mandate returned for this exact act, passed through unchanged. It must be an allow, made under this party's own mandate, over the act document this tool builds, and made within the…
- `due_condition` (object): act=issue. One of due_at_time with at, due_on_event with act_ref or evidence_type, due_on_discharge with obligation_id, or all_of with at least two of those. Anything else is refused with A202-OBLIGA…
- `evidence` (array): act=assert. At least one entry. Each becomes a signed evidence object the assertion references by hash.
- `obligation_id` (string): act=assert. The obligation being performed, prefixed obl_.
- `obligee` (object): act=issue and act=assert. The party owed to.
- `obligor` (object): act=issue and act=assert. The party that owes.
- `quantity` (string): act=issue. Base-10 string of how much is owed.
- `reason_code`: act=respond with reject. The list is closed and anything else is refused.
- `remainder_obligation_id` (string): act=respond with a short acceptance. The obligation carrying the shortfall, so it stays in the record.
- `responder` (object): act=respond. Must be the obligee named on the obligation.
- `response_type`: act=respond.
- `rules_version` (string): The rule set version the record is written under. Defaults to 1.3.
- `term_path` (string): act=issue. The owed term, addressed under $.terms.core or $.terms.profile_terms. The obligation points at the agreement's terms and never restates them, so drift shows up as a hash mismatch.
- `unit_code` (string): act=issue. UN/ECE Recommendation 20 common code, matching the terms.

### `verify_evidence` (~290 tokens)

Verify a record against the published procedure

Run the seven-step verification procedure over a set of objects: content hashes, signatures and the purpose each was issued for, version chains, event-chain continuity, guarded transitions replayed against the rules version in force, whether each determination follows from its rules, and what could not be checked. Use it on your own record before relying on it, and on anything a counterparty sends you.

Pass transaction_id to verify this server's record of one transaction, object_ids to verify part of it, or objects to verify a bundle somebody handed you.

Every check returns verified, failed, or not_checkable, and the result carries no overall boolean, because a report reduced to one discards what could not be checked. A signature whose key you do not hold is not checkable and is never thereby verified. Without rules_version, guarded transitions are not checkable rather than verified: an unresolvable rule set is not permission in either direction.

Input parameters:

- `object_ids` (array): Identifiers of objects this server holds.
- `objects` (array): Objects presented by value, for example a bundle a counterparty sent.
- `rules_version` (string): The rule set version in force when the record appended, for example 1.3. A record replays against the version it was written under, never the current one.
- `transaction_id` (string): Verify every object this server holds for one transaction.

### `get_transaction_record` (~145 tokens)

Read the transaction record

Return this party's own copy of the hash-chained transaction record: every event in chain order with the state it moved the transaction to, which keys signed it, and the object it concerns, plus the state the record currently reaches and every object identifier held for the transaction.

Call it at any point to see where a transaction stands before deciding what to do next. Ordering is by predecessor reference rather than by a counter, because bilaterally there is no ordering service, and a record whose links do not form one chain is reported as broken with A202-EVIDENCE-CHAIN-GAP.

Input parameters:

- `transaction_id` (string, required): The transaction to read, prefixed txn_.

## Diagnostics

Captured diagnostic sections: Provenance. The full working is on the page: https://verifymcp.io/servers/a202-protocol-a202-mcp/ghcr-io-a202-protocol-a202-mcp-0-1-0#diagnostics

## Score history

- 2026-08-22: 41
- 2026-08-21: 40
- 2026-08-20: 40
- 2026-08-19: 39
- 2026-08-18: 39
- 2026-08-17: 38
- 2026-08-16: 38
- 2026-08-15: 34
- 2026-08-14: 34
- 2026-08-13: 34
- 2026-08-12: 34
- 2026-08-11: 34
- 2026-08-10: 33
- 2026-08-09: 33
- 2026-08-08: 33

## Links

- Repository: https://github.com/a202-protocol/a202
- Website: https://a202.org/
- Changelog RSS feed: https://verifymcp.io/servers/a202-protocol-a202-mcp/ghcr-io-a202-protocol-a202-mcp-0-1-0.xml
- Changelog JSON feed: https://verifymcp.io/servers/a202-protocol-a202-mcp/ghcr-io-a202-protocol-a202-mcp-0-1-0.json
- HTML version of this page: https://verifymcp.io/servers/a202-protocol-a202-mcp/ghcr-io-a202-protocol-a202-mcp-0-1-0
