Skip to main content
Glama

vscode-a2a

An MCP bridge that exposes A2A agents as tools in VS Code agent chat (GitHub Copilot, etc.).

Reads an a2a.json config, discovers each agent's card via .well-known/agent-card.json, and registers one MCP tool per agent. The LLM picks which agent to delegate to — multi-turn conversation is maintained automatically.

Compatible with A2A protocolVersion 0.3.0 and 1.0, JSONRPC and REST transports, and SSE streaming.

Debug Logging

vscode-a2a supports leveled debug logging through environment variables in mcp.json.

  • A2A_DEBUG_LEVEL: integer 0 to 5

Level guide:

  1. High-level flow (discovery-start, request-mode, fallback success/error)

  2. Request/response summaries (http-request, http-response, stream start/end)

  3. Payload summaries and collected text

  4. Event-shape diagnostics and SSE preview

  5. Full raw event and buffer-churn logs (most verbose)

Example:

"vscode-a2a": {
  "command": "node",
  "args": ["${workspaceFolder}/vscode-a2a/dist/index.js"],
  "type": "stdio",
  "env": {
    "A2A_DEBUG_LEVEL": "1"
  }
}

Related MCP server: A2A MCP

Installation

Add to your .vscode/mcp.json:

{
  "servers": {
    "vscode-a2a": {
      "command": "npx",
      "args": ["-y", "vscode-a2a"],
      "type": "stdio",
      "env": {
        "MY_AGENT_TOKEN": "${input:myAgentToken}"
      }
    }
  },
  "inputs": [
    {
      "id": "myAgentToken",
      "type": "promptString",
      "description": "Bearer token for your A2A agents",
      "password": true
    }
  ]
}

From source

git clone https://github.com/kranthikirang/vscode-a2a
cd vscode-a2a && npm install && npm run build

Then point mcp.json at the built output:

"vscode-a2a": {
  "command": "node",
  "args": ["/path/to/vscode-a2a/dist/index.js"],
  "type": "stdio"
}

Configuration — a2a.json

Place .vscode/a2a.json (or a2a.json at project root) alongside your mcp.json. The bridge hot-reloads on save.

{
  "agents": {
    "my-agent": {
      "url": "https://example.com/my-agent/",
      // optional: override card discovery path or provide full card URL
      "cardPath": ".well-known/agent-card.json"
    }
  }
}

Agent card discovery

If cardPath is omitted the bridge tries in order:

  1. {url}/.well-known/agent-card.json

  2. {url}/.well-known/agent.json

If neither is reachable the agent is skipped (logged to stderr) and the bridge continues.

Authentication

All secret values support ${env:VAR_NAME} substitution — the variable is read from the process env injected by mcp.json.

az_cli — delegated user identity (recommended for developers)

No secrets required. Uses the user's existing az login session. The token carries the user's actual roles and groups, refreshes automatically.

// Shortest form — az_cli is the implicit default when no auth is specified
{
  "agents": {
    "my-agent": {
      "url": "https://my-gateway.example.com/agw/my-agent/",
      "resource": "api://your-azure-ad-app-client-id"
    }
  }
}
// Explicit form — same result, useful when mixing auth types across agents
"auth": {
  "type": "az_cli",
  "resource": "api://your-azure-ad-app-client-id"
}

resource is the Azure AD application (client) ID prefixed with api://. When omitted, the bridge attempts to discover it from the agent card's securitySchemes.

Prerequisite: az login must have been run at least once. VS Code terminals inherit this session automatically.

Bearer token

"auth": {
  "type": "bearer",
  "token": "${env:MY_AGENT_TOKEN}"
}

Pass the token via mcp.json env:

// .vscode/mcp.json
"env": { "MY_AGENT_TOKEN": "${input:myAgentToken}" }

API key

"auth": {
  "type": "apikey",
  "key": "${env:MY_API_KEY}",
  "header": "X-API-Key"   // optional, default: X-API-Key
}

OAuth2 client credentials (M2M / service principal)

"auth": {
  "type": "oauth2",
  "clientId": "your-client-id",
  "clientSecret": "${env:MY_CLIENT_SECRET}",
  "tokenUrl": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",
  "scopes": ["api://your-app-id/.default"]
}

Tokens are cached and refreshed automatically 60 s before expiry.

Full example — multiple agents, different auth per agent

// .vscode/a2a.json
{
  "agents": {
    // az_cli shorthand — uses developer's `az login` session
    "prometheus-agent": {
      "url": "https://my-gateway.example.com/agw/prometheus-agent/",
      "resource": "api://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    },

    // Same app registration, different agent — each gets its own resource
    "k8s-agent": {
      "url": "https://my-gateway.example.com/agw/k8s-agent/",
      "resource": "api://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    },

    // Different app registration (different environment or org)
    "external-agent": {
      "url": "https://partner.example.com/agw/external/",
      "resource": "api://a1b2c3d4-0000-0000-0000-000000000000"
    },

    // M2M service principal (CI/CD, automation)
    "ci-agent": {
      "url": "https://my-gateway.example.com/agw/ci-agent/",
      "auth": {
        "type": "oauth2",
        "clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "clientSecret": "${env:CI_CLIENT_SECRET}",
        "tokenUrl": "https://login.microsoftonline.com/tenant-id/oauth2/v2.0/token",
        "scopes": ["api://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/.default"]
      }
    },

    // Static bearer token (non-Azure endpoints)
    "third-party-agent": {
      "url": "https://api.thirdparty.example.com/agent/",
      "auth": {
        "type": "bearer",
        "token": "${env:THIRD_PARTY_TOKEN}"
      }
    },

    // API key authentication
    "api-key-agent": {
      "url": "https://api.example.com/agent/",
      "auth": {
        "type": "apikey",
        "key": "${env:AGENT_API_KEY}",
        "header": "X-API-Key"
      }
    }
  }
}

How it works

a2a.json → discover .well-known/agent-card.json
         → register one MCP tool per agent (name + all skills in description)
         → LLM calls tool with { message, start_fresh? }
         → bridge sends A2A message/stream to agent
         → collects streamed artifacts → returns final text to LLM
         → preserves task ID for multi-turn (input-required state)

Stream fallback behavior

For some upstreams, the SDK streaming call can return 200 text/event-stream with zero emitted events. When that happens, the bridge automatically tries fallback paths:

  1. SDK non-stream (sendMessage)

  2. Raw legacy JSON-RPC stream (message/stream) with legacy payload shape

  3. Raw legacy JSON-RPC non-stream (message/send) as last fallback

This keeps normal SDK behavior as primary, while recovering text from upstreams that only respond reliably to legacy stream payloads.

Multi-turn

The bridge keeps the same A2A contextId per agent for the lifetime of the MCP process. When an agent enters input-required state, the bridge returns the agent's question to the LLM; the next tool call continues the same task. Pass start_fresh: true to start a new context.

Live reload

Saving a2a.json triggers agent re-discovery and sends notifications/tools/list_changed to VS Code so new agents appear immediately without restarting.

Versioning

This package follows semver. To cut a release:

npm version patch   # 0.1.0 → 0.1.1  (bug fixes)
npm version minor   # 0.1.0 → 0.2.0  (new features, backwards-compatible)
npm version major   # 0.1.0 → 1.0.0  (breaking changes)
npm publish

npm version bumps package.json, commits, and creates a git tag automatically. prepublishOnly runs npm run build before every publish.

License

Apache-2.0

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to access live VS Code editor state, symbol navigation, diagnostics, and language-aware editing through MCP, bridging the gap between what the agent can infer from disk and what the editor actually knows.
    MIT