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

  1. Provide a non-empty url (http:// or https://) for the http-type MCP server
  2. If the URL comes from an env var, ensure it is set in the runtime environment
  3. Switch the type to stdio if this server is actually a local command
  4. 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

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


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/09c0eee8b6cfa6cb. Report an issue: GitHub.