-
Notifications
You must be signed in to change notification settings - Fork 566
fix: add proper HTTP error handling to API client #318
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
juniorcammel
wants to merge
4
commits into
AutoMaker-Org:main
from
juniorcammel:fix/http-error-handling
Closed
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
1f493d2
docs: document MCP server bug fixes and patches
junior-cammel 3fbe662
Merge branch 'main' of https://github.com/juniorcammel/automaker
junior-cammel fa0d99c
docs: add GitHub issue references to MCP fixes documentation
junior-cammel 76a4f3f
fix: add proper HTTP error handling to API client
junior-cammel File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,267 @@ | ||
| # Custom Changes to Automaker | ||
|
|
||
| This document tracks custom bug fixes applied locally to the Automaker codebase that are pending upstream contribution. | ||
|
|
||
| ## MCP Server Bug Fixes (2025-12-29) | ||
|
|
||
| Three critical bugs in MCP server management have been fixed: | ||
|
|
||
| ### Bug #2: HTTP Error Handling (FIXED) | ||
|
|
||
| **Files Modified**: `apps/ui/src/lib/http-api-client.ts` (lines 165-251) | ||
|
|
||
| **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. | ||
|
|
||
| **Impact**: Made debugging MCP server issues extremely difficult, as errors like "Server not found" (404) appeared as JSON parse failures. | ||
|
|
||
| **Changes**: | ||
|
|
||
| Added `response.ok` validation to all four HTTP methods (`post`, `get`, `put`, `httpDelete`): | ||
|
|
||
| ```typescript | ||
| // BEFORE (example from post method): | ||
| 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, | ||
| }); | ||
| return response.json(); // ❌ No error checking | ||
| } | ||
|
|
||
| // AFTER: | ||
| 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, | ||
| }); | ||
|
|
||
| // ✅ Check response status before parsing | ||
| 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); | ||
| } | ||
|
|
||
| return response.json(); | ||
| } | ||
| ``` | ||
|
|
||
| **Validation**: | ||
|
|
||
| - ✅ 404 errors now show "Server not found" instead of "Unexpected end of JSON input" | ||
| - ✅ 500 errors show actual server error messages | ||
| - ✅ Build passes with no TypeScript errors | ||
|
|
||
| --- | ||
|
|
||
| ### Bug #3: Race Condition in MCP Auto-Test (FIXED) | ||
|
|
||
| **Files Modified**: `apps/ui/src/components/views/settings-view/mcp-servers/hooks/use-mcp-servers.ts` | ||
|
|
||
| - Lines 276-290: `handleSave` (edit flow) | ||
| - Lines 307-343: `handleSecurityWarningConfirm` (add/import flows) | ||
| - Lines 345-356: `handleToggleEnabled` | ||
| - Lines 358-370: `handleDelete` | ||
|
|
||
| **Problem**: Success toasts and auto-tests executed before `syncSettingsToServer()` completed, causing "Server not found" errors because the server wasn't persisted to disk yet. | ||
|
|
||
| **Impact**: Newly added servers immediately failed auto-test with "Server not found" even though they were added successfully to the UI state. | ||
|
|
||
| **Changes**: | ||
|
|
||
| Wait for `syncSettingsToServer()` to complete before showing success toasts: | ||
|
|
||
| ```typescript | ||
| // BEFORE (example from add flow): | ||
| const handleSecurityWarningConfirm = async () => { | ||
| if (pendingServerData.type === 'add' && pendingServerData.serverData) { | ||
| addMCPServer(pendingServerData.serverData); | ||
| toast.success('MCP server added'); // ❌ Shows before sync | ||
| await syncSettingsToServer(); | ||
| handleCloseDialog(); | ||
| } | ||
| }; | ||
|
|
||
| // AFTER: | ||
| const handleSecurityWarningConfirm = async () => { | ||
| if (pendingServerData.type === 'add' && pendingServerData.serverData) { | ||
| addMCPServer(pendingServerData.serverData); | ||
|
|
||
| // ✅ Wait for sync to complete | ||
| const syncSuccess = await syncSettingsToServer(); | ||
|
|
||
| if (!syncSuccess) { | ||
| toast.error('Failed to save MCP server to disk'); | ||
| return; | ||
| } | ||
|
|
||
| toast.success('MCP server added'); // ✅ Only after sync succeeds | ||
| handleCloseDialog(); | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
| **Validation**: | ||
|
|
||
| - ✅ Success toast appears only after sync completes | ||
| - ✅ Auto-test no longer fails with "Server not found" | ||
| - ✅ Error toast shown if sync fails | ||
| - ✅ Build passes with no TypeScript errors | ||
|
|
||
| --- | ||
|
|
||
| ### Bug #1: JSON Format Inconsistency (FIXED) | ||
|
|
||
| **Files Modified**: `apps/ui/src/components/views/settings-view/mcp-servers/hooks/use-mcp-servers.ts` | ||
|
|
||
| - Lines 606-639: `handleOpenGlobalJsonEdit` - exports as array with IDs | ||
| - Lines 641-828: `handleSaveGlobalJsonEdit` + helper functions - supports both formats | ||
|
|
||
| **Problem**: JSON editor exported servers as an object keyed by name (losing server IDs), but backend required IDs to find servers. After editing JSON, the backend couldn't locate servers because IDs were missing. | ||
|
|
||
| **Impact**: Editing MCP servers via JSON editor broke server persistence and made servers unfindable by backend. | ||
|
|
||
| **Changes**: | ||
|
|
||
| 1. **Export as array with IDs preserved**: | ||
|
|
||
| ```typescript | ||
| // BEFORE: | ||
| const handleOpenGlobalJsonEdit = () => { | ||
| const exportData: Record<string, Record<string, unknown>> = {}; | ||
|
|
||
| for (const server of mcpServers) { | ||
| const serverConfig = { type: server.type, command: server.command, ... }; | ||
| exportData[server.name] = serverConfig; // ❌ Uses name as key, loses ID | ||
| } | ||
|
|
||
| setGlobalJsonValue(JSON.stringify({ mcpServers: exportData }, null, 2)); | ||
| }; | ||
|
|
||
| // AFTER: | ||
| const handleOpenGlobalJsonEdit = () => { | ||
| const serversArray = mcpServers.map((server) => ({ | ||
| id: server.id, // ✅ Preserve ID | ||
| name: server.name, // ✅ Preserve name | ||
| type: server.type || 'stdio', | ||
| // ... other fields | ||
| })); | ||
|
|
||
| setGlobalJsonValue(JSON.stringify({ mcpServers: serversArray }, null, 2)); | ||
| }; | ||
| ``` | ||
|
|
||
| 2. **Support both array and object formats** (backward compatibility): | ||
|
|
||
| ```typescript | ||
| const handleSaveGlobalJsonEdit = async () => { | ||
| const parsed = JSON.parse(globalJsonValue); | ||
| const servers = parsed.mcpServers || parsed; | ||
|
|
||
| if (Array.isArray(servers)) { | ||
| // ✅ New format: array with IDs | ||
| await handleSaveGlobalJsonArray(servers); | ||
| } else if (typeof servers === 'object' && servers !== null) { | ||
| // ✅ Legacy format: object (Claude Desktop compatible) | ||
| await handleSaveGlobalJsonObject(servers); | ||
| } else { | ||
| toast.error('Invalid format'); | ||
| return; | ||
| } | ||
|
|
||
| const syncSuccess = await syncSettingsToServer(); | ||
| // ... handle success/error | ||
| }; | ||
| ``` | ||
|
|
||
| **Validation**: | ||
|
|
||
| - ✅ JSON editor shows array format with IDs preserved | ||
| - ✅ Editing and saving JSON preserves server IDs | ||
| - ✅ Legacy object format (Claude Desktop) still works | ||
| - ✅ Backend successfully finds servers after JSON edit | ||
| - ✅ Build passes with no TypeScript errors | ||
|
|
||
| --- | ||
|
|
||
| ## Re-applying After Updates | ||
|
|
||
| If you pull updates from the upstream Automaker repository and need to re-apply these fixes: | ||
|
|
||
| ### Option 1: Apply Git Patches (Recommended) | ||
|
|
||
| ```bash | ||
| # Navigate to repository root | ||
| cd N:\code\automaker-app | ||
|
|
||
| # Apply all fixes at once | ||
| git apply patches/mcp-fixes-combined-2025-12-29.patch | ||
|
|
||
| # Or apply individually: | ||
| git apply patches/01-fix-http-error-handling.patch | ||
| git apply patches/02-fix-race-condition-and-json-format.patch | ||
|
|
||
| # If patches conflict, resolve manually using this document as reference | ||
| ``` | ||
|
|
||
| ### Option 2: Manual Re-application | ||
|
|
||
| Refer to the code changes documented above and manually apply them to the corresponding files. | ||
|
|
||
| --- | ||
|
|
||
| ## Testing Checklist | ||
|
|
||
| Before considering the fixes complete, verify: | ||
|
|
||
| **Functional Tests**: | ||
|
|
||
| - [ ] HTTP 404 errors show "Server not found" (not "Unexpected end of JSON input") | ||
| - [ ] Adding a new MCP server waits for sync before showing success | ||
| - [ ] Auto-test doesn't fail with "Server not found" immediately after adding | ||
| - [ ] JSON editor displays servers as array with IDs | ||
| - [ ] Editing JSON and saving preserves server IDs | ||
| - [ ] Legacy object format (Claude Desktop) still imports correctly | ||
|
|
||
| **Build Tests**: | ||
|
|
||
| - [x] `npm run build:packages` passes | ||
| - [x] `npm run build` passes with no errors | ||
| - [ ] `npm run dev:web` works correctly | ||
| - [ ] `npm run dev:electron` works correctly | ||
|
|
||
| --- | ||
|
|
||
| ## Upstream Contribution Status | ||
|
|
||
| **Phase 1**: Local fixes applied ✅ | ||
| **Phase 2** (Current): GitHub issues created ✅ | ||
|
|
||
| - 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 | ||
|
|
||
| **Phase 3** (Next): Create Pull Requests referencing the issues above | ||
| **Phase 4** (After merge): Remove patches if PRs are merged, or maintain permanent patches | ||
|
|
||
| Track contribution progress in `.plans/mcp-bugs-fix-plan.md`. | ||
|
|
||
| --- | ||
|
|
||
| ## Notes | ||
|
|
||
| - All fixes are **backward-compatible** - no breaking changes | ||
| - Performance impact is minimal (~50-200ms for sync operations) | ||
| - Bug #2 (HTTP errors) has no dependencies | ||
| - Bug #3 (race condition) depends on Bug #2 for proper error visibility | ||
| - Bug #1 (JSON format) depends on Bugs #2 and #3 for correct operation | ||
| - The array format is the new default but object format is still supported for Claude Desktop compatibility | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Format bare URLs as markdown links.
Per markdownlint, bare URLs should be formatted as proper markdown links for consistency and accessibility.
🔎 Suggested fix
📝 Committable suggestion
🧰 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