<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vahap Ogut</title>
    <description>The latest articles on DEV Community by Vahap Ogut (@vahapogut).</description>
    <link>https://dev.to/vahapogut</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3935563%2F7d8a7975-15dc-430d-b11f-e548e7f1b261.png</url>
      <title>DEV Community: Vahap Ogut</title>
      <link>https://dev.to/vahapogut</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vahapogut"/>
    <language>en</language>
    <item>
      <title>How I Built a Universal MCP ↔ A2A Bridge: Architecture, Protocol Mapping, and What I Learned</title>
      <dc:creator>Vahap Ogut</dc:creator>
      <pubDate>Sat, 16 May 2026 22:23:07 +0000</pubDate>
      <link>https://dev.to/vahapogut/how-i-built-a-universal-mcp-a2a-bridge-architecture-protocol-mapping-and-what-i-learned-df3</link>
      <guid>https://dev.to/vahapogut/how-i-built-a-universal-mcp-a2a-bridge-architecture-protocol-mapping-and-what-i-learned-df3</guid>
      <description>&lt;p&gt;The AI agent ecosystem is fragmenting into two incompatible standards. On one side, Anthropic's&lt;br&gt;
  MCP (Model Context Protocol) lets AI models use tools. On the other, Google's A2A&lt;br&gt;
  (Agent-to-Agent) lets agents collaborate. They can't talk to each other.&lt;/p&gt;

&lt;p&gt;I built Nexarion, a runtime bridge that translates between these protocols in real-time. Here's&lt;br&gt;
  the architecture, the protocol mapping, and what I learned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Claude Desktop integrates with MCP servers to access tools like databases, APIs, and file&lt;br&gt;
  systems. But Google's A2A ecosystem has a different design. A2A agents expose "Agent Cards" at&lt;br&gt;
  &lt;code&gt;/.well-known/agent-card.json&lt;/code&gt;, describe their skills, and communicate via JSON-RPC.&lt;/p&gt;

&lt;p&gt;They're solving complementary problems but they don't interoperate. If I want Claude to call an&lt;br&gt;
  A2A weather agent, I have to write a custom integration. For every single agent.&lt;/p&gt;

&lt;p&gt;This is the same fragmentation problem the web faced before TCP/IP. Everyone's speaking different&lt;br&gt;
   protocols.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nexarion sits between MCP clients and A2A agents as a translation runtime:&lt;/p&gt;

&lt;p&gt;MCP CLIENTS (Claude, Cursor, VS Code)&lt;br&gt;
          │&lt;br&gt;
          │ tools/list, tools/call (stdio or HTTP)&lt;br&gt;
          ▼&lt;br&gt;
  NEXARION RUNTIME&lt;br&gt;
    ┌─ Discovery: Agent Cards, caching, validation&lt;br&gt;
    ├─ Translation: MCP ↔ A2A, schema mapping&lt;br&gt;
    └─ Routing: Auth passthrough, rate limiting&lt;br&gt;
          │&lt;br&gt;
          │ message/send, task/submit (JSON-RPC or REST)&lt;br&gt;
          ▼&lt;br&gt;
  A2A AGENTS (Weather, Code, Research, Custom)&lt;/p&gt;

&lt;p&gt;Three layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Discovery Layer fetches /.well-known/agent-card.json from A2A agents. Caches results with&lt;br&gt;
configurable TTL. Validates cards against a schema to catch malformed responses early.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Translation Layer converts A2A agent skills into MCP tools with dynamically generated&lt;br&gt;
inputSchema. Each skill's description and tags become the tool's metadata. A generic send_message&lt;br&gt;
tool is also generated for every agent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Routing Layer resolves MCP tool names back to agent endpoints. Handles auth passthrough from&lt;br&gt;
MCP OAuth to A2A bearer tokens. Supports both JSON-RPC (A2A native) and REST/ACP (lighter&lt;br&gt;
weight).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Killer Feature: Dynamic Tool Synthesis&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is what makes the bridge feel like magic:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  1. A2A agent detected at https://weather.agent.ai
  2. GET /.well-known/agent-card.json
  3. Agent Card parsed, skills extracted
  4. Each skill auto-converted to MCP tool with inputSchema
  5. Instantly usable in Claude Desktop, Cursor, VS Code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;No configuration. No manual mapping. Just discover and use.&lt;/p&gt;

&lt;p&gt;A single tools/list call shows every A2A agent as if it's a local MCP server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Protocol Mapping&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The translation is straightforward but non-trivial:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  tools/list fetches Agent Card from /.well-known/agent-card.json
  tools/call(name, args) converts to JSON-RPC message/send
  Tool inputSchema maps to skill description and tags
  Text response extracted from message.parts[].text
  Tool error mapped from status.state = failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tricky part was handling SSE streaming. A2A agents can stream partial results via Server-Sent&lt;br&gt;
   Events, but MCP expects a single JSON response. The streaming adapter buffers SSE events and&lt;br&gt;
  converts them into MCP progress notifications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plugin System&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The bridge supports four middleware hooks:&lt;/p&gt;

&lt;p&gt;beforeTranslate to intercept MCP to A2A translation&lt;br&gt;
  afterTranslate to intercept A2A to MCP translation&lt;br&gt;
  onDiscover to intercept agent discovery&lt;br&gt;
  onError to intercept bridge errors&lt;/p&gt;

&lt;p&gt;This means you can add logging, rate limiting, custom auth, or any transformation without&lt;br&gt;
  touching core code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Agent Cards are inconsistent. Every A2A agent formats their card slightly differently. Some&lt;br&gt;
have capabilities, some don't. Some use endpoints.rest, some only endpoints.jsonRpc. Schema&lt;br&gt;
validation at the discovery layer is not optional. It's essential.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stdio transport is a double-edged sword. Claude Desktop communicates via stdin/stdout. This is&lt;br&gt;
elegant but fragile. A single console.log in the wrong place breaks JSON-RPC parsing. Every log&lt;br&gt;
message must go to stderr.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HMAC token signing is table stakes. If you're bridging two auth systems, you need&lt;br&gt;
cryptographic verification. Base64 encoding a secret isn't enough. Discovered that one the hard&lt;br&gt;
way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rate limiting needs to be everywhere. The bridge, the HTTP server, per-agent, per-client. We&lt;br&gt;
hit our own npm publish rate limit 5 times during development.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The timing is right. MCP and A2A are both growing fast. MCP has 35+ active specification&lt;br&gt;
proposals. A2A has 23K+ GitHub stars. A bridge between them is inevitable. I just built it first.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Stack and Numbers&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; TypeScript (strict mode), pnpm monorepo, tsup build&lt;/li&gt;
&lt;li&gt;  8 packages: core, server, cli, sdk, registry, web, vscode&lt;/li&gt;
&lt;li&gt;  102 tests, 0 build warnings&lt;/li&gt;
&lt;li&gt;  Apache-2.0 license&lt;/li&gt;
&lt;li&gt;  5 npm packages published&lt;/li&gt;
&lt;li&gt;  Docker support with healthcheck&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/vahapogut/nexarion" rel="noopener noreferrer"&gt;https://github.com/vahapogut/nexarion&lt;/a&gt;&lt;br&gt;
  &lt;code&gt;npm: nexarion-core, nexarion-server, nexarioncli, nexarion-sdk, nexarion-registry&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you're building MCP servers or A2A agents, I'd love to hear how you're handling the interoperability question. Is this bridge a stopgap, or is it a long-term piece of the ecosystem?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>typescript</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
