Skip to main content
Glama
joltedbot

a2a-bridge

by joltedbot

A2A Bridge — Bidirectional Multi-Agent Communication

Two companion servers enabling full bidirectional A2A communication between AI coding agents:

  • a2a-bridge (MCP server) — Outbound: Claude Code/Gemini/OpenCode reach A2A agents

  • a2a-server (HTTP server) — Inbound: A2A agents reach Claude Code

Architecture

                    Outbound (MCP bridge)
Claude Code ─┐
Gemini CLI  ─┤─ MCP (stdio) ─► a2a-bridge ─► Elastic Agent Builder
OpenCode    ─┘                              ─► Gemini CLI A2A Server
                                            ─► Any standard A2A agent

                    Inbound (A2A server)
Gemini CLI  ──A2A──► a2a-server (HTTP :3008) ──subprocess──► claude -p
Other agents         /.well-known/agent-card.json

Related MCP server: agent-network

Tools

Tool

Description

list_agents

List all agents across all configured providers

get_agent_card

Get an agent's A2A card (capabilities, skills, metadata)

send_message

Send a message to an agent via A2A and get a response

Agent IDs use compound format: provider/agentId (e.g., elastic/dev_assistant, gemini-local/default). Bare IDs auto-resolve when only one provider is configured.

Prerequisites

  • Node.js 18+

  • At least one A2A-compatible agent endpoint (Elastic Agent Builder, Gemini CLI A2A server, etc.)

Quick Start

Initial Setup (One-Time)

  1. Clone and install:

git clone <repo-url>
cd native-api
npm install
npm run build
  1. Create a .env file (sole source of truth for all credentials):

# For Elastic provider
KIBANA_URL=https://your-deployment.kb.elastic-cloud.com
ELASTIC_API_KEY=your-api-key

# Optional: For Gemini or other A2A servers
# MY_AGENT_TOKEN=your-token-here
  1. (Optional) Create agents.json for multi-provider setup:

cp agents.json.example agents.json
# Edit agents.json to add your providers

Without agents.json, the system auto-creates an Elastic provider from .env variables.

Running Bidirectional A2A (Three Terminals)

Open three terminal windows and run these commands in parallel:

Terminal 1 — Claude Code A2A Server (receives messages from Gemini):

npm run serve
# Output: "A2A server listening on http://127.0.0.1:3008"

Terminal 2 — Gemini CLI A2A Server (receives messages from Claude):

npm run gemini-a2a
# Output: "A2A server listening on port 41965"

Terminal 3 — Claude Code or Gemini CLI for testing:

# In Claude Code, use the MCP bridge:
# List the available A2A agents
# Ask the gemini-local/default agent to [task]

# Or from Gemini CLI:
# /agents list
# /ask claude-code "do something"

Claude Code Integration

Open the project in Claude Code. The .mcp.json auto-starts the MCP bridge:

  1. Verify the server: /mcp — you should see a2a-bridge listed

  2. Try: "List the available A2A agents" → should show agents including gemini-local/default

  3. Try: "Ask the gemini-local/default agent to list files in the current directory"

Gemini CLI Integration

Configure Gemini to discover Claude Code as an A2A agent:

  1. Copy the agent config:

    mkdir -p ~/.gemini/agents
    cp examples/gemini-agents/claude-code.md ~/.gemini/agents/
  2. Verify: /agents list in Gemini CLI should show claude-code

  3. Try: /ask claude-code "list my open files"

Usage

Outbound (MCP bridge — npm start)

> List the available A2A agents
> Get the agent card for elastic/dev_assistant
> Ask the elastic/dev_assistant agent to list the available indices
> Send a message to gemini-local/default asking it to summarize this file

Inbound (A2A server — npm run serve)

Start the A2A server to let other agents talk to Claude Code:

npm run serve

This exposes Claude Code at http://localhost:3008 with a standard A2A agent card. Gemini CLI (or any A2A client) can discover and message it. See Bidirectional Demo for a full walkthrough.

Configuration

Credentials (.env)

.env is the single source of truth for all secrets. Never put credentials in agents.json or .mcp.json.

KIBANA_URL=https://your-deployment.kb.elastic-cloud.com
ELASTIC_API_KEY=your-api-key
MY_AGENT_TOKEN=your-token-here

Provider Registry (agents.json)

agents.json defines which A2A providers to connect to. It references env var names for secrets — never raw values. This file is safe to commit.

{
  "providers": [
    {
      "type": "elastic",
      "name": "elastic",
      "baseUrl": "${KIBANA_URL}",
      "auth": {
        "scheme": "api-key",
        "envVar": "ELASTIC_API_KEY",
        "headers": { "kbn-xsrf": "true" }
      }
    },
    {
      "type": "a2a",
      "name": "gemini-local",
      "baseUrl": "http://localhost:41965",
      "auth": { "scheme": "none" }
    },
    {
      "type": "a2a",
      "name": "my-remote-agent",
      "baseUrl": "https://agent.example.com",
      "auth": {
        "scheme": "bearer",
        "envVar": "MY_AGENT_TOKEN"
      }
    }
  ]
}

Provider types:

  • elastic — Elastic Agent Builder (Kibana-specific endpoints and auth)

  • a2a — Standard A2A agent (well-known discovery at /.well-known/agent-card.json)

Auth schemes:

  • api-keyAuthorization: ApiKey <value> header

  • bearerAuthorization: Bearer <value> header

  • header — Custom static headers only

  • none — No authentication (local agents)

Backward Compatibility

If no agents.json exists, the server auto-creates an Elastic provider from KIBANA_URL and ELASTIC_API_KEY environment variables. Existing setups work without changes.

MCP Config (.mcp.json)

{
  "mcpServers": {
    "a2a-bridge": {
      "command": "node",
      "args": ["--env-file=.env", "dist/index.js"]
    }
  }
}

Using in Other Clients

See the docs/ directory for client-specific setup guides:

User-level MCP config (Claude Code)

Register the server once for all Claude Code sessions:

claude mcp add --scope user a2a-bridge node -- --env-file=/path/to/project/.env /path/to/project/dist/index.js

A2A Protocol Details

  • Standard A2A: Discovery via /.well-known/agent-card.json, messaging via POST with JSON-RPC 2.0 message/send

  • Elastic A2A: Agent card at /api/agent_builder/a2a/{id}.json, messaging at /api/agent_builder/a2a/{id}

  • Part format: kind: "text" discriminator (A2A v0.3+)

  • Streaming: Not currently supported

Security

  • .env is the sole credential store (gitignored, 600 permissions)

  • HTTPS enforced for all non-localhost URLs

  • Agent ID validation: [a-zA-Z0-9_.-]{1,128} per segment

  • 30s request timeout, 32KB message size limit

  • Error sanitization: internal details logged to stderr only

Related MCP Connectors

Related MCP Servers