{"record":{"id":"379f50f9530e46ce","repo":"sipeed/picoclaw","slug":"target-q-looks-like-a-remote-mcp-url-but-transpo","errorCode":null,"errorMessage":"target %q looks like a remote MCP URL, but transport is %q. Use --transport http or --transport sse","messagePattern":"target %q looks like a remote MCP URL, but transport is %q\\. Use --transport http or --transport sse","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/picoclaw/internal/mcp/add.go","lineNumber":226,"sourceCode":"\t\t}\n\t\tif len(args) > 0 {\n\t\t\treturn config.MCPServerConfig{}, fmt.Errorf(\"%s transport does not accept command arguments\", transport)\n\t\t}\n\t\tparsedURL, err := url.ParseRequestURI(target)\n\t\tif err != nil || parsedURL.Scheme == \"\" || parsedURL.Host == \"\" {\n\t\t\treturn config.MCPServerConfig{}, fmt.Errorf(\"invalid MCP URL %q\", target)\n\t\t}\n\t\tserver.URL = target\n\t\tserver.Headers = headers\n\t\treturn server, nil\n\t}\n\n\tif len(headers) > 0 {\n\t\treturn config.MCPServerConfig{}, fmt.Errorf(\"--header can only be used with http or sse transport\")\n\t}\n\n\tif looksLikeRemoteURL(target) {\n\t\treturn config.MCPServerConfig{}, fmt.Errorf(\n\t\t\t\"target %q looks like a remote MCP URL, but transport is %q. Use --transport http or --transport sse\",\n\t\t\ttarget,\n\t\t\ttransport,\n\t\t)\n\t}\n\n\tcommand := target\n\tcommandArgs := append([]string(nil), args...)\n\n\tif err := validateLocalCommandPath(target); err != nil {\n\t\treturn config.MCPServerConfig{}, err\n\t}\n\tif isLocalCommandPath(command) {\n\t\tcommand = expandHomePath(command)\n\t}\n\n\tserver.Command = command\n\tserver.Args = commandArgs","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/cmd/picoclaw/internal/mcp/add.go#L208-L244","documentation":"When transport is stdio (the default) but the target parses as an http/https URL with a host — looksLikeRemoteURL, helpers.go:259-273 — the CLI refuses to store a URL as a stdio command and names the fix (add.go:225-231). This catches the most common mistake: supplying a remote MCP URL while forgetting that transport defaults to stdio.","triggerScenarios":"`picoclaw mcp add github https://api.githubcopilot.com/mcp/` with no --transport flag; `-t stdio` passed explicitly together with a URL.","commonSituations":"Following vendor MCP docs that show only a URL; coming from other CLIs that infer transport from the URL shape; copy-pasting an sse endpoint into a stdio-style command line.","solutions":["Append --transport http (streamable-http is accepted and normalizes to http)","Use --transport sse if the endpoint is a legacy SSE server","If you truly meant stdio, replace the URL with a local command path"],"exampleFix":"# before\npicoclaw mcp add github https://api.githubcopilot.com/mcp/\n# after\npicoclaw mcp add github https://api.githubcopilot.com/mcp/ --transport http","handlingStrategy":"validation","validationCode":"func looksLikeRemoteURL(target string) bool {\n\tu, err := url.ParseRequestURI(target)\n\treturn err == nil && u.Host != \"\" &&\n\t\t(strings.ToLower(u.Scheme) == \"http\" || strings.ToLower(u.Scheme) == \"https\")\n}\n\nif looksLikeRemoteURL(target) && transport == \"stdio\" {\n\ttransport = \"http\" // or fail loudly with a clear message\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Whenever the target starts with http:// or https://, always pass --transport http (or sse)","Pin the transport explicitly in scripts instead of relying on the stdio default"],"tags":["cli","mcp","transport","url-validation"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}