{"record":{"id":"4d0f78b06568d057","repo":"conductor-oss/conductor","slug":"invalid-response-tools-field-is-missing-or-not","errorCode":null,"errorMessage":"Invalid response: 'tools' field is missing or not an array","messagePattern":"Invalid response: 'tools' field is missing or not an array","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/org/conductoross/conductor/ai/mcp/MCPService.java","lineNumber":161,"sourceCode":"            } else {\n                // Parse as JSON directly\n                responseJson = objectMapper.readTree(responseBody);\n            }\n\n            if (responseJson.has(\"error\")) {\n                throw new RuntimeException(\n                        \"JSON-RPC error: \" + responseJson.get(\"error\").toString());\n            }\n\n            if (!responseJson.has(\"result\")) {\n                throw new RuntimeException(\"Invalid JSON-RPC response: missing 'result' field\");\n            }\n\n            JsonNode result = responseJson.get(\"result\");\n            JsonNode toolsNode = result.get(\"tools\");\n\n            if (toolsNode == null || !toolsNode.isArray()) {\n                throw new RuntimeException(\n                        \"Invalid response: 'tools' field is missing or not an array\");\n            }\n            ExternalDataLimits.validateStructure(objectMapper.convertValue(result, Object.class));\n\n            // Convert to McpSchema.Tool list\n            // Use Jackson to deserialize tools directly (same pattern as stdio implementation)\n            List<McpSchema.Tool> tools =\n                    objectMapper.convertValue(\n                            toolsNode,\n                            objectMapper\n                                    .getTypeFactory()\n                                    .constructCollectionType(List.class, McpSchema.Tool.class));\n\n            log.debug(\n                    \"Successfully listed {} tools via direct JSON-RPC from {}\",\n                    tools.size(),\n                    serverUrl);\n            return tools;","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/mcp/MCPService.java#L143-L179","documentation":"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).","triggerScenarios":"Server returns `{\"result\":{}}` with no tools; server returns `{\"result\":{\"tool\":\"...\"}}` (singular); server returns `{\"result\":{\"capabilities\":{...}}}` confusing the list response with an initialize response.","commonSituations":"Server implements a non-standard or older MCP schema; result was meant for a different method; middleware rewrote the response envelope.","solutions":["Inspect the captured result object to see which field actually holds the tools list.","Update or restart the MCP server to a spec-compliant version (tools/list result.tools must be an array).","If the server is intentionally non-standard, wrap it with a compatibility adapter rather than this client."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    List<McpSchema.Tool> tools = mcpService.listTools(serverUrl, headers);\n} catch (RuntimeException e) {\n    if (e.getMessage().contains(\"'tools' field is missing\")) {\n        // server returned a non-standard result shape; inspect with a raw call\n    }\n    throw e;\n}","preventionTips":["Pin the MCP server to a spec-compliant version.","Wrap non-standard servers in a compatibility adapter instead of forcing this client.","Log the result object shape when validation fails."],"tags":["mcp","json-rpc","schema-validation","malformed-response"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}