A2A 0.3 / MCP 2025-11-25 · LOCAL ADAPTER
A2A to MCP: translate, authorize and execute
Map structured messages to real local record operations; inspect grants, revisions and returned envelopes.
Prepare the adapter request
A2A message → structured operation → MCP tool → local record → A2A reply
Grant supplied to the MCP boundary
Computed transformation and local effects
Execution trace
Current fictional records
Outgoing MCP request
Returned A2A response
MCP result and boundary checks
Before and after records
Complete state evidence
Translate a request, then inspect its effect
This local adapter accepts an A2A 0.3 message/send request, extracts one structured operation, constructs an MCP 2025-11-25 tools/call request and executes a fixed JavaScript record function. It converts the returned structured data into a new A2A agent message. Both protocols use JSON-RPC in this lesson, but their methods and payloads are different. Passing an envelope through unchanged cannot perform the translation. No network connection, language model, external record or real credential is involved.
Know which inputs represent authority
Authenticated caller selects Alice in tenant alpha or Bob in tenant beta. This control represents an already authenticated identity; identity never comes from editable message text. Local grant fixture selects a separately bound tool grant: full read/write, read-only, wrong audience, wrong subject or expired. The displayed grant is an ordinary local object, not a signed access token. The fixed teaching clock is one thousand seconds. A grant expiring exactly at that clock is rejected. Per-tool scope names, record schemas and the subject/tenant checks are application policy, not universal protocol requirements.
Use every editor and action deliberately
Example selects a request template; Load example replaces the editor without executing or resetting the store. A2A request is editable JSON. Execute locally parses and validates it, applies the selected mapping and grant, and shows the resulting envelopes, checks and before/after records. Adapter mapping chooses explicit translation or deliberately incorrect unchanged forwarding. Editing the caller, grant, mapping or JSON clears the previous result but preserves the current records. Reset experiment restores both records to revision one, Alice, a bound grant, translation, the read example, counters and identifiers. Selecting a template alone leaves the current request unchanged until Load example is pressed.
Reproduce a read and a conditional write
Start at defaults and execute the read example. The returned alpha record is a1, value Draft, revision one; committed writes remains zero. Load Conditional write and execute. Its expectedRevision is one, so the value becomes Published and the revision becomes two. Execute exactly the same request again. The tool now reports a revision conflict and the store stays unchanged. This is optimistic concurrency, not request-ID deduplication. Edit expectedRevision to two and value to Reviewed, execute, and inspect revision three. The same outer request ID can be reused in this local experiment; it does not promise idempotency.
Keep incoming and outgoing credentials separate
Reset, load Conditional write, choose Read-only grant and execute. The MCP credential gate reports status 403 because records:write is absent; no record changes. Loading Read record with that same grant succeeds. Choose Forward A2A-audience grant to reproduce a 401 audience rejection. Wrong subject and expired grants also fail before execution. These statuses model the HTTP authorization boundary and therefore appear outside the MCP JSON-RPC response. The adapter returns an A2A message whose application data reports failure. It does not label an authorization denial as a successful write or leak an incoming token into a tool argument.
Distinguish translation failure from tool failure
With defaults restored, select Forward envelope unchanged and execute the read. The MCP endpoint receives message/send instead of tools/call, reports JSON-RPC method-not-found code minus thirty-two thousand six hundred one, and performs no record function. Return to Translate structured operation: the generated request has its own tool-prefixed ID and arguments containing id rather than recordId. The outer A2A response echoes outer-7 while its messageId identifies a new response message. Load Stale revision to obtain a different outcome: an understood MCP tool returns isError=true because the expected revision is zero. These errors have different causes and preserve different evidence.
Test tenant and instruction boundaries
At defaults, load Cross-tenant read. Alice cannot access b1, so the adapter denies the request before creating an MCP request. Switch the authenticated caller to Bob; the bound grant now names Bob and beta, and the same structured read returns Private. The MCP dispatcher independently checks record ownership against the grant tenant. Load Text cannot grant access, return to Alice, select a read-only grant and execute. The text asks for write permission, but only the structured operation determines arguments and only the grant supplies scopes. The attempted write remains denied. Text is neither executed nor interpreted by a language model.
Exercise the supported schema and limits
The editor allows twelve thousand characters, a nonempty string or safe-integer request ID, exactly one data part, and up to four total text/data parts. Text parts allow five hundred twelve Unicode code points. A write value allows one hundred twenty-eight code points, including an empty string, and the expected revision is an integer from zero through one million. Read data has only operation and recordId; write additionally requires value and expectedRevision. Unsupported fields, files, task references, extra data operations, malformed JSON and unknown operations fail before dispatch. This intentionally strict subset is not a general A2A validator; optional protocol features may be valid elsewhere while unsupported here.
Interpret the local evidence within its scope
Open the MCP result and before/after details to inspect the exact checks and data. Complete state evidence includes both fictional tenants for teaching; this is not an example of production audit-log permissions. Records persist only until reset or page reload. There is no task lifecycle, streaming, initialization handshake, discovery, credential issuance, cryptographic verification, remote transport or concurrent writer. Record functions run synchronously and immediately, so the lab uses direct actions instead of an artificial playback timer. The displayed transformations and mutations are actually computed, while protocol compatibility with real peers still requires separate integration tests.
Protocol references: A2A 0.3 message and data-part definitions and MCP 2025-11-25 tools and error handling. The application mapping and fictional authorization policy are specific to this experiment.