{"record":{"id":"546317a4859be50b","repo":"unslothai/unsloth","slug":"mcp-server-address-must-start-with-http-or-http","errorCode":null,"errorMessage":"MCP server address must start with http:// or https:// (for example https://example.com/mcp).","messagePattern":"MCP server address must start with http:// or https:// \\(for example https://example\\.com/mcp\\)\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"studio/backend/routes/mcp_servers.py","lineNumber":103,"sourceCode":"                status_code = 400,\n                detail = \"Enter an http(s):// URL, or a local command whose \"\n                \"first token is an executable (not a URL).\",\n            )\n        return trimmed\n    parsed = urlparse(trimmed)\n    if parsed.scheme not in (\"http\", \"https\"):\n        if _looks_like_command(trimmed):\n            detail = (\n                \"Local commands aren't enabled on this server. To allow them, \"\n                \"set UNSLOTH_STUDIO_ALLOW_STDIO_MCP=1 and restart Unsloth, or use \"\n                \"an http:// or https:// URL instead.\"\n            )\n        else:\n            detail = (\n                \"MCP server address must start with http:// or https:// \"\n                \"(for example https://example.com/mcp).\"\n            )\n        raise HTTPException(status_code = 400, detail = detail)\n    if not parsed.netloc:\n        raise HTTPException(status_code = 400, detail = \"url is missing a host\")\n    return trimmed\n\n\ndef _normalize_headers(headers: dict[str, str] | None) -> dict[str, str] | None:\n    \"\"\"Trim header names, drop empties, coerce values to str; None if empty.\"\"\"\n    if not headers:\n        return None\n    out: dict[str, str] = {}\n    for raw_key, value in headers.items():\n        key = str(raw_key).strip()\n        if key:\n            out[key] = str(value)\n    return out or None\n\n\ndef _row_to_response(row: dict) -> McpServerResponse:","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/mcp_servers.py#L85-L121","documentation":"400 raised when the value has no http/https scheme and no whitespace (so it doesn't look like a command) — e.g. a bare host, a scheme-less URL, or a typo like 'htp://'. urlparse puts such strings in the path, the scheme check fails, and the user is pointed at the required http:// or https:// prefix.","triggerScenarios":"POST/PUT an MCP server with url values like 'example.com/mcp', 'localhost:8080', or 'ftp://example.com' — single-token values that aren't commands and aren't http(s).","commonSituations":"Users omitting the scheme out of browser-address-bar habit, or configs migrated from tools that accept bare hosts.","solutions":["Prefix the address with http:// or https:// (e.g. 'https://example.com/mcp').","For local servers use 'http://127.0.0.1:PORT/mcp', not '127.0.0.1:PORT'.","Strip accidental leading whitespace/characters that break scheme parsing."],"exampleFix":"# before\n{'url': 'example.com/mcp'}  # -> 400, missing scheme\n\n# after\n{'url': 'https://example.com/mcp'}","handlingStrategy":"validation","validationCode":"function normalizeMcpUrl(raw) {\n  const v = (raw ?? '').trim();\n  if (!/^https:\\/\\/|http:\\/\\//.test(v)) return 'https://' + v.replace(/^\\/+/, '');\n  return v;\n}","typeGuard":"const isHttpUrl = (v) => /^https?:\\/\\/[^\\s]+$/i.test(v.trim());","tryCatchPattern":null,"preventionTips":["Always send the scheme; don't rely on browser-style scheme-less input.","Validate with a URL parser (new URL(v)) before submitting."],"tags":["mcp","url","validation","http-400"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}