feat: add exclude and excludeRegex support for tool selectors - #1963
Conversation
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 Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1963 +/- ##
==========================================
+ Coverage 84.35% 84.40% +0.04%
==========================================
Files 130 130
Lines 18068 18104 +36
==========================================
+ Hits 15242 15280 +38
+ Misses 1878 1877 -1
+ Partials 948 947 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Signed-off-by: majiayu000 <1835304752@qq.com>
|
Documentation Updates 3 document(s) were updated by changes in this PR: indexView Changes@@ -169,8 +169,55 @@
```
:::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. You cannot specify both `include` and `includeRegex` together, nor both `exclude` and `excludeRegex` together. If not specified, all tools from the MCP server are exposed.
:::
+
+You can also use exclusion patterns to block specific tools or patterns:
+
+- **`exclude`**: A list of exact tool names to exclude. The specified tools will not be available.
+- **`excludeRegex`**: A list of RE2-compatible regular expressions that, when matched, exclude the tool. Tools matching these patterns will not be available.
+
+Exclude rules take precedence over include rules (deny-wins semantics). When both include and exclude patterns are specified, a tool must match an include rule AND not match any exclude rule to be allowed.
+
+```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:
+ # Allow all tools except dangerous ones
+ - name: github
+ kind: Backend
+ group: gateway.envoyproxy.io
+ path: "/mcp/x/issues"
+ toolSelector:
+ include:
+ - issue_read
+ - issue_list
+ - issue_write
+ exclude:
+ - issue_write # Deny-wins: even though listed in include, this tool is blocked
+ securityPolicy:
+ apiKey:
+ secretRef:
+ name: github-token
+
+ # Exclude tools matching a pattern
+ - name: context7
+ kind: Backend
+ group: gateway.envoyproxy.io
+ path: "/mcp"
+ toolSelector:
+ excludeRegex:
+ - ^admin_.* # Block all admin tools
+ - .*delete.* # Block any tools with "delete" in the name
+```
### Server Multiplexing
indexView Changes@@ -169,8 +169,51 @@
```
:::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. You cannot specify both `include` and `includeRegex` together, nor both `exclude` and `excludeRegex` together. If not specified, all tools from the MCP server are exposed.
:::
+
+**Excluding Tools**
+
+You can also exclude specific tools or patterns while allowing others:
+
+```yaml
+# Exclude specific tools by exact name
+- name: github
+ kind: Backend
+ group: gateway.envoyproxy.io
+ path: "/mcp/x/issues/readonly"
+ toolSelector:
+ exclude:
+ - delete_issue
+ - close_issue
+ securityPolicy:
+ apiKey:
+ secretRef:
+ name: github-token
+
+# Exclude tools matching a pattern
+- name: internal-tools
+ kind: Backend
+ group: gateway.envoyproxy.io
+ path: "/mcp"
+ toolSelector:
+ excludeRegex:
+ - ^internal_.* # Excludes all tools starting with "internal_"
+
+# Combine include and exclude (exclude takes precedence)
+- name: mcp-service
+ kind: Backend
+ group: gateway.envoyproxy.io
+ path: "/mcp"
+ toolSelector:
+ include:
+ - read
+ - write
+ exclude:
+ - write # Only "read" will be available
+```
+
+When both include and exclude patterns are specified, exclude rules take precedence (deny-wins semantics). A tool must match an include rule AND not match any exclude rule to be allowed.
### Server Multiplexing
indexView Changes@@ -168,8 +168,59 @@
- query-docs
```
+The `toolSelector` supports both inclusion and exclusion patterns:
+
+- **`include`**: A list of exact tool names to include. Only the specified tools will be available.
+- **`includeRegex`**: A list of RE2-compatible regular expressions that, when matched, include the tool. Only tools matching these patterns will be available.
+- **`exclude`**: A list of exact tool names to exclude. The specified tools will not be available.
+- **`excludeRegex`**: A list of RE2-compatible regular expressions that, when matched, exclude the tool. Tools matching these patterns will not be available.
+
+Exclude rules take precedence over include rules (deny-wins semantics). When both include and exclude patterns are specified, a tool must match an include rule AND not match any exclude rule to be allowed.
+
+**Example using exclude patterns:**
+
+```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:
+ # GitHub: allow all tools except dangerous ones
+ - name: github
+ kind: Backend
+ group: gateway.envoyproxy.io
+ path: "/mcp/x/issues/readonly"
+ toolSelector:
+ excludeRegex:
+ - .*delete.* # Block any tools with "delete" in the name
+ - .*admin.* # Block any admin tools
+ securityPolicy:
+ apiKey:
+ secretRef:
+ name: github-token
+
+ # Context7: allow specific tools but exclude one
+ - name: context7
+ kind: Backend
+ group: gateway.envoyproxy.io
+ path: "/mcp"
+ toolSelector:
+ include:
+ - read-docs
+ - write-docs
+ - admin-reset
+ exclude:
+ - admin-reset # Exclude this specific tool even though it's in include
+```
+
:::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. You cannot specify both `include` and `includeRegex` together, nor both `exclude` and `excludeRegex` together. If not specified, all tools from the MCP server are exposed.
:::
### Server Multiplexing |
|
/gemini review |
There was a problem hiding this comment.
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>
|
Can you format the code to fix the style checks? |
Signed-off-by: majiayu000 <1835304752@qq.com>
|
fixed — ran gofmt on the test file, was just struct field alignment. |
|
/retest |
**Description** Draft release notes for the v0.6.x series, mirroring the existing v0.5 layout. Filed as a draft so reviewers can correct and refine content while v0.6.0 is still in RC. **Three commits:** 1. `build: exclude .git, .claude, .cursor from license-eye` — small drive-by tooling fix. license-eye walks the entire repo and, on checkouts that contain extra metadata under `.git/worktrees/`, `.claude/`, or `.cursor/`, it descends into them, hits unsupported file types, and exits non-zero — failing `make precommit` for changes that don't touch any source code. None of these directories ever contain license-bearing project sources, so they belong in `paths-ignore`. Happy to split this into its own PR if preferred. 2. `site: v0.6 release notes` — the rendered release notes (JSON data, MDX page, navigation, index card). 3. `release-notes: add plain-markdown copy of v0.6.0 notes` — adds a new top-level `release-notes/` directory with `v0.6.0.md`, a self-contained plain-markdown rendering of the same content for direct copy-paste into the GitHub release body. Sits alongside `RELEASES.md` (the release process doc). ### Notable content **Breaking change** — AIGatewayRoute `filterConfig` field has been removed (#1900). Migration guidance to `GatewayConfig` is in the **Upgrade Guidance** section of `v0.6.mdx` (and mirrored in `release-notes/v0.6.0.md`). **Highlights:** - Core CRDs + MCPRoute promoted to `v1beta1` (#1900, #2090) - AWS Bedrock InvokeModel for Claude (#1648), OpenAI ↔ Bedrock embeddings (#1969) - Anthropic endpoint on OpenAI backends (#1878), structured output for Claude (#1846) - Gemini embeddings (#1625), prefix-style context caching (#1792) - MCP per-backend ForwardHeaders (#2047), JWT claim forwarding (#1815), tool-selector excludes (#1963) - GKE Workload Identity via ADC (#1979), webhook host network (#1954) - Request/response body redaction (#1758), OTLP access logging in `aigw` (#1832) - Responses API phase 2 (#1791), Open Responses API compat (#1847), batch inference (#1779) - Dependencies: Go 1.26.2, Envoy Gateway v1.7.0, Envoy v1.37, Gateway API v1.4.1, MCP Go SDK 1.4.1 ### Test plan - [x] `cd site && npm install && npm run build` — completes successfully (only warnings are pre-existing broken anchors in old docs versions, none on the new pages) - [x] `npm run start` — confirmed `/release-notes/` features v0.6.x with the "Latest" badge and demotes v0.5.x; `/release-notes/v0.6` renders all sections (Features, API Updates, Breaking Changes, Bug Fixes, Upgrade Guidance, Dependencies, Patch Releases placeholder, Acknowledgements, What's Next) with no console errors - [x] `release-notes/v0.6.0.md` reviewed for self-containment (no MDX residue, no `<code>` tags, links to rendered version included) - [x] `make precommit` passes on this branch (after the license-eye fix) **Related Issues/PRs (if applicable)** None directly. Cross-references to the individual feature/fix PRs are inline in the release-notes content above. **Special notes for reviewers (if applicable)** - Release date is currently a placeholder (`May 15, 2026`). Update both the JSON (`site/src/data/releases/v0.6.json`) and the `release-notes/v0.6.0.md` heading area before merge to the actual `v0.6.0` final tag date. - Any commits landing between this draft and the tag should be folded in — the JSON, MDX, and the plain-markdown copy each need updating; happy to script this into the existing release-notes workflow if maintainers want. - Each item was cross-checked against `api/v1alpha1/`, `internal/translator/`, `internal/extproc/`, `internal/controller/`, and `internal/backendauth/` per the existing release-notes workflow, but a fresh pair of eyes on accuracy is very welcome — call out anything that's mischaracterized, missing, or shouldn't be there. - Drafted with AI assistance (Claude Code) following the existing v0.5 release-notes pattern; every item was cross-checked against the source PRs before inclusion. --------- Signed-off-by: Erica Hughberg <erica.sundberg.90@gmail.com>
**Description** Draft release notes for the v0.6.x series, mirroring the existing v0.5 layout. Filed as a draft so reviewers can correct and refine content while v0.6.0 is still in RC. **Three commits:** 1. `build: exclude .git, .claude, .cursor from license-eye` — small drive-by tooling fix. license-eye walks the entire repo and, on checkouts that contain extra metadata under `.git/worktrees/`, `.claude/`, or `.cursor/`, it descends into them, hits unsupported file types, and exits non-zero — failing `make precommit` for changes that don't touch any source code. None of these directories ever contain license-bearing project sources, so they belong in `paths-ignore`. Happy to split this into its own PR if preferred. 2. `site: v0.6 release notes` — the rendered release notes (JSON data, MDX page, navigation, index card). 3. `release-notes: add plain-markdown copy of v0.6.0 notes` — adds a new top-level `release-notes/` directory with `v0.6.0.md`, a self-contained plain-markdown rendering of the same content for direct copy-paste into the GitHub release body. Sits alongside `RELEASES.md` (the release process doc). ### Notable content **Breaking change** — AIGatewayRoute `filterConfig` field has been removed (envoyproxy#1900). Migration guidance to `GatewayConfig` is in the **Upgrade Guidance** section of `v0.6.mdx` (and mirrored in `release-notes/v0.6.0.md`). **Highlights:** - Core CRDs + MCPRoute promoted to `v1beta1` (envoyproxy#1900, envoyproxy#2090) - AWS Bedrock InvokeModel for Claude (envoyproxy#1648), OpenAI ↔ Bedrock embeddings (envoyproxy#1969) - Anthropic endpoint on OpenAI backends (envoyproxy#1878), structured output for Claude (envoyproxy#1846) - Gemini embeddings (envoyproxy#1625), prefix-style context caching (envoyproxy#1792) - MCP per-backend ForwardHeaders (envoyproxy#2047), JWT claim forwarding (envoyproxy#1815), tool-selector excludes (envoyproxy#1963) - GKE Workload Identity via ADC (envoyproxy#1979), webhook host network (envoyproxy#1954) - Request/response body redaction (envoyproxy#1758), OTLP access logging in `aigw` (envoyproxy#1832) - Responses API phase 2 (envoyproxy#1791), Open Responses API compat (envoyproxy#1847), batch inference (envoyproxy#1779) - Dependencies: Go 1.26.2, Envoy Gateway v1.7.0, Envoy v1.37, Gateway API v1.4.1, MCP Go SDK 1.4.1 ### Test plan - [x] `cd site && npm install && npm run build` — completes successfully (only warnings are pre-existing broken anchors in old docs versions, none on the new pages) - [x] `npm run start` — confirmed `/release-notes/` features v0.6.x with the "Latest" badge and demotes v0.5.x; `/release-notes/v0.6` renders all sections (Features, API Updates, Breaking Changes, Bug Fixes, Upgrade Guidance, Dependencies, Patch Releases placeholder, Acknowledgements, What's Next) with no console errors - [x] `release-notes/v0.6.0.md` reviewed for self-containment (no MDX residue, no `<code>` tags, links to rendered version included) - [x] `make precommit` passes on this branch (after the license-eye fix) **Related Issues/PRs (if applicable)** None directly. Cross-references to the individual feature/fix PRs are inline in the release-notes content above. **Special notes for reviewers (if applicable)** - Release date is currently a placeholder (`May 15, 2026`). Update both the JSON (`site/src/data/releases/v0.6.json`) and the `release-notes/v0.6.0.md` heading area before merge to the actual `v0.6.0` final tag date. - Any commits landing between this draft and the tag should be folded in — the JSON, MDX, and the plain-markdown copy each need updating; happy to script this into the existing release-notes workflow if maintainers want. - Each item was cross-checked against `api/v1alpha1/`, `internal/translator/`, `internal/extproc/`, `internal/controller/`, and `internal/backendauth/` per the existing release-notes workflow, but a fresh pair of eyes on accuracy is very welcome — call out anything that's mischaracterized, missing, or shouldn't be there. - Drafted with AI assistance (Claude Code) following the existing v0.5 release-notes pattern; every item was cross-checked against the source PRs before inclusion. --------- Signed-off-by: Erica Hughberg <erica.sundberg.90@gmail.com> Signed-off-by: Anurag Saykar <anuragsaikar100@gmail.com>
Description
Add
ExcludeandExcludeRegexfields toMCPToolFilterfor exclusion-based tool filtering, complementing the existingInclude/IncludeRegexfields. Exclude rules take precedence over include rules (deny-wins semantics).Fixes #1921
Changes
Modified across 4 layers:
api/v1alpha1/mcp_route.go): New fields withMaxItems=32validation. CEL rules enforce mutual exclusivity within include/exclude pairs and require at least one field set.internal/filterapi/mcpconfig.go): Mirror fields inMCPToolSelector.internal/mcpproxy/config.go): Compiled exclude map + regexps.allows()checks excludes first for short-circuit denial.internal/controller/gateway.go): Field mapping from CRD to filterapi.Test Plan
allows(): exclude-only, excludeRegex-only, include+exclude combo, include+excludeRegex comboLoadConfigtests for exclude parsing and invalid regex error handlingmake precommitandmake testpass