Skip to content

Add worktree handoff and status tools to the t3-code MCP server#3754

Merged
juliusmarminge merged 5 commits into
pingdotgg:t3code/codex-turn-mappingfrom
nsxdavid:pr/mcp-worktree-tools
Jul 24, 2026
Merged

Add worktree handoff and status tools to the t3-code MCP server#3754
juliusmarminge merged 5 commits into
pingdotgg:t3code/codex-turn-mappingfrom
nsxdavid:pr/mcp-worktree-tools

Conversation

@nsxdavid

@nsxdavid nsxdavid commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

What Changed

Closes #3753. Reworked on top of #2829 per review: the tools are implemented against the orchestration-v2 services and this PR now targets t3code/codex-turn-mapping.

Adds two tools to the t3-code MCP server, following the conventions of the v2 orchestrator toolkit (a service behind thin handlers, one tagged failure with a code union, failureMode: "return", t3_-prefixed names, branded timeline labels):

  • t3_worktree_handoff creates a worktree and re-points the calling thread at it. branch is required; baseRef, startFromOrigin, path (absolute only), and runSetupScript behave as before. New: continuationPrompt queues a message as the thread's next turn, because on v2 a worktreePath change detaches the live provider session and ends the current turn. The queued run is promoted when the detached run terminates and starts inside the worktree with the conversation preserved. The handoff pre-checks branch existence so the common collision fails with an actionable invalid_request instead of an opaque git error, and rolls back the created worktree on any failure before the binding commits.

  • t3_worktree_status reports the thread's binding (attached or not, worktree path, branch, workspace root, the server's startFromOrigin default).

The last commit is a ProviderSessionManager change this feature exposed (details in Notes): per-thread MCP credentials are now stable across detach and re-attach, with revocation moved to session release and to a new terminal-detach path for thread archive/delete.

Tested with unit tests over WorktreeMcpService (49) and ProviderSessionManager (25), an HTTP-level test driving the production MCP layer end to end, and manually on Windows: full ClickUp task workflow with handoff from origin, automatic continuation in the worktree, and working MCP tools in the resumed session.

