DocsMCP gateway
MCP gateway errors
How the MCP gateway refuses a call: tool results with isError for the model to read, HTTP errors before any MCP message, and JSON-RPC protocol errors.
INFRO is in private early access. Running these examples requires an early-access account, an active trial or subscription entitlement, and your own provider connection. Self-serve purchasing is not generally open. See Early access.
The MCP gateway is served at https://mcp.infro.io/gateway/mcp and https://mcp.infro.io/gateway/<slug>/mcp, on the Business plan and above.
A refusal reaches the agent in one of three ways, depending on when it happens.
Tool errors
Once the key is authenticated and the tool is known, a refusal is a tool result with isError: true, which the MCP specification intends for the model to read and adapt to. It carries a text block with the message and structuredContent.error with type, code and message, in the shape of INFRO's error envelope. Messages say what to do next; they never describe other teams' servers or tools.
{
"jsonrpc": "2.0",
"id": 7,
"result": {
"isError": true,
"content": [
{
"type": "text",
"text": "`github_create_issue` changed on its server after it was approved, so INFRO is refusing it. Ask an admin to review the change and approve it again in INFRO, under MCP & connectors. Do not retry until then."
}
],
"structuredContent": {
"error": {
"type": "permission_denied",
"code": "tool_definition_changed",
"message": "`github_create_issue` changed on its server after it was approved, so INFRO is refusing it. Ask an admin to review the change and approve it again in INFRO, under MCP & connectors. Do not retry until then."
}
}
}
}code | type | When | Reached the server? |
|---|---|---|---|
tool_not_allowed | permission_denied | The key's grant does not allow the tool: no grant on the tool's server, a write tool under a read grant, or a tool not named in a selected grant. | No |
tool_not_approved | permission_denied | The tool is pending, blocked or removed. | No |
tool_definition_changed | permission_denied | The server changed the tool's definition after it was approved. Do not retry until an admin approves it again. | No |
invalid_tool_arguments | invalid_request_error | The arguments do not match the approved inputSchema (the message names the path), exceed 256 KB, or need a network $ref. | No |
guardrail_blocked | permission_denied | A guardrail block rule matched the arguments (input) or the result (output). The message names the detector, never the matched text. | No for input; yes for output |
guardrail_unavailable | permission_denied | The guardrail engine failed and the policy says on_engine_error: block. | Depends on the stage |
tool_result_too_large | upstream_error | The result is larger than the server's result limit. Ask for less. | Yes |
tool_result_invalid | upstream_error | The result's structuredContent does not match the approved outputSchema. The result was withheld. | Yes |
upstream_unavailable | upstream_error | The network failed; the server answered 5xx, a redirect or something that is not MCP; it refused the credential INFRO holds for it (401 or 403: an admin must replace the credential); or it rate-limited that credential (429). The message says which, cleaned of credentials. | Attempted |
upstream_timeout | request_timeout | The server's time limit passed. | Yes |
upstream_rejected | upstream_error | The server answered the call with a JSON-RPC protocol error, for example because it no longer knows the tool or refused the arguments itself. Its message, cleaned, is passed on. | Yes |
A result the server itself marked isError: true is not a gateway refusal: it reaches the agent unchanged, with credential-shaped text removed.
HTTP errors
These are answered before any MCP message is processed, in INFRO's usual error envelope.
| Status | code | When |
|---|---|---|
| 401 | — | Missing, unknown, expired or revoked gateway key. The response carries WWW-Authenticate: Bearer. |
| 403 | ip_not_allowed | The key has an IP allowlist and the request came from elsewhere. |
| 403 | key_disabled | The key is turned off. |
| 403 | organization_suspended | An operator hold is on the organization. |
| 403 | project_archived | The key's project is archived. |
| 403 | plan_feature | The organization's plan does not include the MCP gateway (from Business). |
| 403 | subscription_required | The organization has no active subscription or trial. |
| 404 | mcp_server_not_found | The per-server path's slug is unknown, disabled, outside the key's projects or environments, or not granted to the key. The answer is the same in every case. Type not_found. |
| 400 | invalid_attribution | A malformed X-INFRO-* attribution header or ?trace_id=. |
| 429 | — | The key's rate limit, shared with its model calls. Retry-After says when to retry. |
| 429 | mcp_server_rate_limited | The server's own limit, across every key. Retry-After says when to retry. |
| 405 | — | Anything but POST. |
Protocol errors
| JSON-RPC code | When |
|---|---|
-32602 | On the aggregated endpoint, a tools/call naming a tool that does not exist in the organization ("Unknown tool"). On the per-server endpoint, the same for a name the server does not have. |
-32020 | With HTTP 400: the request's Mcp-Method or Mcp-Name header disagrees with its body. |
-32700 | With HTTP 400: the body is not JSON. |
Retrying
- Retry
upstream_unavailable,upstream_timeoutand both429s with backoff; on a429, wait forRetry-After. Anupstream_unavailablewhose message says the server refused INFRO's credential needs an admin instead. - Do not retry
tool_not_allowed,tool_not_approved,tool_definition_changed,guardrail_blocked,401,403or404: they need an admin or a configuration change. - After
invalid_tool_argumentsortool_result_too_large, change the arguments before calling again.
Configuration errors
Registering and changing servers, tools and grants, in the console or the management API, can return 400 with these codes:
code | When |
|---|---|
invalid_mcp_server_url | The URL is not public HTTPS, carries a user name, password or fragment, points at a private address or at INFRO. |
invalid_mcp_credential | A credential header name is invalid or reserved, or there are too many headers. |
mcp_discovery_failed | The server did not answer tools/list with the credential given. |
mcp_server_slug_taken | Another server in the organization has this slug. |
mcp_tool_name_clash | Two tools would get the same exposed name; the message lists them. |
mcp_tool_definition_stale | The definition changed since the hash you approved (expected_sha256). Review it again. |
mcp_tool_removed | The server no longer lists the tool, so there is nothing to approve. |
mcp_tool_not_approved | A class can be set only on an approved tool. |
mcp_trifecta_unconfirmed | The grant would give one key private data, untrusted content and a way to send data out. Repeat it with confirm_trifecta: true if that is intended. |
key_revoked | A grant names a revoked key. |