Repository navigation
feat(server): one access gate for every T3 MCP tool - #15961
Conversation
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: unavailable · PR result: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
| * `TOOL_ACCESS` is checked before its handler runs, and a tool missing from | ||
| * the table fails registration. | ||
| */ | ||
| export const gatedServer = ( |
There was a problem hiding this comment.
gatedServer constructs a production McpServer service by accepting another service instance and a callback closing over ThreadManagementService. This hides its dependencies behind factory parameters rather than acquiring them from Effect's environment. Consider making the decorator an Effect constructor that yield* acquires both services and performs the shell lookup there; the registration sites can then use that constructor directly. This spans the constructor and its call site, so there isn't a self-contained inline suggestion.
Posted via Macroscope — Effect Service Conventions
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This PR introduces a substantial centralized authorization layer that changes runtime access behavior across every MCP tool and modifies thread-launch permissions. Because it affects security-sensitive authentication/authorization paths and includes an unresolved architectural concern, human review is warranted. You can add or adjust custom eligibility rules. Learn more. |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. 🧰 Additional context used📚 Code guidelines (2)No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (15)
💤 Files with no reviewable changes (2)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review. 📝 WalkthroughWalkthroughMCP tool registration now applies table-driven access checks based on caller credentials, thread state, and mode limits. Thread launches resolve runtime and interaction modes within the caller’s limits. ChangesMCP access and launch behavior
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~30 minutes Change: Feature Sequence Diagram(s)sequenceDiagram
participant MCPClient
participant MCPServer
participant McpToolAccess
participant ThreadManagementService
participant ToolkitHandler
MCPClient->>MCPServer: Invoke registered tool with thread scope
MCPServer->>McpToolAccess: Check tool access
McpToolAccess->>ThreadManagementService: Get caller thread shell
ThreadManagementService-->>McpToolAccess: Return thread shell
McpToolAccess-->>MCPServer: Allow or return structured denial
MCPServer->>ToolkitHandler: Invoke handler when access is allowed
Merge Risk: ⚪ Minimal · up to No concrete access regression is established for this change; it is mergeable after normal checks. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Description checkExplanation The description explains the problem, change, and verification in detail. It does not include the required scope and approval information, and the described behavior change is not presented as a small, obvious fix.
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
9b2326d to
9bbabe9
Compare
|
GitHub marked this merged by mistake: I force-pushed its branch while reordering the stack, the new head was already in its old base branch, and GitHub closed it as merged and deleted the branch. Nothing from it reached |
Part 4 of the MCP stack (#15220 → #15222 → this). Based on #15222.
Problem
Each T3 MCP tool picked its own permission checks from about a dozen helpers, and they had drifted:
t3_thread_launchrefused every caller below Full access with a hand-written check, so a Supervised or plan-mode thread couldn't do cross-project orchestration, even though an outside agent approved at Supervised could.Fix
McpToolAccessby what it does:ReadOnlyClientSafeescape hatch.Verification
vp test run src/mcp src/auth/McpOAuth.test.ts(server, in a PID namespace): 24 files, 212 tests pass.McpToolAccess.test.ts): 41 caller × tool cases, covering:runtimeMode: full-accessandinteractionMode: default.Readonlyannotation. It differs on two tools, both on purpose:t3_thread_readis a read here. It used to be callable by read-only agents throughReadOnlyClientSafe.t3_worktree_statusis "acts as the calling thread", which outside agents were already refused.src/providerrun, 7 process-tree / OpenCode-server tests fail. The same 7 fail on the base branch in the same sandbox, so they're environmental.Not a visual change.
Model: Claude Opus 5.5 (1M context) via T3 Code's Claude Code harness.
🤖 Generated with Claude Code