Apps on OZ

Interop matrix

Which MCP and A2A clients were tested against the MCP server and the A2A agents, which agent frameworks were run as harnesses, what each did, and when.

For: application developers.

Use this matrix to check which protocol features were exercised with each client's own SDK. Every agent and flow is available as an MCP tool and an A2A agent. The rows report test results; they do not compare products or establish whether an unlisted client works.

make interop starts a dev server, a node and two agents: one answers and one asks a person a question. Each client runs with an operator's tenant API key, another operator's key and a key scoped to one agent. For the OAuth check, a person signs in through a fake identity provider and approves the client in the console; that check uses no API key.

Last run: 2026-10-21, on orchestrator-zero 5af15e15e (commit 5af15e15e, built 2026-10-20T23:05:25Z, go1.27.2 linux/amd64).

pass is a feature that did what the protocol and this server's documentation say; n/a is a feature the client does not offer (its protocol revision or its SDK has none), as its note says; fail did not work, and its note says how. An empty cell is a feature that client's driver does not run.

MCP clients

ClientVersionTestedhandshaketools/listtools/callinput required (MRTR)Tasks extensionsubscriptions/listenconversationscoped keyOAuth
Python MCP SDK (mcp 1.x)1.30.02026-10-21passpasspassn/an/an/apasspasspass
Python MCP SDK (mcp)2.3.02026-10-21passpasspasspasspasspasspasspasspass
Python MCP SDK (mcp), legacy mode2.3.02026-10-21passpasspassn/an/an/apasspasspass
TypeScript MCP SDK (@modelcontextprotocol/client)2.3.12026-10-21passpasspasspassn/apasspasspasspass
TypeScript MCP SDK (@modelcontextprotocol/client), legacy mode2.3.12026-10-21passpasspassn/an/an/apasspasspass
TypeScript MCP SDK (@modelcontextprotocol/sdk)1.32.12026-10-21passpasspassn/an/an/apasspasspass
  • handshake: server/discover for MCP 2026-07-28, initialize for 2025-11-25 and before.
  • input required (MRTR): the agent asks a person a question; the client's elicitation handler answers it and the SDK retries the call with the answer.
  • Tasks extension: tasks/get, tasks/update with the answer, and tasks/cancel.
  • conversation: a call that sends back _meta["ai.oz0/conversation"] is the next turn; another key of the same tenant that sends it is told it is unknown.
  • scoped key: a key scoped to one agent lists and calls only that agent.
  • OAuth: no key at all: the client finds the tenant's authorization server from the 401, registers with a loopback redirect address, sends the person to the console, where they sign in through the identity provider and approve the client, redeems the code with PKCE, and then lists and calls the person's agents as them.
  • input required (MRTR), n/a: 2025-11-25 has no input_required results; the question waits in the inbox (Python MCP SDK (mcp 1.x) 1.30.0, Python MCP SDK (mcp), legacy mode 2.3.0, TypeScript MCP SDK (@modelcontextprotocol/client), legacy mode 2.3.1, TypeScript MCP SDK (@modelcontextprotocol/sdk) 1.32.1).
  • Tasks extension, n/a: the SDK has no client for the Tasks extension: it refuses a task as tools/call's result (TypeScript MCP SDK (@modelcontextprotocol/client) 2.3.1).
  • Tasks extension, n/a: the Tasks extension needs 2026-07-28 (Python MCP SDK (mcp 1.x) 1.30.0, Python MCP SDK (mcp), legacy mode 2.3.0, TypeScript MCP SDK (@modelcontextprotocol/client), legacy mode 2.3.1, TypeScript MCP SDK (@modelcontextprotocol/sdk) 1.32.1).
  • subscriptions/listen, n/a: subscriptions/listen is 2026-07-28's (Python MCP SDK (mcp 1.x) 1.30.0, Python MCP SDK (mcp), legacy mode 2.3.0, TypeScript MCP SDK (@modelcontextprotocol/client), legacy mode 2.3.1, TypeScript MCP SDK (@modelcontextprotocol/sdk) 1.32.1).

A2A clients

