sipeed/picoclaw · error
invalid MCP URL %q
Error message
invalid MCP URL %q
What it means
Thrown by `picoclaw mcp add` when transport is http or sse and the target does not parse as an absolute URL. buildServerConfig runs url.ParseRequestURI(target) and additionally requires a non-empty Scheme and Host (add.go:212-215); anything missing either part is rejected with the raw target quoted. It is pure input validation before any config is written.
Source
Thrown at cmd/picoclaw/internal/mcp/add.go:214
Enabled: true,
Type: transport,
Deferred: opts.Deferred,
}
switch transport {
case "http", "sse":
if len(env) > 0 {
return config.MCPServerConfig{}, fmt.Errorf("--env can only be used with stdio transport")
}
if strings.TrimSpace(opts.EnvFile) != "" {
return config.MCPServerConfig{}, fmt.Errorf("--env-file can only be used with stdio transport")
}
if len(args) > 0 {
return config.MCPServerConfig{}, fmt.Errorf("%s transport does not accept command arguments", transport)
}
parsedURL, err := url.ParseRequestURI(target)
if err != nil || parsedURL.Scheme == "" || parsedURL.Host == "" {
return config.MCPServerConfig{}, fmt.Errorf("invalid MCP URL %q", target)
}
server.URL = target
server.Headers = headers
return server, nil
}
if len(headers) > 0 {
return config.MCPServerConfig{}, fmt.Errorf("--header can only be used with http or sse transport")
}
if looksLikeRemoteURL(target) {
return config.MCPServerConfig{}, fmt.Errorf(
"target %q looks like a remote MCP URL, but transport is %q. Use --transport http or --transport sse",
target,
transport,
)
}
View on GitHub (pinned to 49183d7e8d)
Solutions
- Rewrite the target as a full absolute URL including scheme and host, e.g. https://example.com/mcp
- Quote the whole URL so the shell cannot mangle it: picoclaw mcp add mysvc --transport http "https://example.com/mcp"
- If the target is actually a local command, drop --transport http/sse and use stdio syntax
Example fix
# before picoclaw mcp add cache --transport http localhost:6379/mcp # after picoclaw mcp add cache --transport http https://localhost:6379/mcp
Defensive patterns
Strategy: validation
Validate before calling
func validMCPURL(target string) bool {
u, err := url.ParseRequestURI(target)
return err == nil && u.Scheme != "" && u.Host != ""
}
// before shelling out:
if !validMCPURL(target) {
return fmt.Errorf("target %q must be an absolute URL like https://host/mcp", target)
} Prevention
- Always pass http/sse endpoints as scheme+host URLs (https://example.com/mcp)
- Quote the entire URL argument in shell scripts
- In wrappers, pre-check with the same ParseRequestURI + Scheme + Host rules the CLI uses
When it happens
Trigger: `picoclaw mcp add mysvc --transport http localhost:8080/mcp` (no scheme), `--transport sse example.com/sse` (no scheme), a bare path like `/mcp` (no host), or a typo that makes ParseRequestURI fail.
Common situations: Copy-pasting an endpoint from vendor docs that list it as host:port without https://; shell quoting eating part of the URL; assuming the CLI infers the scheme like some other MCP clients do.
Related errors
- target %q looks like a remote MCP URL, but transport is %q.
- failed to confirm overwrite: %w
- aborted: MCP server %q already exists
- missing value for %s
- usage: picoclaw mcp add [flags] <name> <command-or-url> [arg
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/0e5136fe1a498d58.
Report an issue: GitHub.