Notes for reviewers

  • The ProviderSessionManager commit deserves close review: long-lived provider processes (the codex app-server) build their MCP client once per conversation and keep the credential they started with, so the previous revoke-on-detach broke tool auth for any thread that detached and re-attached (workspace handoff, and plausibly runtime-mode changes on shared sessions). Credentials are now reused while they resolve, revoked at session release with a guard for live replacements, and revoked immediately on archive/delete via a revokeMcpCredential flag on the detach effect.

  • The handoff-induced run interruption surfaces in the UI as "Run interrupted by user". A distinct label for server-initiated interruptions ("workspace changed") would read better; that attribution lives in the UI/orchestrator layering, so it is not touched here.

  • thread.metadata.update has no conditional form, so a binding committed concurrently from the UI between the handoff's recheck and its dispatch is overwritten (last write wins). The recheck plus per-thread serialization narrows this to a very small window; closing it needs a worktreePath precondition at the dispatch layer. One Macroscope thread tracks this and is left open deliberately.

  • v2 has no worktree cleanup on thread delete (the v1 reactor's equivalent does not exist), so the tool description states worktrees are not removed automatically.

  • CI: Check is green. The 4 Test failures are pre-existing on the base branch (config.test.ts expects pre-userdata-v2 paths at lines 128/198, and the tool_call_read_only_on_request / tool_call_restricted_granular claudeAgent replay fixtures drifted); none of the failing files are in this diff.

Why

See #3753: an agent can create a worktree from its shell, but the thread binding lives in T3 Code's orchestration state and nothing agent-reachable can update it, so agent-driven worktree setup dead-ends. The MCP server is the only channel T3 Code exposes to the agent, so this is the only place the capability can live.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

High Risk
Large changes to MCP authentication and credential revocation on detach/re-attach, plus git worktree creation and thread metadata updates that can leave disk state if rollback paths fail.

Overview
Agents can move a thread into a new git worktree via t3_worktree_handoff and read binding state with t3_worktree_status, registered on the MCP HTTP server behind a new worktree capability (included on newly issued MCP sessions).

WorktreeMcpService drives handoff: validates repo/branch, optionally bases the branch from origin, creates the worktree, updates thread metadata, optionally runs the project setup script, and can queue a continuationPrompt for the next turn after the workspace change detaches the live session. Failed pre-bind steps roll back the worktree; concurrent handoffs per thread are serialized.

ProviderSessionManager no longer revokes MCP credentials on every detach. Credentials are reused across re-attach when still valid, revocation is scoped per credential id (with reservations for in-flight opens), workspace-change detaches keep tokens alive, and archive/delete detaches set revokeMcpCredential so tokens are revoked immediately.

Reviewed by Cursor Bugbot for commit f0589f4. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add worktree handoff and status tools to the t3-code MCP server

  • Adds two new MCP tools (t3_worktree_handoff, t3_worktree_status) that let agents hand a thread off to a git worktree and query its attachment state via the MCP HTTP server.
  • Introduces WorktreeMcpService which orchestrates worktree creation, thread binding, optional setup script execution, and continuation message scheduling; concurrent handoffs for the same thread fail with a typed handoff_in_progress error.
  • Adds a worktree MCP capability derived from the new ALL_MCP_CAPABILITIES constant in McpInvocationContext; all newly issued sessions include it automatically.
  • Reworks per-thread MCP credential lifecycle in ProviderSessionManager: credentials are now reused across attaches when still valid, revocation is scoped to specific credential ids, and thread.archive/thread.delete detaches now carry revokeMcpCredential: true to trigger immediate revocation.
  • Risk: the credential revocation logic is significantly reworked — credentials are no longer unconditionally revoked on every detach, which changes behavior for any code that relied on a clean credential state after detach.

Macroscope summarized f0589f4.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3c2bf006-89a5-4bdf-93ee-2e88e56797e8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

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

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 6, 2026

@macroscopeapp macroscopeapp 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.

One convention issue: WorktreeOperationError copies the underlying cause.message into a detail field and builds its message from it, instead of preserving the real failure as cause and deriving the message from structural attributes. The sibling previewAutomation.ts errors already follow the expected pattern (cause: Schema.Defect() plus bounded diagnostics). See inline comment.

Posted via Macroscope — Effect Service Conventions

Comment thread packages/contracts/src/worktree.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a7bf0f58f3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/server/src/mcp/toolkits/worktree/handlers.ts Outdated
Comment thread apps/server/src/mcp/toolkits/worktree/handlers.ts Outdated
Comment thread packages/contracts/src/worktree.ts Outdated
Comment thread apps/server/src/mcp/toolkits/worktree/handlers.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

1 blocking correctness issue found. This PR introduces new worktree handoff and status MCP tools with significant new capability, complex concurrency handling, and modifications to credential/session lifecycle. Two unresolved review comments identify potential race conditions in the binding logic that warrant human review.

You can customize Macroscope's approvability policy. Learn more.

@github-actions github-actions Bot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Jul 7, 2026

@macroscopeapp macroscopeapp 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.

One finding on the new worktree handlers: WorktreeOperationError requires a cause, but the project-not-found path has no underlying failure and fabricates an Error only to satisfy that field.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/mcp/toolkits/worktree/handlers.ts Outdated
Comment thread apps/server/src/mcp/toolkits/worktree/handlers.ts Outdated
Comment thread apps/server/src/mcp/toolkits/worktree/handlers.ts Outdated

@juliusmarminge juliusmarminge left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please target against #2829 which introduces and reworks the MCP services a bit

@nsxdavid
nsxdavid force-pushed the pr/mcp-worktree-tools branch from 769a4e7 to 5c63efe Compare July 20, 2026 20:36
@nsxdavid
nsxdavid changed the base branch from main to t3code/codex-turn-mapping July 20, 2026 20:36
@github-actions github-actions Bot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Jul 20, 2026
Comment thread apps/server/src/mcp/WorktreeMcpService.ts Outdated
Comment thread apps/server/src/mcp/WorktreeMcpService.ts
@nsxdavid
nsxdavid force-pushed the pr/mcp-worktree-tools branch from 5c63efe to 633ba7a Compare July 20, 2026 22:07
@github-actions github-actions Bot added size:XL 500-999 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Jul 20, 2026

@macroscopeapp macroscopeapp 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.

One Effect service-convention violation: the new WorktreeMcpService retains a standalone WorktreeMcpServiceShape interface instead of defining the service interface inline in the Context.Service declaration. See details inline.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/mcp/WorktreeMcpService.ts Outdated
@nsxdavid
nsxdavid force-pushed the pr/mcp-worktree-tools branch from 633ba7a to a3cf90a Compare July 20, 2026 22:24
Comment thread apps/server/src/mcp/WorktreeMcpService.ts
Comment thread apps/server/src/mcp/WorktreeMcpService.ts
@nsxdavid
nsxdavid marked this pull request as draft July 20, 2026 22:41
@nsxdavid
nsxdavid force-pushed the pr/mcp-worktree-tools branch from a3cf90a to ee25215 Compare July 20, 2026 22:50
Comment thread apps/server/src/mcp/toolkits/worktree/tools.ts Outdated
Comment thread apps/server/src/mcp/toolkits/worktree/tools.ts Outdated
Comment thread apps/server/src/mcp/WorktreeMcpService.ts Outdated
@nsxdavid

Copy link
Copy Markdown
Contributor Author

@juliusmarminge

please target against #2829 which introduces and reworks the MCP services a bit

Status update: I am working on this and have a test article. It is a might bit more difficult in v2 than v1 due to some issues I will enumerate when ready for review.

@nsxdavid
nsxdavid force-pushed the pr/mcp-worktree-tools branch 2 times, most recently from 0ca5533 to a85b089 Compare July 23, 2026 15:47
Comment thread apps/server/src/mcp/WorktreeMcpService.ts
@nsxdavid
nsxdavid force-pushed the pr/mcp-worktree-tools branch 2 times, most recently from fc7b7a4 to 9dbf702 Compare July 23, 2026 16:06

@macroscopeapp macroscopeapp 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.

One Effect service-convention finding on the new WorktreeMcpService. This was raised on an earlier revision of this PR; the file has since been rewritten (squashed into a single commit) but the same violation persists, so I'm re-surfacing it on the current diff.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/mcp/WorktreeMcpService.ts Outdated
@nsxdavid
nsxdavid force-pushed the pr/mcp-worktree-tools branch from 9dbf702 to 4e26d31 Compare July 23, 2026 16:18
@nsxdavid

Copy link
Copy Markdown
Contributor Author

@juliusmarminge Retargeting is complete: the PR is rebuilt on #2829, based on t3code/codex-turn-mapping, and the tools are reimplemented against the v2 services following the orchestrator toolkit conventions (t3_worktree_handoff / t3_worktree_status, service behind thin handlers, single failure with a code union). Tested end to end on Windows: handoff, automatic continuation, tools working in the resumed worktree session.

Three things to know when reviewing:

  1. The last commit changes ProviderSessionManager, so please look at it closely. The old code revoked a thread's MCP token whenever the thread detached from its provider session. That is the wrong lifetime: a provider process that survives the detach (today, only the shared codex app-server) keeps using the token it was started with, so after the handoff re-attached the thread, every MCP call from that process failed auth. The fix ties revocation to the right events instead: tokens stay stable across detach and re-attach, and die when the provider process shuts down or the thread is archived or deleted.

  2. On v2 the handoff ends the current turn (the workspace change detaches the session), so the tool gained continuationPrompt: remaining work is queued as the thread's next message and resumes inside the worktree automatically.

  3. Cosmetic but visible: the turn ended by a handoff shows in the UI as a red "Run interrupted by user", which reads like a failure and misattributes a server-initiated interruption. A distinct label ("workspace changed") would fix it, but that attribution lives in your UI/orchestrator layering, so I left it alone.

CI: Check is green. The 4 Test failures are pre-existing on the base branch (the userdata-v2 config tests and two claude replay fixtures). Smaller notes are in the updated PR description.

@nsxdavid
nsxdavid marked this pull request as ready for review July 23, 2026 17:07

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4e26d31738

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/server/src/orchestration-v2/ProviderSessionManager.ts Outdated
Comment thread apps/server/src/mcp/WorktreeMcpService.ts
@nsxdavid
nsxdavid requested a review from juliusmarminge July 23, 2026 17:42
@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch 2 times, most recently from 1e58e65 to a286c60 Compare July 24, 2026 13:37
@juliusmarminge
juliusmarminge force-pushed the pr/mcp-worktree-tools branch from 0a22804 to 4e87631 Compare July 24, 2026 14:22

@juliusmarminge juliusmarminge left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requested retargeting onto the orchestration-v2 branch is satisfied. Rebased onto the current target after #4193/#4229; 83 focused tests, targeted lint/formatting, and server/contracts/shared typechecks pass locally. Approving the current head for merge once required CI is green.

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4e87631. Configure here.

resolved.threadId === threadId &&
resolved.providerInstanceId === providerInstanceId
) {
return { mcpCredentialId: existing.providerSessionId, issued: false };

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.

Reused tokens lack worktree capability

Medium Severity

The prepareMcpSession logic reuses existing MCP credentials, but capabilities are fixed at issuance. This means sessions reusing older credentials will lack newly introduced capabilities (e.g., worktree), resulting in capability_denied errors during operations like workspace handoffs.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4e87631. Configure here.

);
return heldElsewhere
? Effect.void
: clearMcpSession(threadId, mcpCredentialId);

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.