ClientVersionTestedsigned cardSendMessage, blockingSendMessage, returnImmediately + GetTaskinput requiredCancelTaskcontextsartifact hashscoped keyADK's default client
A2A JavaScript SDK (@a2a-js/sdk)1.3.02026-10-21passpasspasspasspasspasspasspass
Google ADK (google-adk), RemoteA2aAgent2.11.02026-10-21n/apasspasspasspass
Python A2A SDK (a2a-sdk)1.2.22026-10-21passpasspasspasspasspasspasspass
  • signed card: the card's JWS (ES256 over its RFC 8785 form) verified with the key at its jku.
  • contexts: a message with a task's contextId is the next turn; another key of the same tenant that sends it is told it is unknown.
  • artifact hash: metadata["ai.oz0/sha256"] recomputed from the parts the client received.
  • The server speaks A2A 1.0 only, and refuses a client of 0.3 (no A2A-Version: 1.0 header) with -32009.
  • signed card, n/a: ADK resolves the card by its URL and does not check its signature (Google ADK (google-adk), RemoteA2aAgent 2.11.0).

Our A2A client

Outside A2A agents run through the A2A client of the verified plugin a2a-remote. make interop also runs it against a sample server built with each A2A SDK, on loopback, as a job's session would call an outside agent.

ServerVersionTestedcard and interfacesigned cardSendMessage + GetTaskinput requiredCancelTask
A2A JavaScript SDK (@a2a-js/sdk), its server1.3.02026-10-21passpasspasspasspass
Python A2A SDK (a2a-sdk), its server1.2.22026-10-21passpasspasspasspass
  • card and interface: the card read, and its JSON-RPC interface on the card's own origin chosen.
  • signed card: the card's signature (the SDK's own signer) verified with the key at its jku.
  • SendMessage + GetTask: a task sent with returnImmediately and read until it answers.
  • input required: the server's question answered, as a person answers it, and the task completed.
  • CancelTask: a running task cancelled when the job is.

Agent frameworks as harnesses

The harness templates run an agent written for one of these frameworks as one session of a job. make interop-frameworks installs each template's example plugin on a dev server with two nodes and runs it against a fake model API behind the gateway, with the framework's own pinned release. Last run: 2026-10-21, on orchestrator-zero 5af15e15e (commit 5af15e15e, built 2026-10-20T23:05:25Z, go1.27.2 linux/amd64).

FrameworkVersionTestedturntool call asked and answeredquota resumebudget refusallost node
AWS Strands (strands-agents)1.59.02026-10-21passpasspasspasspass
Google ADK (google-adk)2.11.02026-10-21passpasspasspass
Microsoft Agent Framework (agent-framework-core)1.21.02026-10-21passpasspasspass
  • turn: a job ran as one session; every model call went through the gateway, in the framework's own API, and was metered under the job.
  • tool call asked and answered: each of the framework's tool calls was asked as <harness>.<tool>; a read ran, a write waited for a person's approval and ran once approved.
  • quota resume: a quota refused the session's second model call; once it was raised, the session was started again with its session ID and went on from its conversation.
  • budget refusal: the gateway's refusal stopped the session's call, and the job waited for a budget decision instead of failing.
  • lost node: the node was killed under a session; the restart waited for a person, and a fresh session ran from scratch on the other node.
  • Each is governed and metered, and durable only as one step: a lost node starts the session again from scratch, and that restart asks a person first unless lint proves the agent's tools only read.

Not tested

ClientProtocolWhy notWhat a run needs
Claude CodemcpIts MCP client runs inside the agent, and driving it headless (claude -p) needs a signed-in account or an API key and calls the provider's model; the harness signs in to nothing and calls no outside serviceA test account or key, and a decision to call the provider from the harness; then claude mcp add --transport http with the tenant's /mcp URL, which connects as a person with OAuth, or with a tenant key
CursormcpIts MCP client runs in the editor and its command-line agent, both of which need a signed-in accountA test account; the client then connects to the tenant's /mcp URL as a person with OAuth
Visual Studio CodemcpIts MCP client is part of the chat's agent mode, which needs a signed-in account; nothing drives it headless without oneA test account; the client then connects to the tenant's /mcp URL as a person with OAuth
IBM watsonx Orchestratemcp, a2aA hosted serviceA trial account, and an edge it can reach
Microsoft Copilot Studiomcp, a2aA hosted serviceA trial tenant, and an edge it can reach
Google ADK, hosted parts (Agent Engine)a2aA hosted service; ADK's own A2A client, which runs locally, is tested aboveA cloud project, and an edge it can reach

Product names belong to their owners and are used here only to say which client or framework was run; a row says what we ran, not that the owner endorses it.

Copyright © 2026