{"record":{"id":"772dcbc3ae1ff808","repo":"alibaba/open-code-review","slug":"mcp-server-url-q-must-include-a-host","errorCode":null,"errorMessage":"MCP server URL %q must include a host","messagePattern":"MCP server URL %q must include a host","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/opencodereview/config_cmd.go","lineNumber":897,"sourceCode":"\t\t\tidx := strings.Index(e, \"=\")\n\t\t\tif idx <= 0 {\n\t\t\t\treturn fmt.Errorf(\"invalid env entry %q: must be in KEY=VALUE format\", e)\n\t\t\t}\n\t\t}\n\t\tentry.Env = env\n\tcase \"url\":\n\t\tif value == \"\" {\n\t\t\treturn fmt.Errorf(\"MCP server URL cannot be empty\")\n\t\t}\n\t\tparsed, err := url.Parse(value)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"invalid MCP server URL %q: %w\", value, err)\n\t\t}\n\t\tif parsed.Scheme != \"http\" && parsed.Scheme != \"https\" {\n\t\t\treturn fmt.Errorf(\"MCP server URL must use http or https scheme, got %q\", parsed.Scheme)\n\t\t}\n\t\tif parsed.Host == \"\" {\n\t\t\treturn fmt.Errorf(\"MCP server URL %q must include a host\", value)\n\t\t}\n\t\tentry.URL = value\n\tcase \"headers\":\n\t\tparsed, err := parseMCPHeaders(value)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"invalid headers for %s: %w\", key, err)\n\t\t}\n\t\tentry.Headers = parsed\n\tcase \"tools\":\n\t\tvar tools []string\n\t\tif err := json.Unmarshal([]byte(value), &tools); err != nil {\n\t\t\treturn fmt.Errorf(\"invalid JSON array for %s: %w\", key, err)\n\t\t}\n\t\tseen := make(map[string]struct{}, len(tools))\n\t\tfiltered := make([]string, 0, len(tools))\n\t\tfor _, t := range tools {\n\t\t\tif t == \"\" {\n\t\t\t\treturn fmt.Errorf(\"tool names in %s must not be empty\", key)","sourceCodeStart":879,"sourceCodeEnd":915,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/cmd/opencodereview/config_cmd.go#L879-L915","documentation":"After the URL parses and passes the http/https scheme check, the setter requires a non-empty Host. A URL like 'http://' or a scheme-only/relative form has no host to connect to, so a remote MCP server configured with it would be unreachable; the setter rejects it with the original value quoted.","triggerScenarios":"Calling setMCPServerValue with field \"url\" where the URL has a valid http/https scheme but no host, e.g. \"http://\" or \"https:///api/mcp\".","commonSituations":"Truncated paste of a URL losing the hostname; templated URLs where the host variable was empty; mistyping extra slashes after the scheme.","solutions":["Include the hostname (and port if needed) after the scheme: https://mcp.example.com/sse","Re-copy the complete URL from the server documentation","Check templated/scripted values so the host placeholder is filled"],"exampleFix":"// before\nocr config set mcp_servers.api.url https:///api/mcp\n// after\nocr config set mcp_servers.api.url https://mcp.example.com/api/mcp","handlingStrategy":"validation","validationCode":"u, err := url.Parse(rawURL)\nif err != nil || u.Host == \"\" {\n\treturn fmt.Errorf(\"URL must include a host\")\n}","typeGuard":"func hasHost(rawURL string) bool {\n\tu, err := url.Parse(rawURL)\n\treturn err == nil && u.Host != \"\"\n}","tryCatchPattern":"if err := setMCPServerValue(cfg, key, value); err != nil {\n\tfmt.Fprintf(os.Stderr, \"config set failed: %v\\n\", err)\n\tos.Exit(1)\n}","preventionTips":["Verify the hostname is present after the scheme","Re-copy the full URL from server docs rather than retyping","In scripts, check that the host variable is non-empty before interpolation"],"tags":["config","mcp","url","validation"],"backgroundTag":"invalid-url","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}