BloopAI/vibe-kanban · error · ApiError

Failed to save MCP servers

Error message

Failed to save MCP servers

What it means

mcpApi.save POSTs the MCP server configuration to /api/mcp-config; on a non-OK response it parses the JSON body and throws ApiError with errorData.message when the backend supplied one, otherwise this fallback string 'Failed to save MCP servers'. It means the server refused or failed to persist the MCP servers config for the project/profile.

Source

Thrown at packages/web-core/src/shared/lib/api.ts:1095

    const params = new URLSearchParams(query);
    // params.set('profile', profile);
    const response = await makeHostAwareRequest(
      `/api/mcp-config?${params.toString()}`,
      hostId,
      {
        method: 'POST',
        body: JSON.stringify(data),
      }
    );
    if (!response.ok) {
      const errorData = await response.json();
      console.error('[API Error] Failed to save MCP servers', {
        message: errorData.message,
        status: response.status,
        response,
        timestamp: new Date().toISOString(),
      });
      throw new ApiError(
        errorData.message || 'Failed to save MCP servers',
        response.status,
        response
      );
    }
  },
};

// Profiles API
export const profilesApi = {
  load: async (
    hostId?: string | null
  ): Promise<{ content: string; path: string }> => {
    const response = await makeHostAwareRequest('/api/profiles', hostId);
    return handleApiResponse<{ content: string; path: string }>(response);
  },
  save: async (content: string, hostId?: string | null): Promise<string> => {
    const response = await makeHostAwareRequest('/api/profiles', hostId, {

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Check the response.status and any server message logged by the console.error('[API Error]...') output for the precise backend reason
  2. Validate the MCP server entries (command exists, args/env well-formed) before saving
  3. Confirm the backend host is reachable and the project/profile still exists; refresh the host list if using a remote host
  4. Check backend logs and filesystem permissions where the MCP config is written

Example fix

// before
if (!response.ok) {
  const errorData = await response.json();
  ...
  throw new ApiError(errorData.message || 'Failed to save MCP servers', response.status, response);
}
// after
if (!response.ok) {
  const errorData = await response.json().catch(() => ({}));
  throw new ApiError(
    errorData.message || `Failed to save MCP servers (HTTP ${response.status})`,
    response.status,
    response
  );
}
Defensive patterns

Strategy: validation

Validate before calling

function validateMcpServers(data: UpdateMcpServersBody): string | null {
  for (const s of data.servers ?? []) {
    if (!s.command?.trim()) return 'Each MCP server needs a command';
  }
  return null;
}
const err = validateMcpServers(body);
if (err) return showToast(err); // don't call the API

Type guard

function isApiError(e: unknown): e is ApiError {
  return e instanceof ApiError;
}

Try / catch

try {
  await mcpApi.save(query, body, hostId);
} catch (e) {
  if (isApiError(e)) showToast(`MCP save failed (${e.status}): ${e.message}`);
  else showToast('MCP save failed unexpectedly');
}

Prevention

When it happens

Trigger: Saving MCP server settings when the POST /api/mcp-config responds 4xx/5xx: invalid config payload failing backend validation (bad command, missing required fields), malformed JSON body, the target project/profile doesn't exist, or the backend errors writing the config file (permissions, disk). Response body is not valid JSON itself, response.json() will throw before this message is produced.

Common situations: Entering an MCP server command that doesn't exist or invalid env var syntax; editing config for a remote host that is offline (proxy returns 502/504); backend config file owned by another user or read-only filesystem; stale hostId pointing to a removed host.

Related errors


AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29). Data as JSON: /api/errors/7ac360bbfdab904d. Report an issue: GitHub.