{"record":{"id":"2bc621966784ce57","repo":"BerriAI/litellm","slug":"missing-parameter","errorCode":"missing_parameter","errorMessage":"server_id is required in request body","messagePattern":"server_id is required in request body","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"litellm/proxy/_experimental/mcp_server/rest_endpoints.py","lineNumber":952,"sourceCode":"        try:\n            user_api_key_dict = await acting_user_auth(user_api_key_dict)\n            data = await request.json()\n\n            tool_name: Final = data.get(\"name\")\n            tool_arguments: Final = data.get(\"arguments\") or {}\n\n            from litellm.proxy._experimental.mcp_server.tool_search import (\n                MCP_TOOL_CALL_TOOL_NAME,\n                MCP_TOOL_SEARCH_TOOL_NAME,\n            )\n\n            if tool_name in (MCP_TOOL_SEARCH_TOOL_NAME, MCP_TOOL_CALL_TOOL_NAME):\n                return await _handle_virtual_mcp_tool(request, data, tool_name, user_api_key_dict)\n\n            # Validate required parameters early\n            server_id: Final = data.get(\"server_id\")\n            if not server_id:\n                raise HTTPException(\n                    status_code=400,\n                    detail={\n                        \"error\": \"missing_parameter\",\n                        \"message\": \"server_id is required in request body\",\n                    },\n                )\n\n            if not tool_name:\n                raise HTTPException(\n                    status_code=400,\n                    detail={\n                        \"error\": \"missing_parameter\",\n                        \"message\": \"name is required in request body\",\n                    },\n                )\n\n            proxy_base_llm_response_processor: Final = ProxyBaseLLMRequestProcessing(data=data)\n            (","sourceCodeStart":934,"sourceCodeEnd":970,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/_experimental/mcp_server/rest_endpoints.py#L934-L970","documentation":"The REST tool-call route validates required body fields early: for any concrete tool (everything except the virtual mcp_tool_search/mcp_tool_call tools), server_id must be a non-empty field of the JSON request body. Missing, null, or empty-string server_id yields 400 error=missing_parameter with this message before any auth or upstream work happens.","triggerScenarios":"POST to the tool-call route with {\"tool_name\": ..., \"arguments\": ...} but no server_id; putting server_id in the query string or URL path instead of the body; sending \"server_id\": \"\" or null.","commonSituations":"Clients ported from the native MCP SDK where tools are addressed globally without a server; generated SDKs that drop optional-looking fields; copy-pasting examples that use the virtual tool shape for concrete tools.","solutions":["Include the target server's id in the JSON body: {\"server_id\": \"...\", \"tool_name\": \"...\", \"arguments\": {...}}.","Discover the correct server_id first via GET /mcp/tools/list.","If you genuinely want server-agnostic search/call, use the mcp_tool_search/mcp_tool_call virtual tools - but the key then needs mcp_tool_search_enabled."],"exampleFix":"# before\ncurl -X POST $PROXY/mcp/tool-call -H \"Authorization: Bearer $KEY\" \\\n  -d '{\"tool_name\": \"get_weather\", \"arguments\": {\"city\": \"Paris\"}}'\n# -> 400 {\"error\":\"missing_parameter\",\"message\":\"server_id is required in request body\"}\n\n# after\ncurl -X POST $PROXY/mcp/tool-call -H \"Authorization: Bearer $KEY\" \\\n  -d '{\"server_id\": \"weather\", \"tool_name\": \"get_weather\", \"arguments\": {\"city\": \"Paris\"}}'","handlingStrategy":"validation","validationCode":"def valid_tool_call_payload(payload: dict) -> bool:\n    return (\n        bool(payload.get(\"tool_name\"))\n        and bool(payload.get(\"server_id\"))  # not required only for mcp_tool_search/mcp_tool_call\n        and isinstance(payload.get(\"arguments\", {}), dict)\n    )\n\nassert valid_tool_call_payload(payload), \"server_id and tool_name are required in the body\"","typeGuard":null,"tryCatchPattern":"resp = await client.post(f\"{proxy}/mcp/tool-call\", json=payload, headers=headers)\nif resp.status_code == 400 and resp.json().get(\"detail\", {}).get(\"error\") == \"missing_parameter\":\n    raise BadRequest(f\"fill required body fields: {resp.json()['detail']['message']}\") from None\nresp.raise_for_status()","preventionTips":["Validate the request body shape (server_id + tool_name + arguments) client-side before sending.","Remember server_id lives in the JSON body, not the URL or query string, on this route.","Only the virtual tools mcp_tool_search/mcp_tool_call omit server_id - and those need the key flag."],"tags":["mcp","http-400","validation","request-body","missing-parameter"],"backgroundTag":"missing-request-parameter","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T10:36:37.832Z"}