@@ -35,8 +35,8 @@ import { injectVariables } from "../../utils/config"
3535
3636export type McpConnection = {
3737 server : McpServer
38- client : Client
39- transport : StdioClientTransport | SSEClientTransport | StreamableHTTPClientTransport
38+ client : Client | null
39+ transport : StdioClientTransport | SSEClientTransport | StreamableHTTPClientTransport | null
4040}
4141
4242// Base configuration schema for common settings
@@ -553,6 +553,48 @@ export class McpHub {
553553 await this . initializeMcpServers ( "project" )
554554 }
555555
556+ /**
557+ * Creates a placeholder connection for disabled servers or when MCP is globally disabled
558+ * @param name The server name
559+ * @param config The server configuration
560+ * @param source The source of the server (global or project)
561+ * @param reason The reason for creating a placeholder (mcpDisabled or serverDisabled)
562+ * @returns A placeholder McpConnection object
563+ */
564+ private createPlaceholderConnection (
565+ name : string ,
566+ config : z . infer < typeof ServerConfigSchema > ,
567+ source : "global" | "project" ,
568+ reason : "mcpDisabled" | "serverDisabled" ,
569+ ) : McpConnection {
570+ return {
571+ server : {
572+ name,
573+ config : JSON . stringify ( config ) ,
574+ status : "disconnected" ,
575+ disabled : reason === "serverDisabled" ? true : config . disabled ,
576+ source,
577+ projectPath : source === "project" ? vscode . workspace . workspaceFolders ?. [ 0 ] ?. uri . fsPath : undefined ,
578+ errorHistory : [ ] ,
579+ } ,
580+ client : null ,
581+ transport : null ,
582+ }
583+ }
584+
585+ /**
586+ * Checks if MCP is globally enabled
587+ * @returns Promise<boolean> indicating if MCP is enabled
588+ */
589+ private async isMcpEnabled ( ) : Promise < boolean > {
590+ const provider = this . providerRef . deref ( )
591+ if ( ! provider ) {
592+ return true // Default to enabled if provider is not available
593+ }
594+ const state = await provider . getState ( )
595+ return state . mcpEnabled ?? true
596+ }
597+
556598 private async connectToServer (
557599 name : string ,
558600 config : z . infer < typeof ServerConfigSchema > ,
@@ -562,49 +604,18 @@ export class McpHub {
562604 await this . deleteConnection ( name , source )
563605
564606 // Check if MCP is globally enabled
565- const provider = this . providerRef . deref ( )
566- if ( provider ) {
567- const state = await provider . getState ( )
568- const mcpEnabled = state . mcpEnabled ?? true
569-
570- // Skip connecting if MCP is globally disabled
571- if ( ! mcpEnabled ) {
572- // Still create a connection object to track the server, but don't actually connect
573- const connection : McpConnection = {
574- server : {
575- name,
576- config : JSON . stringify ( config ) ,
577- status : "disconnected" ,
578- disabled : config . disabled ,
579- source,
580- projectPath :
581- source === "project" ? vscode . workspace . workspaceFolders ?. [ 0 ] ?. uri . fsPath : undefined ,
582- errorHistory : [ ] ,
583- } ,
584- client : null as any , // We won't actually create a client when MCP is disabled
585- transport : null as any , // We won't actually create a transport when MCP is disabled
586- }
587- this . connections . push ( connection )
588- return
589- }
607+ const mcpEnabled = await this . isMcpEnabled ( )
608+ if ( ! mcpEnabled ) {
609+ // Still create a connection object to track the server, but don't actually connect
610+ const connection = this . createPlaceholderConnection ( name , config , source , "mcpDisabled" )
611+ this . connections . push ( connection )
612+ return
590613 }
591614
592615 // Skip connecting to disabled servers
593616 if ( config . disabled ) {
594617 // Still create a connection object to track the server, but don't actually connect
595- const connection : McpConnection = {
596- server : {
597- name,
598- config : JSON . stringify ( config ) ,
599- status : "disconnected" ,
600- disabled : true ,
601- source,
602- projectPath : source === "project" ? vscode . workspace . workspaceFolders ?. [ 0 ] ?. uri . fsPath : undefined ,
603- errorHistory : [ ] ,
604- } ,
605- client : null as any , // We won't actually create a client for disabled servers
606- transport : null as any , // We won't actually create a transport for disabled servers
607- }
618+ const connection = this . createPlaceholderConnection ( name , config , source , "serverDisabled" )
608619 this . connections . push ( connection )
609620 return
610621 }
@@ -875,8 +886,8 @@ export class McpHub {
875886 // Use the helper method to find the connection
876887 const connection = this . findConnection ( serverName , source )
877888
878- if ( ! connection ) {
879- throw new Error ( `Server ${ serverName } not found` )
889+ if ( ! connection || ! connection . client ) {
890+ throw new Error ( `Server ${ serverName } not found or not connected ` )
880891 }
881892
882893 const response = await connection . client . request ( { method : "tools/list" } , ListToolsResultSchema )
@@ -930,7 +941,7 @@ export class McpHub {
930941 private async fetchResourcesList ( serverName : string , source ?: "global" | "project" ) : Promise < McpResource [ ] > {
931942 try {
932943 const connection = this . findConnection ( serverName , source )
933- if ( ! connection ) {
944+ if ( ! connection || ! connection . client ) {
934945 return [ ]
935946 }
936947 const response = await connection . client . request ( { method : "resources/list" } , ListResourcesResultSchema )
@@ -947,7 +958,7 @@ export class McpHub {
947958 ) : Promise < McpResourceTemplate [ ] > {
948959 try {
949960 const connection = this . findConnection ( serverName , source )
950- if ( ! connection ) {
961+ if ( ! connection || ! connection . client ) {
951962 return [ ]
952963 }
953964 const response = await connection . client . request (
@@ -969,8 +980,12 @@ export class McpHub {
969980
970981 for ( const connection of connections ) {
971982 try {
972- await connection . transport . close ( )
973- await connection . client . close ( )
983+ if ( connection . transport ) {
984+ await connection . transport . close ( )
985+ }
986+ if ( connection . client ) {
987+ await connection . client . close ( )
988+ }
974989 } catch ( error ) {
975990 console . error ( `Failed to close transport for ${ name } :` , error )
976991 }
@@ -1123,16 +1138,9 @@ export class McpHub {
11231138
11241139 async restartConnection ( serverName : string , source ?: "global" | "project" ) : Promise < void > {
11251140 this . isConnecting = true
1126- const provider = this . providerRef . deref ( )
1127- if ( ! provider ) {
1128- return
1129- }
11301141
11311142 // Check if MCP is globally enabled
1132- const state = await provider . getState ( )
1133- const mcpEnabled = state . mcpEnabled ?? true
1134-
1135- // Skip restarting if MCP is globally disabled
1143+ const mcpEnabled = await this . isMcpEnabled ( )
11361144 if ( ! mcpEnabled ) {
11371145 this . isConnecting = false
11381146 return
@@ -1177,26 +1185,20 @@ export class McpHub {
11771185 }
11781186
11791187 // Check if MCP is globally enabled
1180- const provider = this . providerRef . deref ( )
1181- if ( provider ) {
1182- const state = await provider . getState ( )
1183- const mcpEnabled = state . mcpEnabled ?? true
1184-
1185- // Skip refreshing if MCP is globally disabled
1186- if ( ! mcpEnabled ) {
1187- // Clear all existing connections
1188- const existingConnections = [ ...this . connections ]
1189- for ( const conn of existingConnections ) {
1190- await this . deleteConnection ( conn . server . name , conn . server . source )
1191- }
1188+ const mcpEnabled = await this . isMcpEnabled ( )
1189+ if ( ! mcpEnabled ) {
1190+ // Clear all existing connections
1191+ const existingConnections = [ ...this . connections ]
1192+ for ( const conn of existingConnections ) {
1193+ await this . deleteConnection ( conn . server . name , conn . server . source )
1194+ }
11921195
1193- // Still initialize servers to track them, but they won't connect
1194- await this . initializeMcpServers ( "global" )
1195- await this . initializeMcpServers ( "project" )
1196+ // Still initialize servers to track them, but they won't connect
1197+ await this . initializeMcpServers ( "global" )
1198+ await this . initializeMcpServers ( "project" )
11961199
1197- await this . notifyWebviewOfServerChanges ( )
1198- return
1199- }
1200+ await this . notifyWebviewOfServerChanges ( )
1201+ return
12001202 }
12011203
12021204 this . isConnecting = true
@@ -1537,7 +1539,7 @@ export class McpHub {
15371539
15381540 async readResource ( serverName : string , uri : string , source ?: "global" | "project" ) : Promise < McpResourceResponse > {
15391541 const connection = this . findConnection ( serverName , source )
1540- if ( ! connection ) {
1542+ if ( ! connection || ! connection . client ) {
15411543 throw new Error ( `No connection found for server: ${ serverName } ${ source ? ` with source ${ source } ` : "" } ` )
15421544 }
15431545 if ( connection . server . disabled ) {
@@ -1561,7 +1563,7 @@ export class McpHub {
15611563 source ?: "global" | "project" ,
15621564 ) : Promise < McpToolCallResponse > {
15631565 const connection = this . findConnection ( serverName , source )
1564- if ( ! connection ) {
1566+ if ( ! connection || ! connection . client ) {
15651567 throw new Error (
15661568 `No connection found for server: ${ serverName } ${ source ? ` with source ${ source } ` : "" } . Please make sure to use MCP servers available under 'Connected MCP Servers'.` ,
15671569 )
0 commit comments