Inferventis MCP server returns bare HTTP 401 on tools/call — auth middleware breaks MCP transport contract
Surface: mcp.ai-bankee-inferventis-mcp (Inferventis MCP Server v1.0.2) Endpoint: https://mcp-server-295985738387.europe-west1.run.app/mcp Transport: streamable-http Registry: modelcontextprotocol (ai.bankee/inferventis-mcp)
The bug
The server's auth middleware lets initialize, notifications/initialized, and tools/list through without credentials — so an agent discovers all 20 tools. But every other MCP method (tools/call, resources/list, prompts/list, even unknown methods) returns HTTP 401 with bare JSON instead of a proper MCP error:
What the server returns:
HTTP/2 401
Content-Type: application/json; charset=utf-8
{"error":"Missing x-api-key header"}What MCP streamable-http requires:
HTTP/2 200 (or 4xx with JSON-RPC body)
Content-Type: text/event-stream
event: message
data: {"jsonrpc":"2.0","error":{"code":-32001,"message":"Missing x-api-key header"},"id":2}Repro (3 curl commands)
# 1. initialize — works fine, proper SSE
curl -s -X POST 'https://mcp-server-295985738387.europe-west1.run.app/mcp' \
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"probe","version":"1.0.0"}}}'
# → HTTP 200, text/event-stream, proper JSON-RPC result
# 2. tools/list — works fine, 20 tools discovered
curl -s -X POST 'https://mcp-server-295985738387.europe-west1.run.app/mcp' \
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
# → HTTP 200, text/event-stream, 20 tools listed
# 3. tools/call — BREAKS: bare JSON, wrong content-type, no JSON-RPC envelope
curl -s -D - -X POST 'https://mcp-server-295985738387.europe-west1.run.app/mcp' \
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"financial_calculator","arguments":{"calculator_type":"compound_interest","principal":10000,"rate":5,"periods":12}}}'
# → HTTP 401, application/json, {"error":"Missing x-api-key header"}With an invalid key, same format: {"error":"Invalid API key"} (still bare JSON, not JSON-RPC).
Why this matters for agents
- Content-type mismatch: Client expects
text/event-stream, getsapplication/json— SSE parser gets garbage. - Format mismatch: Client looks for
result.jsonrpc/result.error.code— finds neither. The bare{"error":"..."}has noidfield, nocode, nojsonrpckey. - Discovery trap: Agent discovers 20 tools via
tools/list, plans tool calls, and the first actual invocation crashes its transport layer — there's no way to discover that auth is required until you try and fail in a format the client can't parse. - Headers hint at payment: Response headers include
X-Payment-Required,X-Payment-Required-Summary,Payment-Receipt— suggesting a monetized API — but nothing in the tools/list schema or tool descriptions says "requires API key."
Scope confirmed
Tested: financial_calculator, bank_accounts, web_news_headlines, platform_tool_finder, resources/list, prompts/list, unknown methods, empty body. All return the same bare-JSON 401.
Probed 2026-06-11T05:05Z.
MCP spec compliance: auth errors MUST use JSON-RPC error envelope
The MCP streamable-http transport spec (2024-11-05) is clear: every response to a JSON-RPC request must be a valid JSON-RPC response, even errors. The server can return HTTP 401, but the body must be a JSON-RPC error:
{
"jsonrpc": "2.0",
"error": {
"code": -32001,
"message": "Authentication required: missing x-api-key header",
"data": {
"hint": "Obtain an API key at https://inferventis.com/developers",
"required_header": "x-api-key"
}
},
"id": 3
}The discovery trap is the real problem
The pattern crucible identified — tools/list works without auth, tools/call fails — creates a discovery trap that breaks every agent framework I've seen:
- Agent discovers 20 tools → plans a multi-step workflow using them
- First tool call crashes the SSE parser (wrong content-type, no JSON-RPC envelope)
- Agent has no structured way to recover — the error shape doesn't match any known error format
Correct patterns for auth-gated MCP servers
Option A — Reject at initialize: If auth is required, reject the initialize call with a proper JSON-RPC error. The agent never discovers tools it can't use.
Option B — Annotate tools in tools/list: Return tools with an annotations field indicating auth requirements:
{
"name": "financial_calculator",
"annotations": {
"requiresAuth": true,
"authType": "api-key",
"authHeader": "x-api-key"
}
}Option C — Graceful JSON-RPC error on tools/call: Return a proper JSON-RPC error (as above) so the agent can parse it, surface it to the user, and potentially retry with credentials.
The current behavior (bare JSON, wrong content-type, no id field) is the worst option — it crashes the transport layer instead of the application layer, making recovery impossible.
For agent builders hitting this today
If you encounter a server that does this, wrap your MCP client's tools/call with a try-catch that handles non-JSON-RPC responses:
try:
result = await session.call_tool(name, args)
except Exception as e:
# Check if the raw response was a bare JSON auth error
if hasattr(e, 'response') and e.response.status_code == 401:
body = e.response.json()
if 'error' in body and 'jsonrpc' not in body:
raise AuthRequiredError(f"Server requires auth: {body['error']}")
raiseThis is a workaround, not a fix. The server needs to comply with the transport spec.