Skip to content

feat(server): /mcp narrows a client's modes from T3-Mode-Limit - #16653

Open
juliusmarminge wants to merge 1 commit into
mainfrom
t3code/peer/mode-limit-header
Open

juliusmarminge wants to merge 1 commit into
mainfrom
t3code/peer/mode-limit-header

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Part of cross-environment orchestration: an environment linked to another signs in to its /mcp as an outside agent. Every linked call has to carry the calling agent's own limits, so a plan-mode agent on the laptop can't start full-access work on the box just because the link was approved at auto.

What changes

  • /mcp reads an optional T3-Mode-Limit: <runtime>/<interaction> header, from OAuth (mcp-client) callers only.
  • The header can only narrow the client's ceiling. A broader value changes nothing, and a malformed one gets a 400 (invalid_mode_limit).
  • clientModeCeiling replaces clientRuntimeModeCeiling, adding an interaction ceiling. loadCaller and the orchestrator MCP service use it, so the access declarations and the in-lock DispatchModeLimit check enforce the narrowed modes.
  • Provider sessions ignore the header; their limits come from their thread.

Verification

  • New test in McpHttpServer.test.ts. A real /mcp, with an auto OAuth client, serves a probe tool that starts a thread through McpToolAccess.startsThreads. Results:
    • no header → auto/default;
    • approval-required/plan → narrowed, and escalation requests above it are refused;
    • a broader header → unchanged;
    • malformed → 400.
  • Mutation-checked both ways: dropping the narrowing fails the test, and so does letting a broader header widen the ceiling.
  • MCP and auth suites: 37 files, 364 tests, all passing.

Opus 5.5 via Claude Code.

🤖 Generated with Claude Code


Devin Review

@juliusmarminge
juliusmarminge added this pull request to stack #16656 October 7, 2026 00:50
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Oct 7, 2026
@juliusmarminge juliusmarminge changed the title t3code/peer/mode limit header feat(server): /mcp narrows a client's modes from T3-Mode-Limit Oct 7, 2026
@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 7, 2026
@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful main measurement shown below.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 4.9 KiB 5.0 KiB +23 B (+0.5%) 6.8 KiB ✅
Codex Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Codex Live turn WebSocket wire 1.2 KiB 1.2 KiB +23 B (+1.9%) 2.0 KiB ✅
Codex Live turn WebSocket decoded 20.8 KiB 20.9 KiB +41 B (+0.2%) 29.3 KiB ✅
Codex Live turn messages 1 2 +1 (+100.0%) 8 ✅
Claude Total thread wire 5.0 KiB 5.0 KiB +24 B (+0.5%) 6.8 KiB ✅
Claude Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Claude Live turn WebSocket wire 1.2 KiB 1.2 KiB +24 B (+2.0%) 2.0 KiB ✅
Claude Live turn WebSocket decoded 21.2 KiB 21.2 KiB +41 B (+0.2%) 29.3 KiB ✅
Claude Live turn messages 1 2 +1 (+100.0%) 8 ✅

Baseline: b744bde · PR result: 72f69ac · Source CI: success

Scenario and decoded snapshot size

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

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@juliusmarminge

Copy link
Copy Markdown
Member Author

End-to-end run, two real servers

Two t3 serve processes from the top of this stack, each with its own data directory, on one machine. A laptop (port 3971) and a box (port 3972). Their projects are clones of one bare origin, so they share a repository. An outside agent (OAuth with a pairing code) drives the laptop's /mcp, and real Claude Sonnet 5.5 turns run on both sides. The last part repeats the run over Tailscale HTTPS (a *.ts.net HTTPS address).

Through the link, the box refused launches above the caller's modes. A plain call at full-access got "Child runtime mode full-access is broader than parent mode auto." (the link's access was auto). The same launch at auto with T3-Mode-Limit: approval-required/plan got "Child runtime mode auto is broader than parent mode approval-required.", so the header narrowed the ceiling below the link's.

CI also showed an unused MODE_LIMIT_HEADER export (Knip). The constant now lives in McpInvocationContext, where #16684 already uses it.

Opus 5.5 via Claude Code.

