Repository navigation
ENG-965: mask mcp lane results with the lane's mask rules - #2125
Draft
luanlorenzo wants to merge 10 commits into
Draft
luanlorenzo wants to merge 10 commits into
luanlorenzo wants to merge 10 commits into
Conversation
Contributor
📋 API ChangelogAPI Changelog unknown vs. unknownNo changes detected |
Contributor
|
✅ Build Completed with Success, Version=2125.0.0-g2416c49 |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📝 Description
The sidecar mcp lane masks tool and resource results with its own mask rules, through mcpproxy's redactor. Stacked on #2120. Stays draft until mcpproxy v0.2.0 is tagged; the pin is the pseudo-version of mcpproxy 7d089fd.
🔗 Related Issue
Part of ENG-965
🚀 Type of Change
📋 Changes Made
gate.MaskSupportedaccepts mcp; Validate stops refusingmaskon an mcp listener.Hooks.Redact= the session masker (the hook gets no session).RecordMaskedtakes its count from themcp.redactedevent. No result walker of our own.mcp_mask: the plane does not serve mask rules on an mcp lane to a sidecar without it. 1.290.0 refuses a lanemaskblock there and ignores inherited rules.columnsnever fires on an mcp lane. Validate refuses one in the lane's ownmaskblock, and the plane refuses to bind one to an mcp listener (422, same daemon check). The served document never puts one in an mcp lane's own block, whatever route bound it, and an import does not bind a top-level one to an mcp lane. An inherited one is skipped with a-validatenote and a startup warning, so configs valid on 1.290 still start. The lane's own rules ormask: {rules: []}replace inherited ones.structuredContentpast 128 levels, a result or read field of an unexpected type; it now also masksstructuredContent, nestedresource.text,resources/readcontents andtasks/result;nameandargumentskeys, and invalid params are refused before the pipeline (no budget spent); a failed initialize gets no session;LANE_FEATURE_BLOCKS, ENG-959: mcp lanes in the sidecar form, rule editor and session view #2121), the mcp lane docs page (ENG-965: docs(sidecar): masking and the ai analyzer on the mcp lane documentation#258), the libhoop Redact hook logging a cause.🧪 Testing
Result: an agent behind the mcp lane gets emails and SSNs masked in every result field; a result the masker cannot read is withheld, not leaked; a config with a column mask rule still boots. Independent QA PASS on
2416c49c6(4 rounds) against the basea56f2b8dc, test data only.What it solves: teams with an MCP server behind the sidecar mcp lane get their mask rules applied to what the agent reads.
sidecar/mcpgateway/mask_test.go:TestAToolResultTextIsMasked,TestAResourceReadIsMasked,TestANestedResourceTextIsMasked,TestEveryStructuredContentStringIsMasked,TestAMaskerErrorWithholdsTheResultAndTheSessionSurvives,TestAMaskedResultThatIsNotRecordedIsWithheld,TestALaneWithoutMaskRulesForwardsResultsAsSent,TestAResultOfAnUnexpectedTypeIsWithheld.sidecar/daemon/mcpgateway_test.go:TestAnMCPLaneMasksWithItsMaskRules,TestAnMCPLaneRefusesColumnMaskRules,TestMCPLaneSessionMasksAndRecordsTheCount,TestAnMCPLaneWithMaskRulesNeedsTheCapability.gateway/services/sidecarrules_test.go:TestValidateSpecForLane(mcp cases),TestAServedMCPLaneNeverHoldsAColumnMaskRule;gateway/services/sidecarimport_test.go:TestImportDoesNotBindAColumnMaskRuleToAnMCPLane.cd sidecar && go vet ./... && go test ./...cd sidecar/mcpgateway && go vet ./... && go test -race ./...cd sidecar/cmd && go vet ./... && CGO_ENABLED=0 go test ./...cd agent && go test ./controller/...,cd gateway && go test ./api/connections/ -run 'MCP|Mcp',cd gateway && go test ./services ./api/sidecar ./api/sidecarbind,cd client && go build ./...TestTheObserverCountsMessagesByToolAndDecision: since mcpproxy v0.1.7, invalid tools/call params are refused before the pipeline. They still count as a deny with no tool (mcpproxy 826f2e6), but spend no budget, so the test budget is 3.