Skip to content

feat: add exclude and excludeRegex support for tool selectors#1963

Open
majiayu000 wants to merge 5 commits intoenvoyproxy:mainfrom
majiayu000:feat/issue-1921-tool-exclude-filter
Open

feat: add exclude and excludeRegex support for tool selectors#1963
majiayu000 wants to merge 5 commits intoenvoyproxy:mainfrom
majiayu000:feat/issue-1921-tool-exclude-filter

Conversation

@majiayu000
Copy link
Copy Markdown
Contributor

@majiayu000 majiayu000 commented Mar 17, 2026

Description

Add Exclude and ExcludeRegex fields to MCPToolFilter for exclusion-based tool filtering, complementing the existing Include/IncludeRegex fields. Exclude rules take precedence over include rules (deny-wins semantics).

Fixes #1921

Changes

Modified across 4 layers:

  • API types (api/v1alpha1/mcp_route.go): New fields with MaxItems=32 validation. CEL rules enforce mutual exclusivity within include/exclude pairs and require at least one field set.
  • Filter API (internal/filterapi/mcpconfig.go): Mirror fields in MCPToolSelector.
  • Proxy config (internal/mcpproxy/config.go): Compiled exclude map + regexps. allows() checks excludes first for short-circuit denial.
  • Controller (internal/controller/gateway.go): Field mapping from CRD to filterapi.

Test Plan

  • Unit tests for allows(): exclude-only, excludeRegex-only, include+exclude combo, include+excludeRegex combo
  • LoadConfig tests for exclude parsing and invalid regex error handling
  • Controller test for field mapping
  • CRD CEL validation fixtures: valid exclude-only, valid excludeRegex-only, valid include+exclude, invalid exclude+excludeRegex combo
  • make precommit and make test pass

Add Exclude and ExcludeRegex fields to MCPToolFilter to support
exclusion-based tool filtering. Exclude rules take precedence over
include rules (deny-wins model).

Signed-off-by: majiayu000 <1835304752@qq.com>
Signed-off-by: majiayu000 <1835304752@qq.com>
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 17, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.29%. Comparing base (7f77c8a) to head (7720986).
⚠️ Report is 8 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1963      +/-   ##
==========================================
- Coverage   84.22%   82.29%   -1.93%     
==========================================
  Files         128      156      +28     
  Lines       17828    18479     +651     
==========================================
+ Hits        15016    15208     +192     
- Misses       1868     2328     +460     
+ Partials      944      943       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Signed-off-by: majiayu000 <1835304752@qq.com>
@majiayu000 majiayu000 marked this pull request as ready for review March 17, 2026 09:45
@majiayu000 majiayu000 requested a review from a team as a code owner March 17, 2026 09:45
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Mar 17, 2026
@dosubot
Copy link
Copy Markdown

dosubot bot commented Mar 17, 2026

Related Documentation

4 document(s) may need updating based on files changed in this PR:

Envoy's Space

