on main help sign in
fix(mcp): centrally filter disabled tools (#1622)
43b0e0bAmolith
internal/agent/coordinator.go−6
@@ -407,12 +407,6 @@ func (c *coordinator) buildTools(ctx context.Context, agent config.Agent) ([]fan
407 }
407 }
408
408
409 for _, tool := range tools.GetMCPTools(c.permissions, c.cfg.WorkingDir()) {
409 for _, tool := range tools.GetMCPTools(c.permissions, c.cfg.WorkingDir()) {
410− // Check MCP-specific disabled tools.
411− if mcpCfg, ok := c.cfg.MCP[tool.MCP()]; ok {
412− if slices.Contains(mcpCfg.DisabledTools, tool.MCPToolName()) {
413− continue
414− }
415− }
416 if agent.AllowedMCP == nil {
410 if agent.AllowedMCP == nil {
417 // No MCP restrictions
411 // No MCP restrictions
418 filteredTools = append(filteredTools, tool)
412 filteredTools = append(filteredTools, tool)
internal/agent/tools/mcp/init.go+2−2
@@ -188,12 +188,12 @@ func Initialize(ctx context.Context, permissions permission.Service, cfg *config
188 return
188 return
189 }
189 }
190
190
191− updateTools(name, tools)
191+ toolCount := updateTools(name, tools)
192 updatePrompts(name, prompts)
192 updatePrompts(name, prompts)
193 sessions.Set(name, session)
193 sessions.Set(name, session)
194
194
195 updateState(name, StateConnected, nil, session, Counts{
195 updateState(name, StateConnected, nil, session, Counts{
196− Tools: len(tools),
196+ Tools: toolCount,
197 Prompts: len(prompts),
197 Prompts: len(prompts),
198 })
198 })
199 }(name, m)
199 }(name, m)
internal/agent/tools/mcp/tools.go+25−4
@@ -6,8 +6,10 @@ import (
6 "fmt"
6 "fmt"
7 "iter"
7 "iter"
8 "log/slog"
8 "log/slog"
9+ "slices"
9 "strings"
10 "strings"
10
11
12+ "github.com/charmbracelet/crush/internal/config"
11 "github.com/charmbracelet/crush/internal/csync"
13 "github.com/charmbracelet/crush/internal/csync"
12 "github.com/modelcontextprotocol/go-sdk/mcp"
14 "github.com/modelcontextprotocol/go-sdk/mcp"
13)
15)
@@ -119,10 +121,10 @@ func RefreshTools(ctx context.Context, name string) {
119 return
121 return
120 }
122 }
121
123
122− updateTools(name, tools)
124+ toolCount := updateTools(name, tools)
123
125
124 prev, _ := states.Get(name)
126 prev, _ := states.Get(name)
125− prev.Counts.Tools = len(tools)
127+ prev.Counts.Tools = toolCount
126 updateState(name, StateConnected, nil, session, prev.Counts)
128 updateState(name, StateConnected, nil, session, prev.Counts)
127}
129}
128
130
@@ -137,10 +139,29 @@ func getTools(ctx context.Context, session *mcp.ClientSession) ([]*Tool, error)
137 return result.Tools, nil
139 return result.Tools, nil
138}
140}
139
141
140−func updateTools(name string, tools []*Tool) {
142+func updateTools(name string, tools []*Tool) int {
143+ tools = filterDisabledTools(name, tools)
141 if len(tools) == 0 {
144 if len(tools) == 0 {
142 allTools.Del(name)
145 allTools.Del(name)
143− return
146+ return 0
144 }
147 }
145 allTools.Set(name, tools)
148 allTools.Set(name, tools)
149+ return len(tools)
150+}
151+
152+// filterDisabledTools removes tools that are disabled via config.
153+func filterDisabledTools(mcpName string, tools []*Tool) []*Tool {
154+ cfg := config.Get()
155+ mcpCfg, ok := cfg.MCP[mcpName]
156+ if !ok || len(mcpCfg.DisabledTools) == 0 {
157+ return tools
158+ }
159+
160+ filtered := make([]*Tool, 0, len(tools))
161+ for _, tool := range tools {
162+ if !slices.Contains(mcpCfg.DisabledTools, tool.Name) {
163+ filtered = append(filtered, tool)
164+ }
165+ }
166+ return filtered
146}
167}