feat: v0.22.0 (MCP proxy operator allowlist/denylist for tools/list and tools/call)#112
Conversation
…/call Add --allow-tool and --deny-tool repeatable CLI flags to the MCP proxy. Filtered tools are dropped from tools/list responses before the client sees them, and any tools/call to a filtered tool is rejected at the perimeter with an MCP isError payload (decision=FILTERED) without forwarding upstream or invoking the risk pipeline. Denylist wins on overlap with allowlist. Backward compatible: no flags = passthrough. Use case: hide write/delete tools (delete_repository, create_branch) when the upstream MCP server exposes more capability than the deployment policy allows. The LLM client never learns the tool exists.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe MCP proxy gains operator-configurable tool filtering with allow and deny lists (denylist takes precedence). Filtered tools are removed from ChangesOperator-side Tool Filtering Policy
Sequence Diagram(s)[No diagram generated: changes are primarily configuration, policy enforcement, and test validation without complex multi-component interaction flow suitable for sequence visualization.] Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
End-to-end smoke against the real A:
B:
C: no flags (regression check)
Audit-trail behavior is asymmetric by design: filtered calls leave only a stderr WARNING and no DB write (the proxy maintains the fiction that hidden tools do not exist). Allowed calls produce the full |
Summary
Adds operator-side tool filtering to the MCP proxy via two new repeatable CLI flags:
--allow-tool NAME: if any are given, only those tools pass through.--deny-tool NAME: those tools are filtered. Denylist wins on overlap.Effects:
tools/listresponses are filtered before the client sees them. The LLM never learns that hidden tools exist.tools/callto a filtered tool is rejected at the perimeter with an MCPisError: truepayload (decision: "FILTERED",reason: "Tool filtered by operator policy"). The upstream is not contacted and the risk pipeline is not invoked.Backward compatible: no flags means current passthrough behavior. The pipeline-based interception path is unchanged for non-filtered tool calls.
Why
The proxy already governs each
tools/callthrough the risk pipeline at runtime. That covers the "is this specific call safe right now" question. It does not cover the "should the LLM ever see this tool at all" question.Example: an MCP client running against
github/github-mcp-serveris exposed to write tools likedelete_repository,create_branch,merge_pull_request. A deployment may want a read-only posture without depending on the LLM to refrain. Denying those tools at the perimeter shapes the LLM's tool surface to match operator policy, independent of the risk score.Small surface, real policy-semantic upgrade: from "score every call" to "score every call AND control what's reachable."
Usage
Read-only against GitHub MCP. Anything else returns
Tool filtered by operator policyon call, and never appears intools/listto begin with.Test plan
pytest tests/test_integrations_mcp_proxy.py— 14 tests pass (8 new, covering denylist drops, allowlist restricts, denylist-wins-on-overlap, no-policy passthrough, filtered tools/call returns block, allowlist tools/call still pipelines)github-mcp-serverwith--deny-tool delete_repositoryand verifytools/listandtools/callboth reject (deferred to follow-up unless reviewer wants it pre-merge)Summary by CodeRabbit
--allow-tooland--deny-toolCLI flags. Filtered tools are excluded from tool listings and blocked from execution without forwarding to upstream. Denylist takes precedence over allowlist.