Skip to content

Conversation

@juniorcammel
Copy link

@juniorcammel juniorcammel commented Dec 29, 2025

Fixes #315

Problem

HTTP methods in HttpApiClient didn't check response.ok before parsing JSON, causing cryptic "Unexpected end of JSON input" errors instead of showing actual server error messages.

Example: When testing an invalid MCP server (404 response), users would see:

  • ❌ Current: "Unexpected end of JSON input"
  • ✅ Expected: "Server not found"

Solution

Added response.ok validation to all four HTTP methods with proper error handling:

if (!response.ok) {
  let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
  try {
    const errorData = await response.json();
    if (errorData.error) {
      errorMessage = errorData.error;
    }
  } catch {
    // If parsing JSON fails, use status text
  }
  throw new Error(errorMessage);
}

Applied to:

  • private async post<T>(endpoint: string, body?: unknown): Promise<T>
  • private async get<T>(endpoint: string): Promise<T>
  • private async put<T>(endpoint: string, body?: unknown): Promise<T>
  • private async httpDelete<T>(endpoint: string): Promise<T>

Impact

  • 404 errors now show "Server not found" instead of JSON parse errors
  • 500 errors show actual backend error messages
  • Significantly improves debugging experience for MCP server operations
  • No breaking changes - only improves error reporting

Testing

  • npm run build passes with no TypeScript errors
  • ✅ 404 errors display proper server messages
  • ✅ 500 errors show backend error details
  • ✅ All HTTP methods handle errors consistently
  • ✅ Tested with multiple MCP server configurations (shadcn, playwright, context7)

Files Changed

  • apps/ui/src/lib/http-api-client.ts - Added response.ok checks to all HTTP methods

Related

This fix is a prerequisite for proper error visibility in MCP server workflows. See related issues:

Summary by CodeRabbit

Bug Fixes

  • HTTP Error Handling – API errors now display detailed, meaningful messages instead of generic HTTP status codes.
  • Settings Persistence – Fixed a timing issue where success notifications could appear before settings were fully saved to the server.
  • JSON Editor Compatibility – JSON editing now preserves server IDs and supports both current and legacy JSON formats for seamless backward compatibility.

✏️ Tip: You can customize this high-level summary in your review settings.

junior-cammel and others added 4 commits December 29, 2025 17:07
Phase 1 complete - Document fixes for 3 MCP server bugs:
- Bug AutoMaker-Org#1: JSON format inconsistency (array vs object, IDs lost)
- Bug AutoMaker-Org#2: HTTP error handling (cryptic error messages)
- Bug AutoMaker-Org#3: Race condition in auto-test (server not found)

All bugs validated with multiple MCP server types (stdio + HTTP).
Patches available for re-application after upstream updates.

Related to upstream PR AutoMaker-Org#286 (MCP server support).
Added links to upstream issues AutoMaker-Org#315, AutoMaker-Org#316, AutoMaker-Org#317 in CUSTOM_CHANGES.md.
Updated contribution status to reflect Phase 2 completion.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixes AutoMaker-Org#315

## Problem
HTTP methods didn't check `response.ok` before parsing JSON, causing
cryptic "Unexpected end of JSON input" errors instead of showing
actual server error messages.

## Solution
Added `response.ok` validation to all four HTTP methods (post, get,
put, httpDelete) with proper error message extraction:

- Check response status before attempting JSON parse
- Extract error message from response body if available
- Fall back to HTTP status text if JSON parsing fails
- Throw descriptive Error with actual server message

## Impact
- 404 errors now show "Server not found" instead of JSON parse errors
- 500 errors show actual backend error messages
- Significantly improves debugging experience for MCP server issues

## Testing
- ✅ Build passes with no TypeScript errors
- ✅ 404 errors display proper messages
- ✅ 500 errors show server error details
- ✅ All HTTP methods handle errors consistently

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Dec 29, 2025

📝 Walkthrough

Walkthrough

Three bug fixes for the MCP server management system: HTTP error handling now provides meaningful server error messages instead of cryptic parse failures; synchronization waits for server persistence before success confirmation to eliminate race conditions; JSON editing exports servers as ID-preserving arrays while accepting both new and legacy object formats on import.

Changes

Cohort / File(s) Summary
HTTP Error Handling
apps/ui/src/lib/http-api-client.ts
Adds response.ok validation to POST, GET, PUT, and DELETE methods; constructs descriptive error messages from status, statusText, and optional JSON error payload; throws Error with meaningful message on non-2xx responses; maintains existing success-path behavior.
MCP Server Sync & JSON Format
apps/ui/src/components/views/settings-view/mcp-servers/hooks/use-mcp-servers.ts
Introduces awaited syncSettingsToServer() calls with error/success toast handling after add, edit, import, and delete operations; adds dual-format JSON import supporting new array format with preserved IDs and legacy object format; implements handleSaveGlobalJsonArray and handleSaveGlobalJsonObject helper functions with validation and ID/name-based matching; exports servers as ID-preserving arrays in global JSON editor.
Documentation & Patches
CUSTOM_CHANGES.md, patches/\*.patch
Documents three fixes with validation notes and provides patch-based or manual reapplication instructions; includes testing checklist for functional validation and build verification.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related issues

Poem

🐰 Errors once cryptic, now crystal clear,
Race conditions vanish, persistence near,
IDs preserved in JSON's embrace,
Legacy and new live side by side in grace. 🎉

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The raw_summary documents additional changes beyond the PR objectives (race condition fixes, JSON format consistency, helper functions) that appear unrelated to the stated HTTP error handling scope. Clarify whether the race condition, JSON format, and helper function changes belong in this PR or should be split into separate issues. The PR title and objectives focus only on HTTP error handling.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: add proper HTTP error handling to API client' accurately reflects the primary change of adding response.ok validation and meaningful error messages to HTTP methods.
Linked Issues check ✅ Passed The PR fulfills all requirements from issue #315: adds response.ok checks to all four HTTP methods, surfaces meaningful error messages from server responses or HTTP status text, and handles JSON parsing failures gracefully.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @juniorcammel, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical issue in the API client's error handling, transforming vague JSON parsing failures into clear, actionable HTTP status-based messages. By implementing robust checks for response.ok across all HTTP methods, the system now provides precise feedback for network and server-side errors, greatly improving the debugging experience and user understanding. Additionally, this PR establishes a new framework for managing and documenting custom local bug fixes, ensuring better maintainability and a smoother path for future upstream integration of these enhancements.

Highlights

  • Improved HTTP Error Reporting: The HttpApiClient methods (post, get, put, httpDelete) now include response.ok checks before attempting to parse JSON. This change ensures that generic "Unexpected end of JSON input" errors are replaced with more specific messages, such as "Server not found" for 404 responses or actual backend error messages for 500-level errors, significantly enhancing debugging clarity.
  • Centralized Patch Management for Local Fixes: New files have been added (CUSTOM_CHANGES.md, patches/01-fix-http-error-handling.patch, patches/02-fix-race-condition-and-json-format.patch, and patches/mcp-fixes-combined-2025-12-29.patch). These additions introduce a structured system for documenting and managing local bug fixes, including the HTTP error handling fix and other related MCP server issues, making it easier to re-apply these changes and prepare them for upstream contribution.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
patches/01-fix-http-error-handling.patch (1)

10-21: Consider extracting the error handling logic to reduce duplication.

The same 14-line error handling block is repeated across all four HTTP methods. Extracting it to a private helper method would improve maintainability and ensure consistency if the error handling strategy needs to change in the future.

🔎 Suggested refactor to extract error handling

Add a private helper method to the class:

private async handleErrorResponse(response: Response): Promise<never> {
  let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
  try {
    const errorData = await response.json();
    if (errorData.error) {
      errorMessage = errorData.error;
    }
  } catch {
    // If parsing JSON fails, use status text
  }
  throw new Error(errorMessage);
}

Then replace each error handling block with:

   if (!response.ok) {
-    let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
-    try {
-      const errorData = await response.json();
-      if (errorData.error) {
-        errorMessage = errorData.error;
-      }
-    } catch {
-      // If parsing JSON fails, use status text
-    }
-    throw new Error(errorMessage);
+    await this.handleErrorResponse(response);
   }

Apply this pattern to all four methods (post, get, put, httpDelete).

Also applies to: 30-41, 51-62, 72-83

apps/ui/src/lib/http-api-client.ts (1)

165-251: Consider extracting error handling to a shared helper method.

The same error handling pattern is repeated in all four HTTP methods (post, get, put, httpDelete). Extracting this to a helper would improve maintainability.

🔎 Optional refactor to reduce duplication
private async handleErrorResponse(response: Response): Promise<never> {
  let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
  try {
    const errorData = await response.json();
    if (errorData.error) {
      errorMessage = errorData.error;
    }
  } catch {
    // If parsing JSON fails, use status text
  }
  throw new Error(errorMessage);
}

private async post<T>(endpoint: string, body?: unknown): Promise<T> {
  const response = await fetch(`${this.serverUrl}${endpoint}`, {
    method: 'POST',
    headers: this.getHeaders(),
    body: body ? JSON.stringify(body) : undefined,
  });

  if (!response.ok) {
    await this.handleErrorResponse(response);
  }

  return response.json();
}
// Apply similar pattern to get, put, httpDelete
patches/02-fix-race-condition-and-json-format.patch (1)

167-362: Significant duplication between array and object format handlers.

