charmbracelet/crush · error

failed to refresh MCP prompts: status code %d

Error message

failed to refresh MCP prompts: status code %d

What it means

This error is returned by Client.MCPRefreshPrompts when the server responds with a non-200 status code. Unlike MCPAuthenticate, this function does not attempt to decode a proto.Error body, so the caller only receives the raw status: "failed to refresh MCP prompts: status code %d". The request reached the server but the refresh was rejected or failed server-side.

Source

Thrown at internal/client/proto.go:403

		}
		return fmt.Errorf("failed to authenticate MCP: status code %d", rsp.StatusCode)
	}
	return nil
}

// MCPRefreshPrompts refreshes prompts for a named MCP client.
func (c *Client) MCPRefreshPrompts(ctx context.Context, id, name string) error {
	rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/mcp/refresh-prompts", id), nil,
		jsonBody(struct {
			Name string `json:"name"`
		}{Name: name}),
		http.Header{"Content-Type": []string{"application/json"}})
	if err != nil {
		return fmt.Errorf("failed to refresh MCP prompts: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return fmt.Errorf("failed to refresh MCP prompts: status code %d", rsp.StatusCode)
	}
	return nil
}

// MCPRefreshResources refreshes resources for a named MCP client.
func (c *Client) MCPRefreshResources(ctx context.Context, id, name string) error {
	rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/mcp/refresh-resources", id), nil,
		jsonBody(struct {
			Name string `json:"name"`
		}{Name: name}),
		http.Header{"Content-Type": []string{"application/json"}})
	if err != nil {
		return fmt.Errorf("failed to refresh MCP resources: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return fmt.Errorf("failed to refresh MCP resources: status code %d", rsp.StatusCode)
	}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Check the numeric status code: 4xx indicates a request/credential problem, 5xx indicates a server-side problem
  2. Verify the MCP name is registered on the workspace and the workspace id is valid
  3. Refresh credentials if the status is 401/403; check server logs if the status is 5xx
  4. Retry with backoff for transient 5xx/429 responses; fix configuration for 4xx responses

Example fix

// before
if err := client.MCPRefreshPrompts(ctx, wsID, name); err != nil {
    log.Printf("refresh failed: %v", err) // only status code known
}

// after
if err := client.MCPRefreshPrompts(ctx, wsID, name); err != nil {
    var statusErr interface{ HTTPStatus() int }
    _ = statusErr
    log.Printf("refresh failed (status in message): %v — check that MCP %q is registered on %s", err, name, wsID)
}
Defensive patterns

Strategy: fallback

Validate before calling

// Verify the MCP server is registered before attempting a refresh
func mcpRegistered(ctx context.Context, c *Client, wsID, name string) error {
    servers, err := c.MCPList(ctx, wsID) // or equivalent listing call
    if err != nil { return err }
    for _, s := range servers {
        if s.Name == name { return nil }
    }
    return fmt.Errorf("mcp %q not registered on workspace %s", name, wsID)
}

Type guard

// Extract and classify the raw status from the error message
func refreshStatusErr(err error) (code int, transient bool, ok bool) {
    if err == nil { return 0, false, false }
    if n, _ := fmt.Sscanf(err.Error(), "failed to refresh MCP prompts: status code %d", &code); n == 1 {
        return code, code == http.StatusTooManyRequests || code >= 500, true
    }
    return 0, false, false
}

Try / catch

// Fall back to retry for transient statuses, surface otherwise
if err := client.MCPRefreshPrompts(ctx, wsID, name); err != nil {
    if code, transient, ok := refreshStatusErr(err); ok {
        if transient {
            time.Sleep(2 * time.Second)
            return client.MCPRefreshPrompts(ctx, wsID, name)
        }
        return fmt.Errorf("refresh rejected with HTTP %d; verify mcp name and credentials", code)
    }
    return err
}

Prevention

When it happens

Trigger: Calling MCPRefreshPrompts(ctx, id, name) and the server returns any status other than 200 — 400 for an unknown MCP name, 401/403 for missing credentials/permissions, 404 for a bad workspace id, or 5xx from an internal error contacting the actual MCP server.

Common situations: Named MCP client no longer registered on the workspace; token expired after rotation; upstream MCP server down causing the API to return 500; proxy returning 502 during a deploy.

Related errors


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