@@ -45,6 +45,7 @@ const BaseConfigSchema = z.object({
4545 timeout : z . number ( ) . min ( 1 ) . max ( 3600 ) . optional ( ) . default ( 60 ) ,
4646 alwaysAllow : z . array ( z . string ( ) ) . default ( [ ] ) ,
4747 watchPaths : z . array ( z . string ( ) ) . optional ( ) , // paths to watch for changes and restart server
48+ disabledTools : z . array ( z . string ( ) ) . default ( [ ] ) ,
4849} )
4950
5051// Custom error messages for better user feedback
@@ -835,34 +836,39 @@ export class McpHub {
835836 const actualSource = connection . server . source || "global"
836837 let configPath : string
837838 let alwaysAllowConfig : string [ ] = [ ]
839+ let disabledToolsList : string [ ] = [ ]
838840
839841 // Read from the appropriate config file based on the actual source
840842 try {
843+ let serverConfigData : Record < string , any > = { }
841844 if ( actualSource === "project" ) {
842845 // Get project MCP config path
843846 const projectMcpPath = await this . getProjectMcpPath ( )
844847 if ( projectMcpPath ) {
845848 configPath = projectMcpPath
846849 const content = await fs . readFile ( configPath , "utf-8" )
847- const config = JSON . parse ( content )
848- alwaysAllowConfig = config . mcpServers ?. [ serverName ] ?. alwaysAllow || [ ]
850+ serverConfigData = JSON . parse ( content )
849851 }
850852 } else {
851853 // Get global MCP settings path
852854 configPath = await this . getMcpSettingsFilePath ( )
853855 const content = await fs . readFile ( configPath , "utf-8" )
854- const config = JSON . parse ( content )
855- alwaysAllowConfig = config . mcpServers ?. [ serverName ] ?. alwaysAllow || [ ]
856+ serverConfigData = JSON . parse ( content )
857+ }
858+ if ( serverConfigData ) {
859+ alwaysAllowConfig = serverConfigData . mcpServers ?. [ serverName ] ?. alwaysAllow || [ ]
860+ disabledToolsList = serverConfigData . mcpServers ?. [ serverName ] ?. disabledTools || [ ]
856861 }
857862 } catch ( error ) {
858- console . error ( `Failed to read alwaysAllow config for ${ serverName } :` , error )
859- // Continue with empty alwaysAllowConfig
863+ console . error ( `Failed to read tool configuration for ${ serverName } :` , error )
864+ // Continue with empty configs
860865 }
861866
862- // Mark tools as always allowed based on settings
867+ // Mark tools as always allowed and enabled for prompt based on settings
863868 const tools = ( response ?. tools || [ ] ) . map ( ( tool ) => ( {
864869 ...tool ,
865870 alwaysAllow : alwaysAllowConfig . includes ( tool . name ) ,
871+ enabledForPrompt : ! disabledToolsList . includes ( tool . name ) ,
866872 } ) )
867873
868874 return tools
@@ -1491,83 +1497,114 @@ export class McpHub {
14911497 )
14921498 }
14931499
1494- async toggleToolAlwaysAllow (
1500+ /**
1501+ * Helper method to update a specific tool list (alwaysAllow or disabledTools)
1502+ * in the appropriate settings file.
1503+ * @param serverName The name of the server to update
1504+ * @param source Whether to update the global or project config
1505+ * @param toolName The name of the tool to add or remove
1506+ * @param listName The name of the list to modify ("alwaysAllow" or "disabledTools")
1507+ * @param addTool Whether to add (true) or remove (false) the tool from the list
1508+ */
1509+ private async updateServerToolList (
14951510 serverName : string ,
14961511 source : "global" | "project" ,
14971512 toolName : string ,
1498- shouldAllow : boolean ,
1513+ listName : "alwaysAllow" | "disabledTools" ,
1514+ addTool : boolean ,
14991515 ) : Promise < void > {
1500- try {
1501- // Find the connection with matching name and source
1502- const connection = this . findConnection ( serverName , source )
1516+ // Find the connection with matching name and source
1517+ const connection = this . findConnection ( serverName , source )
15031518
1504- if ( ! connection ) {
1505- throw new Error ( `Server ${ serverName } with source ${ source } not found` )
1506- }
1519+ if ( ! connection ) {
1520+ throw new Error ( `Server ${ serverName } with source ${ source } not found` )
1521+ }
15071522
1508- // Determine the correct config path based on the source
1509- let configPath : string
1510- if ( source === "project" ) {
1511- // Get project MCP config path
1512- const projectMcpPath = await this . getProjectMcpPath ( )
1513- if ( ! projectMcpPath ) {
1514- throw new Error ( "Project MCP configuration file not found" )
1515- }
1516- configPath = projectMcpPath
1517- } else {
1518- // Get global MCP settings path
1519- configPath = await this . getMcpSettingsFilePath ( )
1523+ // Determine the correct config path based on the source
1524+ let configPath : string
1525+ if ( source === "project" ) {
1526+ // Get project MCP config path
1527+ const projectMcpPath = await this . getProjectMcpPath ( )
1528+ if ( ! projectMcpPath ) {
1529+ throw new Error ( "Project MCP configuration file not found" )
15201530 }
1531+ configPath = projectMcpPath
1532+ } else {
1533+ // Get global MCP settings path
1534+ configPath = await this . getMcpSettingsFilePath ( )
1535+ }
15211536
1522- // Normalize path for cross-platform compatibility
1523- // Use a consistent path format for both reading and writing
1524- const normalizedPath = process . platform === "win32" ? configPath . replace ( / \\ / g, "/" ) : configPath
1537+ // Normalize path for cross-platform compatibility
1538+ // Use a consistent path format for both reading and writing
1539+ const normalizedPath = process . platform === "win32" ? configPath . replace ( / \\ / g, "/" ) : configPath
15251540
1526- // Read the appropriate config file
1527- const content = await fs . readFile ( normalizedPath , "utf-8" )
1528- const config = JSON . parse ( content )
1541+ // Read the appropriate config file
1542+ const content = await fs . readFile ( normalizedPath , "utf-8" )
1543+ const config = JSON . parse ( content )
15291544
1530- // Initialize mcpServers if it doesn't exist
1531- if ( ! config . mcpServers ) {
1532- config . mcpServers = { }
1533- }
1545+ if ( ! config . mcpServers ) {
1546+ config . mcpServers = { }
1547+ }
15341548
1535- // Initialize server config if it doesn't exist
1536- if ( ! config . mcpServers [ serverName ] ) {
1537- config . mcpServers [ serverName ] = {
1538- type : "stdio" ,
1539- command : "node" ,
1540- args : [ ] , // Default to an empty array; can be set later if needed
1541- }
1549+ if ( ! config . mcpServers [ serverName ] ) {
1550+ config . mcpServers [ serverName ] = {
1551+ type : "stdio" ,
1552+ command : "node" ,
1553+ args : [ ] , // Default to an empty array; can be set later if needed
15421554 }
1555+ }
15431556
1544- // Initialize alwaysAllow if it doesn't exist
1545- if ( ! config . mcpServers [ serverName ] . alwaysAllow ) {
1546- config . mcpServers [ serverName ] . alwaysAllow = [ ]
1547- }
1557+ if ( ! config . mcpServers [ serverName ] [ listName ] ) {
1558+ config . mcpServers [ serverName ] [ listName ] = [ ]
1559+ }
15481560
1549- const alwaysAllow = config . mcpServers [ serverName ] . alwaysAllow
1550- const toolIndex = alwaysAllow . indexOf ( toolName )
1561+ const targetList = config . mcpServers [ serverName ] [ listName ]
1562+ const toolIndex = targetList . indexOf ( toolName )
15511563
1552- if ( shouldAllow && toolIndex === - 1 ) {
1553- // Add tool to always allow list
1554- alwaysAllow . push ( toolName )
1555- } else if ( ! shouldAllow && toolIndex !== - 1 ) {
1556- // Remove tool from always allow list
1557- alwaysAllow . splice ( toolIndex , 1 )
1558- }
1564+ if ( addTool && toolIndex === - 1 ) {
1565+ targetList . push ( toolName )
1566+ } else if ( ! addTool && toolIndex !== - 1 ) {
1567+ targetList . splice ( toolIndex , 1 )
1568+ }
15591569
1560- // Write updated config back to file
1561- await fs . writeFile ( normalizedPath , JSON . stringify ( config , null , 2 ) )
1570+ await fs . writeFile ( normalizedPath , JSON . stringify ( config , null , 2 ) )
15621571
1563- // Update the tools list to reflect the change
1564- if ( connection ) {
1565- // Explicitly pass the source to ensure we're updating the correct server's tools
1566- connection . server . tools = await this . fetchToolsList ( serverName , source )
1567- await this . notifyWebviewOfServerChanges ( )
1568- }
1572+ if ( connection ) {
1573+ connection . server . tools = await this . fetchToolsList ( serverName , source )
1574+ await this . notifyWebviewOfServerChanges ( )
1575+ }
1576+ }
1577+
1578+ async toggleToolAlwaysAllow (
1579+ serverName : string ,
1580+ source : "global" | "project" ,
1581+ toolName : string ,
1582+ shouldAllow : boolean ,
1583+ ) : Promise < void > {
1584+ try {
1585+ await this . updateServerToolList ( serverName , source , toolName , "alwaysAllow" , shouldAllow )
1586+ } catch ( error ) {
1587+ this . showErrorMessage (
1588+ `Failed to toggle always allow for tool "${ toolName } " on server "${ serverName } " with source "${ source } "` ,
1589+ error ,
1590+ )
1591+ throw error
1592+ }
1593+ }
1594+
1595+ async toggleToolEnabledForPrompt (
1596+ serverName : string ,
1597+ source : "global" | "project" ,
1598+ toolName : string ,
1599+ isEnabled : boolean ,
1600+ ) : Promise < void > {
1601+ try {
1602+ // When isEnabled is true, we want to remove the tool from the disabledTools list.
1603+ // When isEnabled is false, we want to add the tool to the disabledTools list.
1604+ const addToolToDisabledList = ! isEnabled
1605+ await this . updateServerToolList ( serverName , source , toolName , "disabledTools" , addToolToDisabledList )
15691606 } catch ( error ) {
1570- this . showErrorMessage ( `Failed to update always allow settings for tool ${ toolName } ` , error )
1607+ this . showErrorMessage ( `Failed to update settings for tool ${ toolName } ` , error )
15711608 throw error // Re-throw to ensure the error is properly handled
15721609 }
15731610 }
0 commit comments