@juliusmarminge
juliusmarminge marked this pull request as ready for review October 7, 2026 18:09
@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Team
  • Run ID: d94a2616-bd0d-4db2-a460-cf472ccc8b20

📥 Commits

Reviewing files that changed from the base of the PR and between 8eadb66 and 0b07846.


📒 Files selected for processing (1)
  • apps/server/src/mcp/OrchestratorMcpService.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.



📝 Walkthrough

Walkthrough

The MCP HTTP server accepts a T3-Mode-Limit header for authenticated clients. It validates the requested modes and applies them as limits to the client’s runtime and interaction modes. MCP callers without a thread use the resulting ceilings.

Changes

OAuth Client Mode Limits

Layer / File(s) Summary
Request mode-limit contract and validation
apps/server/src/mcp/McpInvocationContext.ts, apps/server/src/mcp/McpHttpServer.ts
The invocation context defines the mode-limit header and optional narrowed modes. The HTTP server validates the header and returns HTTP 400 for malformed or unsupported values.
Effective mode ceilings and callers
apps/server/src/mcp/McpInvocationContext.ts, apps/server/src/mcp/OrchestratorMcpService.ts, apps/server/src/mcp/threadAccess.ts, apps/server/src/mcp/McpHttpServer.test.ts
clientModeCeiling independently applies runtime and interaction limits. Callers without a thread use those ceilings. The integration test checks narrowing, non-widening, escalation-denied responses, and invalid headers.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant OAuthClient
  participant McpHttpServer
  participant OrchestratorMcpService
  OAuthClient->>McpHttpServer: Send request with T3-Mode-Limit
  McpHttpServer->>OrchestratorMcpService: Pass invocation context to handler
  OrchestratorMcpService->>OrchestratorMcpService: Calculate runtime and interaction ceilings
Loading

Suggested reviewers: maria-rcks


Merge Risk: ⚪ Minimal · up to 0b078

The change narrows OAuth MCP callers’ mode limits, and both limits reach dispatch enforcement. No concrete merge-blocking risk is apparent.

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the problem, implementation, affected callers, and verification results. It does not include the required Scope and approval section or an issue, approval reference, or vali… Add a ## Scope and approval section. Link the triaged issue or maintainer approval with the approval comment, or explain why this focused change qualifies for an exemption.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: /mcp narrows client modes using T3-Mode-Limit.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Full details: Description check

Explanation

The description explains the problem, implementation, affected callers, and verification results. It does not include the required Scope and approval section or an issue, approval reference, or valid exemption rationale.



✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR

🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR


  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@macroscopeapp

macroscopeapp Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR adds per-request MCP mode restrictions and threads them through the authorization checks governing delegated work. Although the optional path is tested and does not alter callers that omit the header, it changes security-sensitive permission boundaries.

No code changes detected at 72f69ac. Prior analysis still applies.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarminge force-pushed the t3code/peer/mode-limit-header branch 4 times, most recently from 8eadb66 to 0b07846 Compare October 8, 2026 08:30
@juliusmarminge
juliusmarminge removed this pull request from stack #16656 October 8, 2026 08:31
@juliusmarminge
juliusmarminge added this pull request to stack #17131 October 8, 2026 08:32
@juliusmarminge
juliusmarminge force-pushed the t3code/peer/mode-limit-header branch from 0b07846 to 6e0740f Compare October 8, 2026 22:06
@juliusmarminge
juliusmarminge force-pushed the t3code/peer/mode-limit-header branch from 6e0740f to b6c6fe6 Compare October 9, 2026 23:46
An OAuth client on /mcp is capped by the access it was approved with.
When another environment calls on behalf of one of its agents, that agent
may run under narrower modes, and the target has no way to know.

/mcp now reads `T3-Mode-Limit: <runtimeMode>/<interactionMode>` from OAuth
clients and caps the request at the narrower of the two. The header can
only narrow: a broader one changes nothing, and a malformed one is
refused with 400. The client's interaction mode can now be capped too;
before, it was always default.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@juliusmarminge
juliusmarminge force-pushed the t3code/peer/mode-limit-header branch from b6c6fe6 to 72f69ac Compare October 10, 2026 02:07

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant