conductor-oss/conductor · error · RuntimeException
HTTP %d error from MCP server: %s
Error message
HTTP %d error from MCP server: %s
What it means
Thrown by MCPService.listToolsDirectHttp when the remote MCP server returns an HTTP status outside the 200-299 success range for a tools/list JSON-RPC POST. The %d is the status code and %s is the raw response body (read and size-bounded first). It signals the server rejected the request at the transport layer before any JSON-RPC semantics apply.
Source
Thrown at ai/src/main/java/org/conductoross/conductor/ai/mcp/MCPService.java:128
request.put("id", 1);
Request.Builder requestBuilder =
new Request.Builder()
.url(serverUrl)
.post(
RequestBody.create(
objectMapper.writeValueAsString(request),
MediaType.get("application/json")))
.header("Content-Type", "application/json")
.header("Accept", "application/json, text/event-stream");
// Add custom headers
addHeaders(requestBuilder, headers);
ResponsePayload response = execute(requestBuilder.build());
// Check response status
if (response.statusCode < 200 || response.statusCode >= 300) {
throw new RuntimeException(
String.format(
"HTTP %d error from MCP server: %s",
response.statusCode, response.body));
}
// Get response body and content type
String responseBody = response.body;
String contentType = response.contentType;
// Parse response based on content type
JsonNode responseJson;
if (contentType != null && contentType.contains("text/event-stream")) {
// Parse SSE format
responseJson = parseSseResponse(responseBody);
} else {
// Parse as JSON directly
responseJson = objectMapper.readTree(responseBody);
}View on GitHub (pinned to cf7c3e4a8a)
Solutions
- Verify serverUrl points at the MCP server's streamable-HTTP JSON-RPC endpoint, not a browser or SSE-only URL.
- Confirm the headers map contains the auth the server expects (Bearer token, API key) and that it is not expired.
- Reproduce with curl: POST the same tools/list JSON-RPC body with the same headers and inspect the status/body.
- If the server requires MCP initialize, use a client/transport that performs the handshake instead of this raw-JSON-RPC path.
Example fix
// before
List<McpSchema.Tool> tools = mcpService.listTools(url, headers);
// after
if (headers == null || headers.get("Authorization") == null) {
throw new IllegalStateException("MCP server requires Authorization; header missing");
}
List<McpSchema.Tool> tools;
try {
tools = mcpService.listTools(url, headers);
} catch (RuntimeException e) {
throw new RuntimeException("tools/list failed for " + url + " (check URL/auth): " + e.getMessage(), e);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the URL is a plausible MCP JSON-RPC endpoint before calling.
java.net.URI u = java.net.URI.create(serverUrl);
if (!u.getScheme().matches("https?") || u.getHost() == null) {
throw new IllegalArgumentException("Invalid MCP server URL: " + serverUrl);
} Try / catch
try {
List<McpSchema.Tool> tools = mcpService.listTools(serverUrl, headers);
} catch (RuntimeException e) {
// Message contains 'HTTP <code> error'; parse the code for retry/backoff decisions.
if (e.getMessage().contains("HTTP 5") || e.getMessage().contains("HTTP 429")) {
// transient: retry with backoff
} else {
throw e;
}
} Prevention
- Keep serverUrl and credentials in configuration validated at startup, not per-call.
- Distinguish 5xx/429 (retry) from 4xx (fix auth/URL) by parsing the embedded status code.
- Log the raw response body present in the message for diagnosis.
When it happens
Trigger: Calling MCPService.listTools(serverUrl, headers) against an MCP endpoint that responds 4xx/5xx (e.g. 401 Unauthorized when headers lack a valid token, 404 for a wrong URL, 500 from a crashed server, 413 if the request itself is large). Also a server that requires the full MCP initialize handshake and returns 400 to the raw JSON-RPC call this code makes.
Common situations: Wrong base URL (pointed at an HTML page or the SSE endpoint instead of the streamable-HTTP endpoint); missing or expired Authorization header; MCP server behind a gateway that returns 403; server that only accepts the initialized session and rejects bare tools/list.
Related errors
- A2A call '{method}' to {endpoint} failed: {message}
- JSON-RPC error: {error}
- Invalid JSON-RPC response: missing 'result' field
- Invalid response: 'tools' field is missing or not an array
- Failed to list MCP tools from {serverUrl}: {message}
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/161c16e18df934bf.
Report an issue: GitHub.