{"record":{"id":"094ae36ff2179d8b","repo":"HKUDS/DeepTutor","slug":"mcp-server-error","errorCode":null,"errorMessage":"mcp.server_error","messagePattern":"mcp\\.server_error","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"deeptutor/api/routers/mcp_settings.py","lineNumber":52,"sourceCode":"router = APIRouter(dependencies=[Depends(require_admin)])\n\n\nclass MCPSettingsPayload(BaseModel):\n    servers: dict[str, MCPServerConfig] = Field(default_factory=dict)\n\n\ndef _validate_servers(config: MCPConfig) -> None:\n    for name, cfg in config.servers.items():\n        transport = cfg.resolved_type()\n        if transport is None:\n            raise HTTPException(\n                status_code=400,\n                detail=t(\"mcp.configure_command_or_url\", name=name),\n            )\n        if transport in {\"sse\", \"streamableHttp\"}:\n            ok, error = validate_mcp_url(cfg.url)\n            if not ok:\n                raise HTTPException(\n                    status_code=400, detail=t(\"mcp.server_error\", name=name, error=error)\n                )\n\n\n@router.get(\"\")\nasync def get_mcp_settings() -> dict[str, Any]:\n    config = load_mcp_config()\n    manager = get_mcp_manager()\n    await manager.ensure_started()\n    return {\n        \"servers\": {name: cfg.model_dump(mode=\"json\") for name, cfg in config.servers.items()},\n        \"status\": manager.status(),\n    }\n\n\n@router.put(\"\")\nasync def update_mcp_settings(payload: MCPSettingsPayload) -> dict[str, Any]:\n    try:","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/api/routers/mcp_settings.py#L34-L70","documentation":"Validation error from _validate_servers: the server entry declares an SSE or streamable HTTP transport (has a url), but that URL fails validate_mcp_url — typically missing a scheme, using a disallowed scheme, or being malformed. The error message embeds the specific validation error.","triggerScenarios":"PUT mcp settings or upsert with a server whose resolved transport is 'sse' or 'streamableHttp' and whose url is e.g. 'localhost:8080/sse' (no scheme), 'ftp://...', or an unparsable string.","commonSituations":"Copying an MCP endpoint from docs and dropping the https:// prefix; mixing up the fields (putting the URL into a command field or vice versa); proxy/firewall environments where developers hand-edit URLs and introduce typos.","solutions":["Fix the URL to include a full valid scheme and host, e.g. https://example.com/mcp/sse","Read the embedded {error} in the 400 detail — it states exactly what validate_mcp_url rejected","Confirm the transport type matches the URL field usage (stdio servers use command, remote servers use url)","Test the URL with curl to confirm the endpoint is reachable and correctly formed"],"exampleFix":"// before\n{\"servers\": {\"remote\": {\"name\": \"remote\", \"url\": \"example.com/mcp/sse\"}}}\n\n// after\n{\"servers\": {\"remote\": {\"name\": \"remote\", \"url\": \"https://example.com/mcp/sse\"}}}","handlingStrategy":"validation","validationCode":"function isValidMcpUrl(url: string): boolean {\n  try {\n    const u = new URL(url);\n    return u.protocol === 'http:' || u.protocol === 'https:';\n  } catch {\n    return false;\n  }\n}\nif (transport === 'sse' || transport === 'streamableHttp') {\n  if (!isValidMcpUrl(cfg.url)) throw new Error(`Invalid MCP url: ${cfg.url}`);\n}","typeGuard":"function isHttpUrl(s: string): s is string {\n  return /^https?:\\/\\/.+/.test(s);\n}","tryCatchPattern":"try {\n  await api.put('/mcp', { servers });\n} catch (e) {\n  if (e.status === 400 && e.detail?.includes('server_error')) {\n    // fix the reported server's url and retry\n  }\n  throw e;\n}","preventionTips":["Always include the scheme when entering MCP URLs","Normalize/paste URLs from the provider's docs verbatim","Test URLs with curl before saving"],"tags":["mcp","url","validation","config","bad-request"],"backgroundTag":"invalid-url-scheme","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}