conductor-oss/conductor · error · RuntimeException

Invalid response: 'tools' field is missing or not an array

Error message

Invalid response: 'tools' field is missing or not an array

What it means

Thrown by listToolsDirectHttp when result exists but result.tools is either absent or not a JSON array. The tools/list result object must contain a `tools` array per the MCP spec; this guards a server that returns a result of the wrong shape (e.g. an object, or a renamed field).

Source

Thrown at ai/src/main/java/org/conductoross/conductor/ai/mcp/MCPService.java:161

            } else {
                // Parse as JSON directly
                responseJson = objectMapper.readTree(responseBody);
            }

            if (responseJson.has("error")) {
                throw new RuntimeException(
                        "JSON-RPC error: " + responseJson.get("error").toString());
            }

            if (!responseJson.has("result")) {
                throw new RuntimeException("Invalid JSON-RPC response: missing 'result' field");
            }

            JsonNode result = responseJson.get("result");
            JsonNode toolsNode = result.get("tools");

            if (toolsNode == null || !toolsNode.isArray()) {
                throw new RuntimeException(
                        "Invalid response: 'tools' field is missing or not an array");
            }
            ExternalDataLimits.validateStructure(objectMapper.convertValue(result, Object.class));

            // Convert to McpSchema.Tool list
            // Use Jackson to deserialize tools directly (same pattern as stdio implementation)
            List<McpSchema.Tool> tools =
                    objectMapper.convertValue(
                            toolsNode,
                            objectMapper
                                    .getTypeFactory()
                                    .constructCollectionType(List.class, McpSchema.Tool.class));

            log.debug(
                    "Successfully listed {} tools via direct JSON-RPC from {}",
                    tools.size(),
                    serverUrl);
            return tools;

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Inspect the captured result object to see which field actually holds the tools list.
  2. Update or restart the MCP server to a spec-compliant version (tools/list result.tools must be an array).
  3. If the server is intentionally non-standard, wrap it with a compatibility adapter rather than this client.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    List<McpSchema.Tool> tools = mcpService.listTools(serverUrl, headers);
} catch (RuntimeException e) {
    if (e.getMessage().contains("'tools' field is missing")) {
        // server returned a non-standard result shape; inspect with a raw call
    }
    throw e;
}

Prevention

When it happens

Trigger: Server returns `{"result":{}}` with no tools; server returns `{"result":{"tool":"..."}}` (singular); server returns `{"result":{"capabilities":{...}}}` confusing the list response with an initialize response.

Common situations: Server implements a non-standard or older MCP schema; result was meant for a different method; middleware rewrote the response envelope.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/4d0f78b06568d057. Report an issue: GitHub.