@@ -4,7 +4,7 @@ import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js'
44import { db } from '@sim/db'
55import { mcpServers } from '@sim/db/schema'
66import { createLogger } from '@sim/logger'
7- import { describeError , getErrorMessage } from '@sim/utils/errors'
7+ import { getErrorMessage } from '@sim/utils/errors'
88import { sleep } from '@sim/utils/helpers'
99import { backoffWithJitter } from '@sim/utils/retry'
1010import { and , eq , gte , isNull , lt , lte , or } from 'drizzle-orm'
@@ -17,6 +17,7 @@ import {
1717 validateMcpDomain ,
1818 validateMcpServerSsrf ,
1919} from '@/lib/mcp/domain-check'
20+ import { getMcpSafeErrorDiagnostics } from '@/lib/mcp/error-diagnostics'
2021import {
2122 getOrCreateOauthRow ,
2223 loadPreregisteredClient ,
@@ -144,16 +145,6 @@ function getDiscoveryFailureMessage(
144145 return fallback === 'Unknown error' ? 'Connection failed' : fallback
145146}
146147
147- function getSafeErrorDiagnostics ( error : unknown ) {
148- const described = describeError ( error )
149- return {
150- name : described . name ,
151- code : described . code ,
152- errno : described . errno ,
153- syscall : described . syscall ,
154- }
155- }
156-
157148function isTimeoutError ( error : unknown ) : boolean {
158149 if ( error instanceof McpError && error . code === ErrorCode . RequestTimeout ) {
159150 return true
@@ -202,7 +193,7 @@ class McpService {
202193 this . unsubscribeConnectionManager = mcpConnectionManager . subscribe ( ( event ) => {
203194 this . invalidateServerCache ( event . workspaceId , event . serverId ) . catch ( ( error ) => {
204195 logger . warn ( `Failed to invalidate cache for ${ event . serverName } on listChanged` , {
205- error : getSafeErrorDiagnostics ( error ) ,
196+ error : getMcpSafeErrorDiagnostics ( error ) ,
206197 } )
207198 } )
208199 } )
@@ -519,7 +510,43 @@ class McpService {
519510 setEntry : McpCacheMutationSet | null ,
520511 deleteKeys : string [ ]
521512 ) : Promise < boolean > {
522- if ( ! mutation ) return true
513+ if ( ! mutation ) {
514+ const operations = [
515+ ...( setEntry
516+ ? [
517+ {
518+ kind : 'set' ,
519+ run : ( ) => this . cacheAdapter . set ( setEntry . key , setEntry . tools , setEntry . ttlMs ) ,
520+ } ,
521+ ]
522+ : [ ] ) ,
523+ ...deleteKeys . map ( ( key ) => ( {
524+ kind : 'delete' ,
525+ run : ( ) => this . cacheAdapter . delete ( key ) ,
526+ } ) ) ,
527+ ]
528+ const results = await Promise . allSettled (
529+ operations . map ( ( { run } ) => Promise . resolve ( ) . then ( run ) )
530+ )
531+ const failedOperations = results . flatMap ( ( result , index ) =>
532+ result . status === 'rejected'
533+ ? [
534+ {
535+ kind : operations [ index ] . kind ,
536+ error : getMcpSafeErrorDiagnostics ( result . reason ) ,
537+ } ,
538+ ]
539+ : [ ]
540+ )
541+ if ( failedOperations . length > 0 ) {
542+ logger . warn ( `Failed to update cache fallback for server ${ serverId } ` , {
543+ workspaceId,
544+ failedOperations,
545+ } )
546+ }
547+ // Cache availability must not block the authoritative database status.
548+ return true
549+ }
523550 try {
524551 return await this . cacheAdapter . applyMutationIfCurrent (
525552 mutation . scopeKey ,
@@ -530,7 +557,7 @@ class McpService {
530557 } catch ( error ) {
531558 logger . warn ( `Failed to atomically update cache for server ${ serverId } ` , {
532559 workspaceId,
533- error : getSafeErrorDiagnostics ( error ) ,
560+ error : getMcpSafeErrorDiagnostics ( error ) ,
534561 } )
535562 return true
536563 }
@@ -591,15 +618,14 @@ class McpService {
591618 return { scopeKey, id : await this . cacheAdapter . beginMutation ( scopeKey ) }
592619 } catch ( error ) {
593620 logger . warn ( `Failed to order cache mutation for server ${ serverId } ` , {
594- error : getSafeErrorDiagnostics ( error ) ,
621+ error : getMcpSafeErrorDiagnostics ( error ) ,
595622 } )
596623 return null
597624 }
598625 }
599626
600627 private async invalidateServerCache ( workspaceId : string , serverId : string ) : Promise < void > {
601628 const mutation = await this . beginServerCacheMutation ( workspaceId , serverId )
602- if ( ! mutation ) return
603629 await this . applyServerCacheMutation ( workspaceId , serverId , mutation , null , [
604630 serverCacheKey ( workspaceId , serverId ) ,
605631 failureCacheKey ( workspaceId , serverId ) ,
@@ -982,7 +1008,7 @@ class McpService {
9821008 if ( isRetryableDiscoveryError ( error ) && attempt < maxRetries - 1 ) {
9831009 logger . warn (
9841010 `[${ requestId } ] Transient error discovering tools from server ${ serverId } , retrying (attempt ${ attempt + 1 } )` ,
985- { error : getSafeErrorDiagnostics ( error ) }
1011+ { error : getMcpSafeErrorDiagnostics ( error ) }
9861012 )
9871013 await sleep ( backoffWithJitter ( attempt + 1 , null , { baseMs : 250 , maxMs : 2000 } ) )
9881014 continue
0 commit comments