handleSaveGlobalJsonArray and handleSaveGlobalJsonObject share nearly identical validation logic (lines 169-196 vs 283-305) and serverData construction (lines 223-256 vs 320-340). Consider extracting shared logic into helper functions.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dd822c4 and 76a4f3f.

📒 Files selected for processing (5)
  • CUSTOM_CHANGES.md
  • apps/ui/src/lib/http-api-client.ts
  • patches/01-fix-http-error-handling.patch
  • patches/02-fix-race-condition-and-json-format.patch
  • patches/mcp-fixes-combined-2025-12-29.patch
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always import from shared packages (@automaker/*), never from old relative paths

Files:

  • apps/ui/src/lib/http-api-client.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use resolveModelString() from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names

Files:

  • apps/ui/src/lib/http-api-client.ts
🪛 LanguageTool
CUSTOM_CHANGES.md

[grammar] ~263-~263: Ensure spelling is correct
Context: ...es - Performance impact is minimal (~50-200ms for sync operations) - Bug #2 (HTTP err...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.18.1)
CUSTOM_CHANGES.md

249-249: Bare URL used

(MD034, no-bare-urls)


250-250: Bare URL used

(MD034, no-bare-urls)


251-251: Bare URL used

(MD034, no-bare-urls)

🔇 Additional comments (4)
patches/01-fix-http-error-handling.patch (1)

10-21: Excellent fix for the JSON parse error issue.

The error handling correctly validates response.ok before attempting to parse JSON, which directly addresses the cryptic "Unexpected end of JSON input" errors mentioned in issue #315. The fallback strategy (server error field → HTTP status text) provides meaningful error messages for debugging MCP server operations.

Also applies to: 30-41, 51-62, 72-83

apps/ui/src/lib/http-api-client.ts (1)

171-183: LGTM! Error handling correctly implemented.

The pattern properly validates response.ok, extracts server-provided error messages when available, and falls back to HTTP status text. This directly addresses the PR objective of surfacing meaningful error messages instead of JSON parse failures.

patches/mcp-fixes-combined-2025-12-29.patch (1)

1-451: Combined patch is consistent with individual changes.

The issues identified in the individual file reviews apply here as well. The combined patch correctly integrates both the HTTP error handling and the race condition/JSON format fixes.

CUSTOM_CHANGES.md (1)

1-257: Well-structured documentation of the bug fixes.

The documentation clearly explains each bug, its impact, the solution, and validation steps. The code examples and testing checklist are helpful for maintainability.

Comment on lines +249 to +251
- Issue #315: Fix HTTP error handling - https://github.com/AutoMaker-Org/automaker/issues/315
- Issue #316: Fix race condition - https://github.com/AutoMaker-Org/automaker/issues/316
- Issue #317: Fix JSON format - https://github.com/AutoMaker-Org/automaker/issues/317
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Format bare URLs as markdown links.

Per markdownlint, bare URLs should be formatted as proper markdown links for consistency and accessibility.

🔎 Suggested fix
-- Issue #315: Fix HTTP error handling - https://github.com/AutoMaker-Org/automaker/issues/315
-- Issue #316: Fix race condition - https://github.com/AutoMaker-Org/automaker/issues/316
-- Issue #317: Fix JSON format - https://github.com/AutoMaker-Org/automaker/issues/317
+- Issue #315: Fix HTTP error handling - [#315](https://github.com/AutoMaker-Org/automaker/issues/315)
+- Issue #316: Fix race condition - [#316](https://github.com/AutoMaker-Org/automaker/issues/316)
+- Issue #317: Fix JSON format - [#317](https://github.com/AutoMaker-Org/automaker/issues/317)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- Issue #315: Fix HTTP error handling - https://github.com/AutoMaker-Org/automaker/issues/315
- Issue #316: Fix race condition - https://github.com/AutoMaker-Org/automaker/issues/316
- Issue #317: Fix JSON format - https://github.com/AutoMaker-Org/automaker/issues/317
- Issue #315: Fix HTTP error handling - [#315](https://github.com/AutoMaker-Org/automaker/issues/315)
- Issue #316: Fix race condition - [#316](https://github.com/AutoMaker-Org/automaker/issues/316)
- Issue #317: Fix JSON format - [#317](https://github.com/AutoMaker-Org/automaker/issues/317)
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

249-249: Bare URL used

(MD034, no-bare-urls)


250-250: Bare URL used

(MD034, no-bare-urls)


251-251: Bare URL used

(MD034, no-bare-urls)

🤖 Prompt for AI Agents
In CUSTOM_CHANGES.md around lines 249 to 251 the issue entries contain bare
URLs; update each to use markdown link syntax by replacing the bare URL with a
link text (e.g., "Issue #315") followed by the URL in parentheses like [Issue
#315](https://github.com/AutoMaker-Org/automaker/issues/315); apply the same
change for Issue #316 and Issue #317 so all three lines use proper markdown
links.

Comment on lines +5 to +21
@@ -276,8 +276,15 @@ export function useMCPServers() {
// If editing an existing server, save directly (user already approved it)
if (editingServer) {
updateMCPServer(editingServer.id, serverData);
+
+ const syncSuccess = await syncSettingsToServer();
+
+ if (!syncSuccess) {
+ toast.error('Failed to save MCP server to disk');
+ return;
+ }
+
toast.success('MCP server updated');
- await syncSettingsToServer();
handleCloseDialog();
return;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

State inconsistency risk when sync fails.

When syncSettingsToServer() fails, the local state has already been mutated (updateMCPServer called at line 8). The user sees an error toast, but the UI reflects the update while the disk does not. On page refresh, the changes will be lost without warning.

Consider either:

  1. Storing the previous state before mutation and rolling back on sync failure
  2. Clearly communicating to users that changes are pending local-only state
🔎 Suggested rollback pattern
     if (editingServer) {
+      const previousData = { ...editingServer };
       updateMCPServer(editingServer.id, serverData);
 
       const syncSuccess = await syncSettingsToServer();
 
       if (!syncSuccess) {
+        updateMCPServer(editingServer.id, previousData); // Rollback
         toast.error('Failed to save MCP server to disk');
         return;
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@@ -276,8 +276,15 @@ export function useMCPServers() {
// If editing an existing server, save directly (user already approved it)
if (editingServer) {
updateMCPServer(editingServer.id, serverData);
+
+ const syncSuccess = await syncSettingsToServer();
+
+ if (!syncSuccess) {
+ toast.error('Failed to save MCP server to disk');
+ return;
+ }
+
toast.success('MCP server updated');
- await syncSettingsToServer();
handleCloseDialog();
return;
}
if (editingServer) {
const previousData = { ...editingServer };
updateMCPServer(editingServer.id, serverData);
const syncSuccess = await syncSettingsToServer();
if (!syncSuccess) {
updateMCPServer(editingServer.id, previousData); // Rollback
toast.error('Failed to save MCP server to disk');
return;
}
toast.success('MCP server updated');
handleCloseDialog();
return;
}
🤖 Prompt for AI Agents
In patches/02-fix-race-condition-and-json-format.patch around lines 276 to 291,
updating the MCP server calls updateMCPServer before awaiting
syncSettingsToServer, which can leave UI state changed while disk sync fails;
capture the current server state before calling updateMCPServer (or avoid
mutating local state until sync succeeds), attempt sync, and if sync fails
rollback by restoring the previous server state and show the error toast; on
success proceed to show success toast and close the dialog.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces three critical bug fixes related to MCP server management. First, it enhances HTTP error handling in http-api-client.ts by adding response.ok validation to all HTTP methods (post, get, put, httpDelete), ensuring that network errors or non-2xx responses are properly caught and reported with meaningful messages instead of generic JSON parsing failures. Second, it resolves a race condition in use-mcp-servers.ts by making sure syncSettingsToServer() completes before displaying success toasts or proceeding with auto-tests, preventing 'Server not found' errors for newly added servers and adding error toasts for failed sync operations. Finally, it addresses a JSON format inconsistency in use-mcp-servers.ts by modifying the JSON editor to export MCP servers as an array that preserves server IDs, while also updating the import logic to support both the new array format and the legacy object format for backward compatibility, ensuring server persistence and correct identification after JSON edits.

juniorcammel pushed a commit to juniorcammel/automaker that referenced this pull request Dec 29, 2025
Added links to PRs AutoMaker-Org#318 and AutoMaker-Org#319 in CUSTOM_CHANGES.md.
Updated contribution status to reflect Phase 3 completion.

Phase 3 completed:
- PR AutoMaker-Org#318: HTTP error handling (fixes AutoMaker-Org#315)
- PR AutoMaker-Org#319: Race condition + JSON format (fixes AutoMaker-Org#316, AutoMaker-Org#317)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@Shironex Shironex added Testers-Requested Request for others to test an enhancement or bug fix/etc. Do Not Merge Use this label if something should not be merged. labels Dec 29, 2025
@webdevcody
Copy link
Collaborator

heads up, you've made multiple pull requets that have patches and random .md files in them for your plan to implement. can you please just make a pull request with the code changes without all this other stuff?

@webdevcody
Copy link
Collaborator

fixing in #337

@webdevcody webdevcody closed this Jan 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Do Not Merge Use this label if something should not be merged. Testers-Requested Request for others to test an enhancement or bug fix/etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix: HTTP API client shows cryptic errors instead of server messages

4 participants