mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
fix(mcp): coerce corrupted consecutiveFailures instead of crashing the whole server list (#5593)
Root cause: updateServerStatus() only fell back to the default status
config when the whole statusConfig column was null/undefined, not when
it was a real object missing consecutiveFailures (e.g. the column's
'{}' default on server creation). currentConfig.consecutiveFailures
was then undefined, undefined + 1 evaluated to NaN, and
JSON.stringify(NaN) persisted as a literal `null` into the DB the
first time a freshly-created server had a connection failure.
That corrupted value then failed listMcpServersContract's Zod parse
client-side (consecutiveFailures: z.number() rejects null), and since
the response is a single array, one bad server blanked the entire MCP
servers list with "Response failed contract validation" for the whole
workspace — currently affecting 81 servers across 69 production
workspaces.
Two fixes:
- service.ts: normalize the read-back statusConfig so
consecutiveFailures is always a real number, never NaN, going
forward.
- contracts/mcp.ts: coerce any non-number consecutiveFailures
(including the already-corrupted `null` rows) to the schema's
default of 0 instead of failing validation, so every
already-affected workspace self-heals on next load with no DB
migration needed.
This commit is contained in:
@@ -38,9 +38,14 @@ export const mcpTransportSchema = z.enum(['streamable-http'])
|
||||
|
||||
export const mcpAuthTypeSchema = z.enum(['none', 'headers', 'oauth'])
|
||||
|
||||
const consecutiveFailuresSchema = z.preprocess(
|
||||
(value) => (typeof value === 'number' ? value : undefined),
|
||||
z.number().default(0)
|
||||
)
|
||||
|
||||
export const mcpServerStatusConfigSchema = z
|
||||
.object({
|
||||
consecutiveFailures: z.number().default(0),
|
||||
consecutiveFailures: consecutiveFailuresSchema,
|
||||
lastSuccessfulDiscovery: z.string().nullable().default(null),
|
||||
})
|
||||
.passthrough()
|
||||
|
||||
@@ -328,11 +328,14 @@ class McpService {
|
||||
)
|
||||
.limit(1)
|
||||
|
||||
const currentConfig: McpServerStatusConfig =
|
||||
(currentServer?.statusConfig as McpServerStatusConfig | null) ?? {
|
||||
consecutiveFailures: 0,
|
||||
lastSuccessfulDiscovery: null,
|
||||
}
|
||||
const storedConfig = currentServer?.statusConfig as Partial<McpServerStatusConfig> | null
|
||||
const currentConfig: McpServerStatusConfig = {
|
||||
consecutiveFailures:
|
||||
typeof storedConfig?.consecutiveFailures === 'number'
|
||||
? storedConfig.consecutiveFailures
|
||||
: 0,
|
||||
lastSuccessfulDiscovery: storedConfig?.lastSuccessfulDiscovery ?? null,
|
||||
}
|
||||
|
||||
const now = new Date()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user