charmbracelet/crush · error

failed to list MCP prompts: %w

Error message

failed to list MCP prompts: %w

What it means

ListMCPPrompts GETs /workspaces/{id}/mcp/prompts to enumerate prompts across configured MCP servers. This error wraps any transport failure from c.get before the status code is examined — the HTTP request itself failed.

Source

Thrown at internal/client/config.go:327

	}{Name: name, URI: uri}), http.Header{"Content-Type": []string{"application/json"}})
	if err != nil {
		return nil, fmt.Errorf("failed to read MCP resource: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to read MCP resource: status code %d", rsp.StatusCode)
	}
	var contents []MCPResourceContents
	if err := json.NewDecoder(rsp.Body).Decode(&contents); err != nil {
		return nil, fmt.Errorf("failed to decode MCP resource: %w", err)
	}
	return contents, nil
}

func (c *Client) ListMCPPrompts(ctx context.Context, id string) ([]proto.MCPPrompt, error) {
	rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/mcp/prompts", id), nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to list MCP prompts: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to list MCP prompts: status code %d", rsp.StatusCode)
	}
	var prompts []proto.MCPPrompt
	if err := json.NewDecoder(rsp.Body).Decode(&prompts); err != nil {
		return nil, fmt.Errorf("failed to decode MCP prompts: %w", err)
	}
	return prompts, nil
}

// GetMCPPrompt retrieves a prompt from a named MCP server.
func (c *Client) GetMCPPrompt(ctx context.Context, id, clientID, promptID string, args map[string]string) (string, error) {
	rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/mcp/get-prompt", id), nil, jsonBody(struct {
		ClientID string            `json:"client_id"`
		PromptID string            `json:"prompt_id"`
		Args     map[string]string `json:"args"`

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Verify the Coder server is reachable and the base URL is correct.
  2. Validate the workspace ID before the call.
  3. Inspect the wrapped error for the network root cause.
  4. Retry with a fresh, adequately long context.

Example fix

// before
prompts, err := client.ListMCPPrompts(ctx, id)
// after
prompts, err := client.ListMCPPrompts(ctx, id)
if err != nil {
    if strings.Contains(err.Error(), "connection refused") {
        return nil, fmt.Errorf("coder server unreachable — is it running?")
    }
    return nil, err
}
Defensive patterns

Strategy: retry

Validate before calling

if workspaceID == "" {
    return errors.New("workspace ID is required to list MCP prompts")
}
// optionally confirm server reachability first
if err := pingServer(ctx); err != nil {
    return fmt.Errorf("server unreachable, skipping prompt list: %w", err)
}

Try / catch

ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
defer cancel()
prompts, err := client.ListMCPPrompts(ctx, id)
if err != nil && isTransientNetworkError(err) {
    prompts, err = retryWithBackoff(3, func() ([]proto.MCPPrompt, error) {
        return client.ListMCPPrompts(ctx, id)
    })
}

Prevention

When it happens

Trigger: c.get errors: connection refused, DNS failure, TLS problems, invalid workspace ID producing a bad URL, or a cancelled/expired context.

Common situations: Coder server unreachable; misconfigured client URL; offline environment; test servers (see TestListMCPPrompts*) simulating network failures.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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