# Files changed · PR \#10566 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/10566/diffs)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

[feat\(mcp\): expose branch-backed workspace discovery](https://git.cafe/pingdotgg/t3code/pull/10566.md)

Version: 6

Head commit: 1dce00c6a6af3bfabaab3fc77f8d22d704e66fa6

Base commit: 3492b1573c3107d2611541e2d54c28cf2c7f462e

Comparison base: 3492b1573c3107d2611541e2d54c28cf2c7f462e

Showing up to 20 entries from this revision. If the pull request changes, reopen the first page before continuing.

## apps/server/src/mcp/toolkits/worktree/handlers.ts

Status: modified; +26; −0

```diff
@@ -1,3 +1,8 @@
+import { OrchestratorMcpFailure } from "@t3tools/contracts";
+import * as Option from "effect/Option";
+import * as GitWorkflow from "../../../git/GitWorkflowService.ts";
+import * as Project from "../../../project/ProjectService.ts";
+import { readCaller, unavailable } from "../../threadAccess.ts";
 import * as Effect from "effect/Effect";
 
 import { McpInvocationContext } from "../../McpInvocationContext.ts";
@@ -5,6 +10,27 @@
 import { WorktreeToolkit } from "./tools.ts";
 
 const handlers = {
+  t3_worktree_list: (input) =>
+    Effect.gen(function* () {
+      const context = yield* McpInvocationContext;
+      if (!context.capabilities.has("worktree"))
+        return yield* new OrchestratorMcpFailure({
+          code: "capability_denied",
+          message: "This credential cannot inspect worktrees.",
+        });
+      const { caller } = yield* readCaller();
+      const projects = yield* Project.ProjectService;
+      const project = yield* projects.getById(caller.projectId).pipe(Effect.mapError(unavailable));
+      if (Option.isNone(project))
+        return yield* new OrchestratorMcpFailure({
+          code: "invalid_request",
+          message: "The project was not found.",
+        });
+      const git = yield* GitWorkflow.GitWorkflowService;
+      return yield* git
+        .listRefs({ ...input, cwd: caller.worktreePath ?? project.value.workspaceRoot })
+        .pipe(Effect.mapError(unavailable));
+    }),
   t3_worktree_handoff: (input) =>
     Effect.gen(function* () {
       const scope = yield* McpInvocationContext;
```

## apps/server/src/mcp/toolkits/worktree/tools.ts

Status: modified; +34; −1

```diff
@@ -1,9 +1,16 @@
 import {
   WorktreeMcpFailure,
+  OrchestratorMcpFailure,
+  VcsListRefsInput,
+  VcsListRefsResult,
   WorktreeMcpHandoffInput,
   WorktreeMcpHandoffResult,
   WorktreeMcpStatusResult,
 } from "@t3tools/contracts";
+import * as Schema from "effect/Schema";
+import { GitWorkflowService } from "../../../git/GitWorkflowService.ts";
+import { ProjectService } from "../../../project/ProjectService.ts";
+import { ThreadManagementService } from "../../../orchestration-v2/ThreadManagementService.ts";
 import { Tool, Toolkit } from "effect/unstable/ai";
 
 import * as McpInvocationContext from "../../McpInvocationContext.ts";
@@ -44,4 +51,30 @@
   .annotate(Tool.Idempotent, true)
   .annotate(Tool.OpenWorld, false);
 
+export const WorktreeListTool = Tool.make("t3_worktree_list", {
+  description:
+    "List branch refs and their associated checkout paths for this thread's workspace using the app's ref inventory. Detached worktrees without a branch are not included. Use t3_worktree_status for the thread binding and t3_worktree_handoff to create a new worktree.",
+  parameters: Schema.Struct({
+    query: VcsListRefsInput.fields.query,
+    cursor: VcsListRefsInput.fields.cursor,
+    limit: VcsListRefsInput.fields.limit,
+    refKind: VcsListRefsInput.fields.refKind,
+    includeMatchingRemoteRefs: VcsListRefsInput.fields.includeMatchingRemoteRefs,
+  }),
+  success: VcsListRefsResult,
+  failure: OrchestratorMcpFailure,
+  failureMode: "return",
+  dependencies: [
+    McpInvocationContext.McpInvocationContext,
+    ThreadManagementService,
+    ProjectService,
+    GitWorkflowService,
+  ],
+})
-export const WorktreeToolkit = Toolkit.make(WorktreeHandoffTool, WorktreeStatusTool);
+  .annotate(Tool.Readonly, true)
+  .annotate(Tool.Destructive, false);
+export const WorktreeToolkit = Toolkit.make(
+  WorktreeHandoffTool,
+  WorktreeStatusTool,
+  WorktreeListTool,
+);
```

## apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts

Status: modified; +2; −0

```diff
@@ -48,6 +48,7 @@
 import { PreviewControlsToolkit } from "../../mcp/toolkits/previewControls/tools.ts";
 import { EnvironmentToolkit } from "../../mcp/toolkits/environment/tools.ts";
 import { ProjectToolkit } from "../../mcp/toolkits/project/tools.ts";
+import { WorktreeToolkit } from "../../mcp/toolkits/worktree/tools.ts";
 import { ThreadToolkit } from "../../mcp/toolkits/thread/tools.ts";
 import { OrchestratorToolkit } from "../../mcp/toolkits/orchestrator/tools.ts";
 import type { EventNdjsonLogger } from "../../provider/Layers/EventNdjsonLogger.ts";
@@ -587,6 +588,7 @@
     const readOnlyToolNames = [
       ...Object.values(OrchestratorToolkit.tools),
       ...Object.values(ThreadToolkit.tools),
+      ...Object.values(WorktreeToolkit.tools),
       ...Object.values(ProjectToolkit.tools),
       ...Object.values(EnvironmentToolkit.tools),
       ...Object.values(PreviewControlsToolkit.tools),
```

## apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts

Status: modified; +2; −0

```diff
@@ -812,6 +812,8 @@
   "mcp__t3-code__t3_pending_request_read",
   "mcp__t3-code__t3_thread_configuration",
   "mcp__t3-code__t3_thread_transfers",
+  "mcp__t3-code__t3_worktree_status",
+  "mcp__t3-code__t3_worktree_list",
   "mcp__t3-code__t3_project_list",
   "mcp__t3-code__t3_project_read",
   "mcp__t3-code__t3_thread_search",
```

## packages/shared/src/t3McpToolPresentation.ts

Status: modified; +1; −0

```diff
@@ -70,6 +70,7 @@
   t3_thread_wait: { displayName: "Wait for a T3 thread", summaryAction: "thread-wait" },
   t3_thread_interrupt: { displayName: "Interrupt a T3 thread", summaryAction: "thread-interrupt" },
   t3_worktree_handoff: { displayName: "Hand off thread to a git worktree" },
+  t3_worktree_list: { displayName: "List workspace branches" },
   t3_worktree_status: { displayName: "Get thread worktree status" },
   t3_preview_list: { displayName: "List preview tabs" },
   t3_preview_close: { displayName: "Close a preview tab" },
```
