fix(mcp): keep a legacy server row from blanking the whole server list#5762
Conversation
The server-list response validated transport/authType/connectionStatus with strict enums, but those columns are free text and can hold legacy values (e.g. transport 'http'/'sse' from before the streamable-http consolidation, including rows copied verbatim by workspace fork). Since the client strict- parses the whole array with retry:false, a single off-enum row blanked the entire workspace's MCP list. - Tolerate off-enum values in the response via Zod .catch() (request bodies stay strict): transport -> streamable-http, authType/connectionStatus -> undefined - Stop the workspace-fork copy from propagating legacy transport values - Reset connection status on a headers->OAuth flip in the create/upsert path, mirroring the update path (kills a false "connected" state) - Drop the positive tool cache on OAuth-pending in bulk discovery, matching the single-server path (no stale tools after re-auth is required)
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Response validation now tolerates bad stored values on list/read paths only (create/update/test bodies stay strict): Workspace fork copies MCP servers with Also aligns two MCP lifecycle edge cases with existing update/single-server behavior: create/upsert resets connection state and revokes OAuth when auth type flips (e.g. OAuth → headers), and bulk tool discovery deletes the positive tool cache when a server hits OAuth-pending so force-refresh cannot serve stale tools. Reviewed by Cursor Bugbot for commit 40a5552. Configure here. |
Greptile SummaryThis PR fixes a production outage where a single MCP server row with a legacy
Confidence Score: 5/5Safe to merge — changes are narrowly scoped Zod coercions and mirrored logic from already-tested update paths, with 149 passing tests covering the new branches. All three schema tolerances are additive (request schemas stay strict), the auth-type reset logic mirrors the already-correct update path, and the OAuth-pending cache eviction follows the identical guard used by the single-server failure path. No files require special attention. Important Files Changed
Reviews (2): Last reviewed commit: "fix(mcp): reset connection status on any..." | Re-trigger Greptile |
…/upsert path The non-OAuth branch optimistically marked the server connected on an oauth->headers flip, leaving a stale lastError and diverging from performUpdateMcpServer. Mirror the update path exactly: reset to disconnected and clear lastError on an auth-type flip or OAuth URL/creds change; only mark connected for a non-OAuth (re-)registration with unchanged auth. Adds a create-path regression test.
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 40a5552. Configure here.
Summary
transport/authType/connectionStatuswith strict enums, but those are free-text DB columns that can hold legacy values (e.g.transporthttp/ssefrom before the streamable-http consolidation). Because the client strict-parses the wholez.array(...)withretry:false, one off-enum row blanked the entire workspace's MCP list ("Response failed contract validation").sse/http) across 11 workspaces. Same class as fix(mcp): coerce corrupted consecutiveFailures instead of crashing the whole server list #5593, which only coveredconsecutiveFailures..catch()tolerance on all three strict-enum-over-free-text columns (request bodies stay strict) —transport→streamable-http,authType/connectionStatus→undefined. Uses Zod's built-in.catch(), matching the existing pattern incontracts/admin.ts.transportvalues (the still-active vector that regenerated bad rows).Type of Change
Testing
lib/api/contracts,app/api/mcp/servers,lib/mcp, andee/workspace-forking; typecheck, Biome, andcheck:api-validationall clean.transport.Follow-up (not in this PR)
.catch()es close the entire present class, so this is future-proofing only.Checklist