charmbracelet/crush · error
mcp http config requires a non-empty 'url' field
Error message
mcp http config requires a non-empty 'url' field
What it means
For MCP HTTP-type servers, createTransport resolves the 'url' field and rejects empty/whitespace values. An HTTP transport cannot be constructed without an endpoint, so init fails with this message.
Source
Thrown at internal/agent/tools/mcp/init.go:1070
}
cmd := exec.CommandContext(ctx, home.Long(command), args...)
cmd.Env = append(os.Environ(), envs...)
// Run the child in its own process group and kill the whole group when
// the session context is cancelled. A stdio server often spawns its own
// children (signal-mcp launches signal-cli); os/exec's default
// cancellation kills only the direct child, orphaning the rest with
// PPID 1 — production accumulated 15+ such zombies over two days.
configureStdioProcess(cmd)
return &mcp.CommandTransport{
Command: cmd,
}, nil, nil
case config.MCPHttp:
url, err := m.ResolvedURL(resolver)
if err != nil {
return nil, nil, err
}
if strings.TrimSpace(url) == "" {
return nil, nil, fmt.Errorf("mcp http config requires a non-empty 'url' field")
}
// OAuth-enabled HTTP transport. The handler persists the token
// (and the client registration/endpoints needed to refresh it)
// on every exchange and refresh via this saver.
if m.OAuth {
tokenSaver := func(tok *oauth.Token) {
if err := cfg.SetConfigField(config.ScopeGlobal, fmt.Sprintf("mcp.%s.oauth_token", name), tok); err != nil {
slog.Warn("Failed to persist MCP OAuth token", "name", name, "error", err)
} else {
slog.Info("Persisted MCP OAuth token", "name", name)
}
}
// A pre-registered client is required for servers that do not
// support dynamic client registration (e.g. GitHub, Slack).
// Resolve the credentials through the shell like other config
// values so $VAR and $(cmd) work.View on GitHub (pinned to 7944b8e522)
Solutions
- Provide a non-empty url (http:// or https://) for the http-type MCP server
- If the URL comes from an env var, ensure it is set in the runtime environment
- Switch the type to stdio if this server is actually a local command
- Check ResolvedURL resolution errors wrapped earlier in the log
Example fix
// before mcp api type http url '' // after mcp api type http url 'https://api.example.com/mcp'
Defensive patterns
Strategy: validation
Validate before calling
u := os.Getenv("MY_MCP_URL")
if strings.TrimSpace(u) == "" {
return errors.New("MY_MCP_URL must be set for http-type mcp servers")
}
if _, err := url.Parse(u); err != nil {
return fmt.Errorf("invalid mcp url: %w", err)
} Prevention
- Always set a full http(s) URL for http-type MCP entries
- Export any env vars referenced in the url field
- Validate config after converting entries between stdio and http
- Test the endpoint with curl before wiring it into config
When it happens
Trigger: An MCP config with type http whose 'url' field is missing, empty, or resolves to an empty string through the variable resolver.
Common situations: URL stored in an env var that is unset (e.g. $MY_MCP_URL); config entry converted from stdio to http without filling in url; trailing typo leaving the field blank.
Related errors
- mcp stdio config requires a non-empty 'command' field
- mcp sse config requires a non-empty 'url' field
- unsupported mcp type: %s
- failed to create request for provider %s: %w
- not a valid bedrock api key
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/09c0eee8b6cfa6cb.
Report an issue: GitHub.