From 74384c81106e37019e50d5015eefdccd996d733d Mon Sep 17 00:00:00 2001 From: Herman Kirshin Date: Mon, 20 Jul 2026 17:17:16 +0300 Subject: [PATCH] DTRC-32091 expose IDE MCP tools to ACP agents when no tool filter is configured McpToolFilter.MaskBased.fromMaskList treated a null mask list the same as an empty/blank one and returned ProhibitAll. ACP agents without an explicit idea_mcp_allowed_tools / mcp.tool.filter resolve their session tool filter to null, so every IDE MCP tool (including the dotTrace analyze tools) was denied and the execute_tool router exposed nothing but itself. This was latent until MCP tool-state filtering was unified to also apply the session filter in VIA_ROUTER mode; previously router mode hardcoded AllowAll, so the null->ProhibitAll mapping had no visible effect. Treat a null mask (no filter configured) as AllowAll, matching the documented "null exposes all tools" contract, while keeping an explicitly empty/blank string as ProhibitAll. The fix lives in the shared community filter, so it covers both the AIA and AIR ACP paths. (cherry picked from commit 1e55c1950ea1630b38061037df5321f01804f2e8) NET-MR-18836 (cherry picked from commit 5249db4a775d13cd4bfcb386ced1474ec22800b3) IJ-CR-216670 GitOrigin-RevId: 235b9d76ff51ababb12935aaa4cc35cef92b1471 --- .../src/com/intellij/mcpserver/McpToolFilter.kt | 13 +++++++++---- .../com/intellij/mcpserver/McpToolFilterTest.kt | 7 +++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/plugins/mcp-server/src/com/intellij/mcpserver/McpToolFilter.kt b/plugins/mcp-server/src/com/intellij/mcpserver/McpToolFilter.kt index 8c4e11a0f2d5..b6748ea3cac8 100644 --- a/plugins/mcp-server/src/com/intellij/mcpserver/McpToolFilter.kt +++ b/plugins/mcp-server/src/com/intellij/mcpserver/McpToolFilter.kt @@ -77,14 +77,19 @@ sealed interface McpToolFilter { companion object { /** - * Creates a MaskBased filter from a mask list string. + * Creates a tool filter from a mask list string. * * @param maskList comma-separated list of mask patterns with +/- prefixes - * @return a new MaskBased filter that denies all if maskList is empty, or AllowAll if null/blank + * @return [AllowAll] when [maskList] is `null` (no filter configured — expose all tools), + * [ProhibitAll] when it is an explicitly empty/blank string (deny all), + * otherwise a [MaskBased] filter built from the patterns. */ fun fromMaskList(maskList: String?): McpToolFilter { - if (maskList.isNullOrBlank()) { - return ProhibitAll // Empty mask = deny all + if (maskList == null) { + return AllowAll // No filter configured = expose all tools + } + if (maskList.isBlank()) { + return ProhibitAll // Explicitly empty mask = deny all } return MaskBased(maskList) } diff --git a/plugins/mcp-server/tests/testSrc/com/intellij/mcpserver/McpToolFilterTest.kt b/plugins/mcp-server/tests/testSrc/com/intellij/mcpserver/McpToolFilterTest.kt index 7bb234752755..f62a28317ec6 100644 --- a/plugins/mcp-server/tests/testSrc/com/intellij/mcpserver/McpToolFilterTest.kt +++ b/plugins/mcp-server/tests/testSrc/com/intellij/mcpserver/McpToolFilterTest.kt @@ -127,6 +127,13 @@ class McpToolFilterTest { assertThat(filter.shouldInclude("read_file")).isFalse() } + @Test + fun `MaskBased fromMaskList returns allow-all filter for null`() { + val filter = McpToolFilter.MaskBased.fromMaskList(null) + + assertThat(filter).isInstanceOf(McpToolFilter.AllowAll::class.java) + } + @Test fun `MaskBased fromMaskList returns prohibit-all filter for empty string`() { val filter = McpToolFilter.MaskBased.fromMaskList("")