2025-10-02-mcp-implementation /ai-gateway/blob/main/site/blog/2025/2025-10-02-mcp-implementation.md
View Suggested Changes
@@ -35,7 +35,7 @@
 | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
 | **Streamable HTTP Transport**                            | Full support for MCP’s streamable HTTP transport, aligning with the [June 2025 MCP spec](https://modelcontextprotocol.io/specification/2025-06-18).<br/>Efficient handling of stateful sessions and multi-part JSON-RPC messaging over persistent HTTP connections.                                                                                                                                                                |
 | **OAuth Authorization**                                  | Native enforcement of [OAuth authentication flows](https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization) for AI agents and services bridging via MCP, ensuring secure tool usage at scale.<br/>Backwards compatibility with the [previous version of the authorization spec](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization) to maximize compatibility with existing agents. |
-| **MCP Server multiplexing, Tool Routing, and Filtering** | Route tool calls and notifications to the right MCP backends, aggregating and filtering available tools based on gateway policy.<br/>Dynamically aggregate, merge, and filter messages and streaming notifications from multiple MCP servers, so agents receive a unified, policy-governed interface to all available services.                                                                                                    |
+| **MCP Server multiplexing, Tool Routing, and Filtering** | Route tool calls and notifications to the right MCP backends, aggregating and filtering available tools based on gateway policy. Tool filtering supports both inclusion and exclusion patterns with deny-wins semantics (exclusions take precedence).<br/>Dynamically aggregate, merge, and filter messages and streaming notifications from multiple MCP servers, so agents receive a unified, policy-governed interface to all available services.                                                                                                    |
 | **Upstream Authentication**                              | Built-in upstream authentication primitives to securely connect to external MCP servers, with support for credential injection and validation using existing Envoy Gateway patterns.                                                                                                                                                                                                                                               |
 | **Full MCP Spec Coverage**                               | Complete [June 2025 MCP spec](https://modelcontextprotocol.io/specification/2025-06-18) compliance, including support for tool calls, notifications, prompts, resources, and bi-directional server-to-client requests.<br/>Robust session and stream management, including reconnection logic (e.g., Last-Event-ID for SSE), ensuring resilience and correctness for long-lived agent conversations.                               |
 | **Zero Friction Developer and Production UX**            | All features are supported in standalone mode, allowing them to start the Envoy AI Gateway locally on their machine with a single command and start leveraging all MCP features. These configurations can be used as-is in production environments, as there is full compatibility between local standalone mode and Kubernetes.                                                                                                   |
@@ -115,6 +115,10 @@
 }
 ```
 
+:::note
+Tool filtering supports both inclusion patterns (shown above) and exclusion patterns. Exclude rules take precedence over include rules, making it easy to allow broad access while denying specific tools (e.g., allow all except administrative tools).
+:::
+
 ### Using the new MCPRoute API
 
 You can also use the new `MCPRoute` API, which will allow a more fine-grained configuration and will work in standalone mode and in Kubernetes as well.
@@ -146,11 +150,14 @@
       kind: Backend
       group: gateway.envoyproxy.io
       path: "/mcp/readonly" # Use the radonly endpoint
-      # Only expose certain tools
+      # Filter tools using both include and exclude patterns
       toolSelector:
         includeRegex:
           - .*pull_requests?.*
           - .*issues?.*
+        exclude:
+          - issue_create  # Exclude write operations (deny-wins)
+          - issue_update
       # Configure upstream authentication
       securityPolicy:
         apiKey:

[Accept] [Decline]

index /ai-gateway/blob/main/site/docs/capabilities/mcp/index.md
View Suggested Changes
@@ -130,7 +130,9 @@
 
 ### Tool Filtering
 
-Control which tools are exposed using the `toolSelector` field. You can use exact matches or regular expressions:
+Control which tools are exposed using the `toolSelector` field. You can use exact matches or regular expressions with both include-based and exclude-based filtering.
+
+**Include-based filtering** (allowlist):
 
 ```yaml
 apiVersion: aigateway.envoyproxy.io/v1alpha1
@@ -168,8 +170,82 @@
           - query-docs
 ```
 
+**Exclude-based filtering** (denylist):
+
+```yaml
+apiVersion: aigateway.envoyproxy.io/v1alpha1
+kind: MCPRoute
+metadata:
+  name: mcp-route
+  namespace: default
+spec:
+  parentRefs:
+    - name: aigw-run
+      kind: Gateway
+      group: gateway.networking.k8s.io
+  backendRefs:
+    # Expose all tools except specific ones
+    - name: github
+      kind: Backend
+      group: gateway.envoyproxy.io
+      path: "/mcp/x/issues"
+      toolSelector:
+        exclude:
+          - delete_issue
+          - close_issue
+      securityPolicy:
+        apiKey:
+          secretRef:
+            name: github-token
+
+    # Exclude tools matching a pattern
+    - name: internal-backend
+      kind: Backend
+      group: gateway.envoyproxy.io
+      path: "/mcp"
+      toolSelector:
+        excludeRegex:
+          - ^admin_.* # Exclude all tools starting with admin_
+          - .*_delete$ # Exclude all tools ending with _delete
+```
+
+**Combining include and exclude** (with deny-wins semantics):
+
+```yaml
+apiVersion: aigateway.envoyproxy.io/v1alpha1
+kind: MCPRoute
+metadata:
+  name: mcp-route
+  namespace: default
+spec:
+  parentRefs:
+    - name: aigw-run
+      kind: Gateway
+      group: gateway.networking.k8s.io
+  backendRefs:
+    # Include all issue tools except dangerous ones
+    - name: github
+      kind: Backend
+      group: gateway.envoyproxy.io
+      path: "/mcp/x/issues"
+      toolSelector:
+        includeRegex:
+          - .*issue.* # Include all issue-related tools
+        exclude:
+          - delete_issue # But exclude this specific tool
+      securityPolicy:
+        apiKey:
+          secretRef:
+            name: github-token
+```
+
 :::note
-The `toolSelector` field requires exactly one of `include` or `includeRegex` to be specified. If not specified, all tools from the MCP server are exposed.
+The `toolSelector` field requires at least one of `include`, `includeRegex`, `exclude`, or `excludeRegex` to be specified. 
+
+- `include` and `includeRegex` are mutually exclusive
+- `exclude` and `excludeRegex` are mutually exclusive
+- When both include and exclude patterns are specified, a tool must match an include rule AND not match any exclude rule to be allowed (exclude rules take precedence)
+- If not specified, all tools from the MCP server are exposed
 :::
 
 ### Server Multiplexing

[Accept] [Decline]

index /ai-gateway/blob/main/site/versioned_docs/version-0.5/capabilities/mcp/index.md
View Suggested Changes
@@ -130,7 +130,7 @@
 
 ### Tool Filtering
 
-Control which tools are exposed using the `toolSelector` field. You can use exact matches or regular expressions:
+Control which tools are exposed using the `toolSelector` field. You can use exact matches or regular expressions for both inclusion and exclusion:
 
 ```yaml
 apiVersion: aigateway.envoyproxy.io/v1alpha1
@@ -168,8 +168,77 @@
           - query-docs
 ```
 
+#### Include and Exclude Fields
+
+The `toolSelector` supports four fields for controlling tool exposure:
+
+- **`include`**: A list of exact tool names to include (allow)
+- **`includeRegex`**: A list of RE2-compatible regular expressions for tools to include (allow)
+- **`exclude`**: A list of exact tool names to exclude (deny)
+- **`excludeRegex`**: A list of RE2-compatible regular expressions for tools to exclude (deny)
+
+#### Validation Rules
+
+- At least one of `include`, `includeRegex`, `exclude`, or `excludeRegex` must be specified
+- `include` and `includeRegex` are mutually exclusive (you cannot use both in the same selector)
+- `exclude` and `excludeRegex` are mutually exclusive (you cannot use both in the same selector)
+- If `toolSelector` is not specified, all tools from the MCP server are exposed
+
+#### Deny-Wins Semantics
+
+When both include and exclude patterns are specified, exclude rules take precedence (deny-wins). A tool must match an include rule AND not match any exclude rule to be allowed:
+
+1. If a tool matches any exclude pattern, it is denied (regardless of include rules)
+2. If a tool does not match any exclude pattern and matches an include pattern, it is allowed
+3. If no include patterns are specified, all tools are allowed (unless excluded)
+
+#### Examples
+
+**Exclude specific tools by exact name:**
+
+```yaml
+toolSelector:
+  exclude:
+    - dangerous_tool
+    - admin_command
+```
+
+**Exclude tools matching a pattern:**
+
+```yaml
+toolSelector:
+  excludeRegex:
+    - "^internal_.*"  # Excludes all tools starting with "internal_"
+    - ".*_admin$"     # Excludes all tools ending with "_admin"
+```
+
+**Combine include and exclude rules:**
+
+```yaml
+toolSelector:
+  includeRegex:
+    - ".*"              # Include all tools by default
+  exclude:
+    - write_file        # Except these specific tools
+    - delete_resource
+```
+
+**Another combination example:**
+
+```yaml
+toolSelector:
+  include:
+    - read_issues
+    - list_issues
+    - create_issue
+  excludeRegex:
+    - ".*_sensitive$"   # Exclude tools ending with "_sensitive"
+```
+
+In this last example, even if `read_issues_sensitive` were somehow in the include list, it would still be denied because it matches the exclude pattern.
+
 :::note
-The `toolSelector` field requires exactly one of `include` or `includeRegex` to be specified. If not specified, all tools from the MCP server are exposed.
+If `toolSelector` is not specified, all tools from the MCP server are exposed.
 :::
 
 ### Server Multiplexing

[Accept] [Decline]

index /ai-gateway/blob/main/site/versioned_docs/version-0.4/capabilities/mcp/index.md
View Suggested Changes
@@ -130,7 +130,7 @@
 
 ### Tool Filtering
 
-Control which tools are exposed using the `toolSelector` field. You can use exact matches or regular expressions:
+Control which tools are exposed using the `toolSelector` field. You can use exact matches or regular expressions for both inclusion and exclusion:
 
 ```yaml
 apiVersion: aigateway.envoyproxy.io/v1alpha1
@@ -166,10 +166,67 @@
         include:
           - resolve-library-id
           - query-docs
-```
+
+    # Slack: exclude sensitive tools by exact name
+    - name: slack
+      kind: Backend
+      group: gateway.envoyproxy.io
+      path: "/mcp"
+      toolSelector:
+        exclude:
+          - delete-workspace
+          - revoke-admin
+
+    # Database: exclude admin tools using patterns
+    - name: database
+      kind: Backend
+      group: gateway.envoyproxy.io
+      path: "/mcp"
+      toolSelector:
+        excludeRegex:
+          - ^admin_.*
+          - .*_delete$
+```
+
+#### Include and Exclude Rules
+
+The `toolSelector` field supports four types of filters:
+
+- **`include`**: A list of exact tool names to include (allow). Only the specified tools will be available.
+- **`includeRegex`**: A list of RE2-compatible regular expressions. Only tools matching these patterns will be available.
+- **`exclude`**: A list of exact tool names to exclude (deny). The specified tools will not be available.
+- **`excludeRegex`**: A list of RE2-compatible regular expressions. Tools matching these patterns will not be available.
+
+**Validation rules:**
+- At least one of `include`, `includeRegex`, `exclude`, or `excludeRegex` must be specified.
+- `include` and `includeRegex` are mutually exclusive.
+- `exclude` and `excludeRegex` are mutually exclusive.
+- If no `toolSelector` is specified, all tools from the MCP server are exposed.
+
+#### Deny-Wins Semantics
+
+When both include and exclude rules are specified, **exclude rules take precedence** (deny-wins):
+
+```yaml
+# Example: Include all read operations except sensitive ones
+toolSelector:
+  includeRegex:
+    - ^read_.*
+  exclude:
+    - read_credentials
+    - read_secrets
+```
+
+In this example, tools like `read_users` and `read_files` will be allowed, but `read_credentials` and `read_secrets` will be blocked even though they match the include pattern.
+
+**Rule evaluation order:**
+1. If the tool matches any `exclude` or `excludeRegex` rule → **denied**
+2. If include rules exist and the tool matches an `include` or `includeRegex` rule → **allowed**
+3. If include rules exist but the tool doesn't match → **denied**
+4. If no include rules exist → **allowed** (after passing exclude checks)
 
 :::note
-The `toolSelector` field requires exactly one of `include` or `includeRegex` to be specified. If not specified, all tools from the MCP server are exposed.
+Use exclude patterns when you want to expose most tools but block specific ones. Use include patterns when you want to expose only specific tools.
 :::
 
 ### Server Multiplexing

[Accept] [Decline]

Note: You must be authenticated to accept/decline updates.

How did I do? Any feedback?  Join Discord

@nacx
Copy link
Copy Markdown
Member

nacx commented Mar 19, 2026

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces Exclude and ExcludeRegex fields for tool filtering, which is a great enhancement. The changes are well-implemented across the API, controller, and proxy layers, with comprehensive tests and documentation updates. I've identified one high-severity issue related to an unintended side effect in the configuration comparison logic and a medium-severity issue regarding code duplication. Overall, this is a solid contribution.

- Clone regex slices before sorting in sameTools to avoid in-place
  mutation side effects on configuration objects
- Extract compileRegexps helper to deduplicate include/exclude regex
  compilation logic

Signed-off-by: majiayu000 <1835304752@qq.com>
Add unit tests for sameTools covering different exclude keys,
different include/exclude regexps, and exclude regexp ordering.

Signed-off-by: majiayu000 <1835304752@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for exclude and excludeRegex for tools

3 participants