Stale map blocks credential revocation

Medium Severity

On session release, heldElsewhere skips revoking an MCP credential when any other live session entry maps the same thread to the same credential id, even if that thread is detached everywhere. After a workspace handoff, an older and a newer provider session can each retain that stale map entry; when both release, each side skips revocation and the bearer token can remain valid in the registry indefinitely.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4e87631. Configure here.

commandId: CommandId.make(part("command", "worktree-handoff")),
continuationCommandId: CommandId.make(part("command", "worktree-continuation")),
continuationMessageId: MessageId.make(part("message", "worktree-continuation")),
};

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.

Handoff command IDs not stable

Medium Severity

Worktree handoff mints fresh random UUIDs for the metadata-update and continuation commandId/messageId on every call instead of a session-scoped stable id derived from the handoff inputs. Orchestrator command receipts dedupe by commandId, so a retried MCP handoff after a successful bind cannot replay the prior receipt and surfaces already_in_worktree rather than an idempotent success.

Fix in Cursor Fix in Web

Triggered by learned rule: Scope idempotency keys by session and operation type

Reviewed by Cursor Bugbot for commit 4e87631. Configure here.

@juliusmarminge
juliusmarminge force-pushed the pr/mcp-worktree-tools branch from 4e87631 to f0589f4 Compare July 24, 2026 14:51
@juliusmarminge
juliusmarminge merged commit 4dffcad into pingdotgg:t3code/codex-turn-mapping Jul 24, 2026
13 of 14 checks passed
@nsxdavid
nsxdavid deleted the pr/mcp-worktree-tools branch July 25, 2026 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL 500-999 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Let the agent move its thread into a worktree

2 participants