MCP Fusion/Integrations and federation/A2A bridge

A2A bridge

Ask AI about Vinkius

Expose an MCP Fusion connector as an Agent2Agent service: compile an Agent Card from the registry, handle message and task JSON-RPC methods, and stream results over HTTP.

MCP is the tool boundary. A2A is the agent boundary. The MCP Fusion A2A package lets a connector participate in an Agent2Agent network without rewriting its tools: the registry remains the source of capabilities, and the bridge exposes the agent-facing task protocol.

Compile an Agent Card

typescript
import { compileAgentCard, A2AHandler } from '@mcpfusion/a2a';

const card = compileAgentCard(
  {
    name: 'billing-agent',
    version: '1.0.0',
    url: 'http://localhost:3001',
  },
  registry.getBuilders(),
  promptRegistry,
  resourceRegistry,
);

The compiler derives skills from builder names and action metadata. The card is served at /.well-known/agent-card.json; the legacy path is /.well-known/agent.json. A2A JSON-RPC requests use /a2a, and the package identifies itself as protocol 1.0.0.

The optional bridge config describes how the card is reached through another bridge. Do not hand-maintain a second capability list: compile from the same builders that serve MCP and the card stays aligned with the real registry.

JSON-RPC handler

The handler consumes an executor with two responsibilities:

typescript
const executor = {
  execute: async (toolName: string, args: Record<string, unknown>) =>
    registry.routeCall(context, toolName, args),
  hasToolName: (name: string) => registry.has(name),
};

const handler = new A2AHandler(executor);
const response = await handler.handleRequest(jsonRpcRequest);

The supported methods include message/send, message/stream, tasks/get, tasks/cancel, tasks/list, tasks/resubscribe, push-notification configuration set/get/list/delete and agent/getAuthenticatedExtendedCard. The bridge validates JSON-RPC, maps tool execution errors to A2A error codes and keeps MCP tool names behind the executor boundary.

Task lifecycle

TaskManager owns the task state used by the handler. Its operational methods are:

  • createTask(contextId, message?)
  • updateStatus(taskId, status)
  • addArtifact(taskId, artifact)
  • getTask(taskId)
  • listTasks(request)
  • cancelTask(taskId)

Configure task TTL and the maximum task count. This is an in-process manager; use the bridge behind a process model that matches its lifetime, or put durable task state at the A2A boundary.

Streaming transport

StreamableHttpTransport wraps an A2AHandler and an optional streaming executor. message/stream emits server-sent events using the package's formatSSEEvent, formatSSEErrorEvent and parser helpers. The MCP server itself can remain stateless while the A2A task layer owns the stream lifecycle.

Error model

The bridge exposes typed errors for invalid JSON-RPC, unsupported operations, missing tasks, non-cancelable tasks, unsupported push notifications, invalid agent responses and content types. It also exports the A2A error-code table, extension header X-A2A-Extensions, SSE headers and the protocol constants, so an integration can test against the same values it serves.

Security boundary

The A2A bridge does not replace MCP authentication. Put JWT, API key or gateway clearance in front of the executor, and make the Agent Card reflect only the tools that deployment is willing to expose. If this bridge is behind Swarm, the delegation token and namespace isolation happen before A2A execution. If it is public, authenticate the HTTP route before parsing task messages.

MCP and A2A together

A single connector can expose:

ConsumerSurface
Claude, Cursor, any MCP clientMCP tools, resources and prompts
Another agent platformAgent Card and A2A tasks
Vinkius Cloudconnector token, governance and console controls

The business logic remains in the same handlers and Presenters. What changes is the protocol adapter at the edge.

Next steps