Skip to content

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

Merged
nacx merged 8 commits into
envoyproxy:mainfrom
majiayu000:feat/issue-1921-tool-exclude-filter
Apr 8, 2026
Merged

feat: add exclude and excludeRegex support for tool selectors#1963
nacx merged 8 commits into
envoyproxy:mainfrom
majiayu000:feat/issue-1921-tool-exclude-filter

Conversation

@majiayu000

@majiayu000 majiayu000 commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

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

codecov-commenter commented Mar 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.40%. Comparing base (304b221) to head (123d741).

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.
📢 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

dosubot Bot commented Mar 17, 2026

Copy link
Copy Markdown

Documentation Updates

3 document(s) were updated by changes in this PR:

index
View 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
 
index
View 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
 
index
View 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

How did I do? Any feedback?  Join Discord

@nacx

nacx commented Mar 19, 2026

Copy link
Copy Markdown
Member

/gemini review

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

Copy link
Copy Markdown
Contributor

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.

Comment thread internal/mcpproxy/config.go Outdated
Comment thread internal/mcpproxy/config.go Outdated
- 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>
@nacx

nacx commented Apr 7, 2026

Copy link
Copy Markdown
Member

Can you format the code to fix the style checks?

Signed-off-by: majiayu000 <1835304752@qq.com>
@majiayu000

Copy link
Copy Markdown
Contributor Author

fixed — ran gofmt on the test file, was just struct field alignment.

@nacx
nacx enabled auto-merge (squash) April 8, 2026 10:05
@nacx

nacx commented Apr 8, 2026

Copy link
Copy Markdown
Member

/retest

@nacx
nacx merged commit 5976c1f into envoyproxy:main Apr 8, 2026
34 checks passed
@missBerg missBerg mentioned this pull request May 1, 2026
4 tasks
nacx pushed a commit that referenced this pull request May 5, 2026
**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>
anurags25 pushed a commit to anurags25/ai-gateway that referenced this pull request May 12, 2026
**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>
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