MCP Gateway API
Use the MCP Gateway API when an agent needs governed access to registered tool servers. DVARA applies workspace policy, PII controls, approvals, loop detection, budgets, and audit before and after the upstream call.
Not included in DVARA Open Source.
Choose the endpoint your client supports
| Endpoint | Contract | Use it for |
|---|---|---|
POST /mcp | MCP JSON-RPC over Streamable HTTP | Native MCP clients; initialize, ping, server/discover, tools/*, resources/list, resources/templates/list, resources/read, prompts/*, completion/complete, tasks/get, tasks/update, tasks/cancel (there is no tasks/list), and (on 2026-07-28) subscriptions/listen |
POST /mcp/{serverId} | MCP JSON-RPC over Streamable HTTP | A native MCP client that should see one governed server only, under that server's own tool, prompt and resource names |
POST /mcp/{serverId}/tools/list | JSON request and response | List one registered server's tools |
POST /mcp/{serverId}/tools/call | JSON request and response | Call one registered server's tool |
POST /mcp/{serverId}/server/discover | JSON request and response | Read one server's advertised capabilities |
POST /mcp/{serverId}/resources/{path} | JSON request and response | Use resource operations on the server-scoped bridge |
POST /mcp/{serverId}/prompts/{path} | JSON request and response | Use prompt operations on the server-scoped bridge |
GET /mcp/v0.1/servers | MCP Registry API (v0.1), read only | List the MCP servers the key may use. Off by default; turn it on with dvara.mcp-gateway.discovery.enabled. See List the MCP servers and A2A agents a key may use |
GET /mcp/v0.1/servers/{namespace}/{name}/versions and .../versions/{version} | MCP Registry API (v0.1), read only | Read one listed server's versions, or one version such as latest. Off by default, like the list |
GET /.well-known/oauth-protected-resource/mcp | OAuth protected-resource metadata | Discover the configured resource, authorization servers, and scopes |
POST /v1/webhooks/actions/{action}?token=... | Signed approval callback | Approve or deny a held MCP tool call from a webhook action |
The native endpoint serves tools, resources, prompts and completions across the workspace's servers. It keeps no session between requests. The server-scoped paths remain for direct calls to one server.
On the server-scoped bridge, the wildcard suffix becomes the MCP operation:
resources/list, resources/read, prompts/list, or prompts/get. Send that
operation's parameter object as the request body. Resource and prompt bridges
work for servers registered with the REST, STREAMABLE_HTTP, SSE or STDIO
transport. A native MCP server must declare the resources or prompts
feature when it starts a session, or the call is refused. A REST_BRIDGE
server supports only tools/list and tools/call.
Authenticate the call
Send a DVARA workspace API key as a bearer token. When OAuth is enabled, the native and server-scoped endpoints also accept an OAuth access token; API keys remain enabled by default. See Authenticate MCP clients with OAuth 2.1.
| Credential | Read operations | Call operations |
|---|---|---|
| Scoped API key | mcp:read for tool listing, discovery, resources, prompts, completions and subscriptions/listen | mcp:call for tools/call and tasks/get, tasks/update, tasks/cancel |
| OAuth access token | mcp:read | mcp:call |
An unscoped API key remains unrestricted. An OAuth token with no scopes is not unrestricted. The approval callback does not take either credential; the signed, expiring token in the webhook action URL is its credential.
Discover OAuth authorization servers
When MCP OAuth is enabled, both
/.well-known/oauth-protected-resource/mcp and
/.well-known/oauth-protected-resource return RFC 9728 metadata. The document
names the canonical resource URI, authorization servers, supported scopes, and
the bearer-header method. These paths return 404 while OAuth is off.
An invalid or missing OAuth credential returns 401 with a
WWW-Authenticate challenge pointing to this metadata. See Authenticate MCP
clients with OAuth 2.1 for issuer, audience,
workspace, PKCE, and client-registration checks.
List the tools in a workspace
Replace the host and credential before running this request:
curl --silent https://<dvara-host>/mcp \
--header 'Authorization: Bearer <your-credential>' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json, text/event-stream' \
--data '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}'
A workspace with one support server receives namespaced tool names:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "support__search_articles",
"description": "Search approved customer-support articles",
"inputSchema": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"]
}
}
]
}
}
Open MCP → Tool Calls (platform roles) or Agents → MCP Tool Calls
(workspace roles) to inspect calls. Tool calls, server/discover and
server-scoped tool listing write MCP events to Governance → Audit. A native
tools/list is not audited.
Complete an approval callback
When a webhook receives an MCP approval request, use the complete action URL from that event. Do not construct or modify its token.
curl --silent --request POST \
'https://<dvara-host>/v1/webhooks/actions/approve?token=<signed-approval-token>'
{
"status": "accepted",
"action": "approve"
}
Use deny instead of approve to refuse the held call. A workspace webhook
can decide only a pending approval from its own workspace; a platform webhook
can decide any approval it receives. An invalid or expired token, a
cross-workspace token, or a workspace webhook's token for an approval that is
no longer pending all return the same 400 response, so the callback does not
reveal whether another approval exists. A platform webhook's valid token is
accepted with 200 even when the approval was already decided.
A native tools/call that includes _meta.progressToken receives progress
notifications while it waits for review and the final result as the last SSE
event. A call without that token, and every server-scoped REST call, waits for
the final decision without progress events.
Handle authentication and size failures
A missing or invalid credential returns 401. An OAuth token without the
required scope returns 403; an API key restricted away from the operation is
also refused before the upstream runs.
The native endpoint limits the complete HTTP request body with
dvara.mcp-gateway.limits.max-request-bytes. From 1.8.6 the default is 4 MiB.
This is separate from the 1 MiB default limit applied to serialized tool
arguments. A declared or chunked request over the body limit receives a bare
413 before JSON-RPC processing. Authentication runs first, so an invalid
credential still gets 401 without its body being read.
The outer limit applies only to the native endpoints (POST /mcp and
POST /mcp/{serverId}), not the server-scoped REST paths. 0 or less disables it. Because it bounds the whole native request, a
workspace argument limit above 4 MiB has no effect there unless the operator
also raises the outer limit.
Plan for deprecated MCP behavior
The native endpoint serves MCP revisions 2026-07-28 (stateless, no
initialize), 2025-11-25 and 2025-06-18. initialize echoes a requested
handshake revision. For any other requested version it answers with
2025-11-25, and the client decides whether to continue. A request that names
an unsupported version in the MCP-Protocol-Version header or in _meta is
refused with UnsupportedProtocolVersionError. The endpoint does not
offer Roots, Sampling, or Logging. Uses of those deprecated features are
refused or ignored as the protocol requires, logged, and recorded as
MCP_DEPRECATED_FEATURE_USED at most once a day per workspace, client, feature
and use, on each gateway pod.
On MCP 2026-07-28 a tool server can still ask for a model call as an input
request inside a tool result. The Gateway never passes that request to your
application: it refuses it, or, if the workspace chooses, makes the call itself
through the LLM Gateway. See Govern model calls that MCP tools ask
for.
Dynamic Client Registration is accepted by default but marked deprecated. Use an OAuth client allow-list, require Client ID Metadata Documents, or set the dynamic-registration sunset described in the OAuth guide.
The legacy HTTP+SSE transport is an upstream-server setting, not a transport
served at /mcp. By default it is refused from 28 July 2027 (UTC), a date set
by dvara.mcp-gateway.legacy-sse-sunset. From the configured sunset, calls to a server that still uses it return
410 mcp_transport_sunset; move those servers to Streamable HTTP.
For policy, PII, approvals, sessions, transports, and detailed JSON-RPC errors, continue with Govern tool calls with the MCP Gateway.