googleapis/mcp-toolbox · error

unable to initialize server: %w

Error message

unable to initialize server: %w

What it means

NewServer calls parsePRMURL(cfg.ToolboxUrl) to compute the URL advertised in WWW-Authenticate Protected Resource Metadata headers. If cfg.ToolboxUrl is set but cannot be converted into a valid PRM URL (malformed scheme/host), the server refuses to start, wrapping the parse error under this message.

Source

Thrown at internal/server/server.go:491

	addr := net.JoinHostPort(cfg.Address, strconv.Itoa(cfg.Port))
	srv := &http.Server{Addr: addr, Handler: r}

	sseManager := newSseManager(ctx)

	primitiveManager := primitives.NewPrimitiveManager(sourcesMap, authServicesMap, embeddingModelsMap, toolsMap, promptsMap, groupsMap)

	limit := cfg.HttpMaxRequestBytes
	if limit <= 0 {
		limit = DefaultHTTPMaxRequestBytes
	}

	mcp.InitializeProtocols(mcp.ProtocolOptions{
		DisableExt: cfg.DisableExt,
	})

	prmURLStr, err := parsePRMURL(cfg.ToolboxUrl)
	if err != nil {
		return nil, fmt.Errorf("unable to initialize server: %w", err)
	}
	prmURL, err := url.Parse(prmURLStr)
	if err != nil {
		return nil, fmt.Errorf("unable to initialize server: %w", err)
	}

	s := &Server{
		version:             cfg.Version,
		sqlCommenterEnabled: cfg.SQLCommenter,
		srv:                 srv,
		root:                r,
		logger:              l,
		instrumentation:     instrumentation,
		sseManager:          sseManager,
		PrimitiveMgr:        primitiveManager,
		toolboxUrl:          cfg.ToolboxUrl,
		prmURL:              prmURLStr,
		mcpPrmFile:          cfg.McpPrmFile,

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Set --toolbox-url to a fully qualified URL including scheme, e.g. https://toolbox.example.com.
  2. If OAuth/PRM advertisement is not needed, unset toolbox-url entirely instead of passing a placeholder.
  3. Check for stripped scheme in env-var templating (e.g. ${TOOLBOX_URL} missing its https:// prefix).

Example fix

// before
toolbox serve --toolbox-url toolbox.internal:5000 ...

// after
toolbox serve --toolbox-url https://toolbox.internal:5000 ...
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(cfg.ToolboxUrl)
if err != nil || u.Scheme == "" || u.Host == "" {
    return fmt.Errorf("--toolbox-url must be an absolute URL like https://host:port, got %q", cfg.ToolboxUrl)
}

Type guard

func isAbsoluteURL(s string) bool {
    u, err := url.Parse(s)
    return err == nil && u.Scheme != "" && u.Host != ""
}

Try / catch

if _, err := server.NewServer(ctx, cfg); err != nil {
    if strings.Contains(err.Error(), "unable to initialize server") && !isAbsoluteURL(cfg.ToolboxUrl) {
        cfg.ToolboxUrl = "https://" + cfg.ToolboxUrl
        _, err = server.NewServer(ctx, cfg)
    }
    return err
}

Prevention

When it happens

Trigger: Setting --toolbox-url (or cfg.ToolboxUrl) to a value that parsePRMURL (internal/server/prm.go) rejects — e.g. missing scheme, empty string where required, or a URL with no host — during NewServer.

Common situations: Deployments behind proxies configuring toolbox-url as "my-proxy.example.com" without "https://", or leftover placeholder values like "changeme" in Helm/K8s manifests.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/04d38ac674780061. Report an issue: GitHub.