feat: add wildcard support for MCP alwaysAllow configuration (#10948)

Co-authored-by: Roo Code <roomote@roocode.com>
This commit is contained in:
roomote[bot] 2026-01-24 22:42:47 -05:00 committed by GitHub
parent c56f0f43c7
commit c28478eda7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 144 additions and 1 deletions

View file

@ -1009,10 +1009,13 @@ export class McpHub {
// Continue with empty configs
}
// Check if wildcard "*" is in the alwaysAllow config
const hasWildcard = alwaysAllowConfig.includes("*")
// Mark tools as always allowed and enabled for prompt based on settings
const tools = (response?.tools || []).map((tool) => ({
...tool,
alwaysAllow: alwaysAllowConfig.includes(tool.name),
alwaysAllow: hasWildcard || alwaysAllowConfig.includes(tool.name),
enabledForPrompt: !disabledToolsList.includes(tool.name),
}))

View file

@ -911,6 +911,146 @@ describe("McpHub", () => {
expect(writtenConfig.mcpServers["test-server"].alwaysAllow).toBeDefined()
expect(writtenConfig.mcpServers["test-server"].alwaysAllow).toContain("new-tool")
})
it("should mark all tools as always allowed when wildcard is present", async () => {
const mockConfig = {
mcpServers: {
"test-server": {
type: "stdio",
command: "node",
args: ["test.js"],
alwaysAllow: ["*"],
},
},
}
// Mock reading config - needs to return for every read
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(mockConfig))
// Set up mock connection with tools
const mockConnection: ConnectedMcpConnection = {
type: "connected",
server: {
name: "test-server",
type: "stdio",
command: "node",
args: ["test.js"],
source: "global",
} as any,
client: {
request: vi.fn().mockResolvedValue({
tools: [
{ name: "tool1", description: "Tool 1" },
{ name: "tool2", description: "Tool 2" },
{ name: "tool3", description: "Tool 3" },
],
}),
} as any,
transport: {} as any,
}
mcpHub.connections = [mockConnection]
// Fetch tools list to test wildcard matching
const tools = await mcpHub["fetchToolsList"]("test-server", "global")
// All tools should be marked as always allowed
expect(tools.length).toBe(3)
expect(tools[0].alwaysAllow).toBe(true)
expect(tools[1].alwaysAllow).toBe(true)
expect(tools[2].alwaysAllow).toBe(true)
})
it("should support both wildcard and specific tool names in alwaysAllow", async () => {
const mockConfig = {
mcpServers: {
"test-server": {
type: "stdio",
command: "node",
args: ["test.js"],
alwaysAllow: ["*", "specific-tool"],
},
},
}
// Mock reading config - needs to return for every read
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(mockConfig))
// Set up mock connection with tools
const mockConnection: ConnectedMcpConnection = {
type: "connected",
server: {
name: "test-server",
type: "stdio",
command: "node",
args: ["test.js"],
source: "global",
} as any,
client: {
request: vi.fn().mockResolvedValue({
tools: [
{ name: "tool1", description: "Tool 1" },
{ name: "specific-tool", description: "Specific Tool" },
],
}),
} as any,
transport: {} as any,
}
mcpHub.connections = [mockConnection]
// Fetch tools list
const tools = await mcpHub["fetchToolsList"]("test-server", "global")
// All tools should be marked as always allowed due to wildcard
expect(tools.length).toBe(2)
expect(tools[0].alwaysAllow).toBe(true)
expect(tools[1].alwaysAllow).toBe(true)
})
it("should only allow specific tools when no wildcard is present", async () => {
const mockConfig = {
mcpServers: {
"test-server": {
type: "stdio",
command: "node",
args: ["test.js"],
alwaysAllow: ["allowed-tool"],
},
},
}
// Mock reading config - needs to return for every read
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(mockConfig))
// Set up mock connection with tools
const mockConnection: ConnectedMcpConnection = {
type: "connected",
server: {
name: "test-server",
type: "stdio",
command: "node",
args: ["test.js"],
source: "global",
} as any,
client: {
request: vi.fn().mockResolvedValue({
tools: [
{ name: "allowed-tool", description: "Allowed Tool" },
{ name: "not-allowed-tool", description: "Not Allowed Tool" },
],
}),
} as any,
transport: {} as any,
}
mcpHub.connections = [mockConnection]
// Fetch tools list
const tools = await mcpHub["fetchToolsList"]("test-server", "global")
// Only the specifically allowed tool should be marked as always allowed
expect(tools.length).toBe(2)
expect(tools[0].alwaysAllow).toBe(true) // allowed-tool
expect(tools[1].alwaysAllow).toBe(false) // not-allowed-tool
})
})
describe("toggleToolEnabledForPrompt", () => {