List the MCP servers and A2A agents a key may use
DVARA, the AI governance platform, already knows which MCP servers and A2A agents each workspace may use. Clients still had to be told by hand. DVARA can now answer that question in two standard shapes:
- the MCP Registry API (
v0.1), which MCP hosts read to find servers, and - an Agentic Resource Discovery (ARD) manifest, a list of agents that any ARD reader understands.
Each answer is built for the key that asks. It lists only what that key may use, in its own workspace, and every address in it is DVARA's. Upstream addresses, credentials and owners are never in it.
Not included in DVARA Open Source.
Both endpoints are off by default. The MCP Registry API is still a preview, and ARD is a proposal (v0.91), so the shapes may change. Turn them on to try them; do not build on them yet.
Turn them on
Set these on the gateway and restart it.
| Setting | Environment variable | Default | What it does |
|---|---|---|---|
dvara.mcp-gateway.discovery.enabled | DVARA_MCPGATEWAY_DISCOVERY_ENABLED | false | Serve the MCP Registry API at /mcp/v0.1/servers |
dvara.mcp-gateway.discovery.namespace | DVARA_MCPGATEWAY_DISCOVERY_NAMESPACE | local.dvara | The first part of every server name, in reverse DNS of a domain you own, such as com.acme.dvara |
a2a.discovery.ard.enabled | A2A_DISCOVERY_ARD_ENABLED | false | Serve the ARD manifest at /a2a/.well-known/ard.json |
a2a.discovery.ard.publisher | A2A_DISCOVERY_ARD_PUBLISHER | dvara.local | The domain in every agent's identifier, such as agents.acme.com |
While a setting is off, its endpoint answers 404.
List MCP servers
curl --silent https://<dvara-host>/mcp/v0.1/servers \
--header 'Authorization: Bearer <your-api-key>'
{
"servers": [
{
"server": {
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "com.acme.dvara/github",
"title": "github-mcp-server",
"description": "MCP server github, governed by the DVARA gateway",
"version": "1.4.2",
"remotes": [
{
"type": "streamable-http",
"url": "https://<dvara-host>/mcp/github",
"headers": [
{
"name": "Authorization",
"value": "Bearer {dvara_credential}",
"isRequired": true,
"isSecret": true
}
]
}
]
},
"_meta": {
"io.modelcontextprotocol.registry/official": { "status": "active", "isLatest": true },
"com.dvarahq/gateway": {
"serverId": "github",
"workspaceUrl": "https://<dvara-host>/mcp",
"toolPrefix": "github__",
"tools": ["create_issue", "search"]
}
}
}
],
"metadata": { "count": 1 }
}
- Which servers. The active servers registered in your key's workspace. A suspended, disabled or quarantined server is not listed, because it cannot be called.
- Where to connect. Each entry points at that server's own
address on DVARA,
/mcp/<server>. Connect there to use just that server: you see only its tools, prompts and resources, with their own names. See Connect to one server.workspaceUrlis the workspace's/mcp, where every server's tools are, each named<server>__<tool>(toolPrefix). - Version. The version the server reported when DVARA last synced it, or
0.0.0if it reported none. - Paging and filters.
limit(up to 100),cursor(frommetadata.nextCursor),search(part of the name) andversion.
Read one server by name, with the slash between the two parts written as a plain slash:
curl --silent https://<dvara-host>/mcp/v0.1/servers/com.acme.dvara/github/versions/latest \
--header 'Authorization: Bearer <your-api-key>'
The MCP Registry API asks clients to encode that slash as %2F. DVARA's web
server refuses an encoded slash in a path, so that form answers 400. Listing
is not affected.
Connect to one server
Every registered MCP server has its own address on DVARA,
https://<dvara-host>/mcp/<server-id>, with the same API key or access token
as /mcp. It works with MCP 2025-06-18, 2025-11-25 and 2026-07-28.
curl --silent https://<dvara-host>/mcp/github \
--header 'Authorization: Bearer <your-api-key>' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json, text/event-stream' \
--header 'MCP-Protocol-Version: 2025-11-25' \
--data '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
The tools come back as the server names them, such as create_issue, and you
call them by those names. Every call is checked exactly as on /mcp: the same
policies, approvals, scans, limits and audit record. The audit record names the
server and the tool, as before.
- A server that is not an active server of your key's workspace answers
404, like a server that does not exist. Nothing is sent to any server. X-Dvara-Virtual-Serveris refused there (400): the address already names one server. Use/mcpfor a virtual server.- An OAuth access token must still be issued for DVARA's MCP resource (the
/mcpaddress), not for a server's own address. - A server whose id holds a slash has no address of its own; its entry points at
/mcp.
List A2A agents
curl --silent https://<dvara-host>/a2a/.well-known/ard.json \
--header 'Authorization: Bearer <your-api-key>'
{
"entries": [
{
"identifier": "urn:air:agents.acme.com:<workspace-id>:planner",
"displayName": "Trip Planner",
"type": "application/a2a-agent-card+json",
"url": "https://<dvara-host>/a2a/planner/.well-known/agent-card.json",
"description": "Plans trips",
"version": "2.1.0",
"capabilities": ["plan"],
"tags": ["travel"],
"metadata": { "dvara.agentId": "planner", "dvara.cardTrustState": "VERIFIED" }
}
]
}
- Which agents. The active agents registered in your key's workspace.
- The card.
urlis the Agent Card DVARA serves for the agent, governed for your key, never the peer's own address. - Skills.
capabilitieslists only the skills your workspace allows for the agent. - Trust.
dvara.cardTrustStateis what DVARA found when it checked the card's signature:VERIFIED,SELF_SIGNED,UNSIGNEDorINVALID.
DVARA serves a manifest, not an ARD registry: it has no search.
Who can see what
- Both endpoints take the same key as
/mcpand/a2a. On the MCP endpoint an OAuth access token works too, when OAuth is on. - A key with no scopes sees everything its workspace may use. A key with scopes
needs
mcp:readormcp:callto list MCP servers, anda2a:readora2a:sendto list agents. Otherwise the answer is403. - A missing or revoked key is
401. A suspended workspace is403. - No answer ever includes another workspace's servers or agents.
- Answers are private to the caller and never cached by a proxy
(
Cache-Control: private, no-store).
Listing an agent does not approve a call to it. Every call still goes through the workspace's policies, approvals and audit.