Skip to content

refactor(mcp): explicit IDs for MCP tools, remove active workspace dependency - #1273

Closed
Kitenite wants to merge 2 commits into
mainfrom
kitenite/create-workspace-mcp-result
Closed

Kitenite wants to merge 2 commits into
mainfrom
kitenite/create-workspace-mcp-result

Conversation

@Kitenite

@Kitenite Kitenite commented Feb 7, 2026 •

Copy link
Copy Markdown
Member

Summary

  • create_workspace now requires projectId instead of deriving it from active workspace
  • start_claude_session and start_claude_subagent now require workspaceId
  • switch_workspace is now UI-only (uses navigateToWorkspace instead of setActive)
  • Removed navigate_to_workspace tool (redundant with switch_workspace)
  • Removed getActiveWorkspaceId from ToolContext — no tool depends on implicit active workspace state
  • create_workspace and start_claude_session now return worktreePath in results

Test plan

  • Verify create_workspace MCP tool works with explicit projectId
  • Verify start_claude_session MCP tool works with explicit workspaceId
  • Verify start_claude_subagent MCP tool works with explicit workspaceId
  • Verify switch_workspace navigates UI without calling setActive
  • Verify navigate_to_workspace is no longer registered as an MCP tool

Summary by CodeRabbit

Release Notes

  • Removals

    • Removed the navigate-to-workspace tool.
  • Changes

    • Workspace creation tools now require an explicit project ID parameter.
    • Created workspaces now return the worktree path information.
    • Tools that interact with workspaces now require an explicit workspace ID instead of inferring from context.
    • Clarified that workspace switching is a UI-only action and does not affect agent context.

…cy, consolidate navigation tools

- create_workspace now requires projectId instead of deriving from active workspace
- start_claude_session and start_claude_subagent now require workspaceId
- switch_workspace is now UI-only (navigateToWorkspace instead of setActive)
- Remove navigate_to_workspace (redundant with switch_workspace)
- Remove getActiveWorkspaceId from ToolContext
@coderabbitai

coderabbitai Bot commented Feb 7, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR refactors tool parameter handling by replacing implicit context-based workspace derivation with explicit parameter passing. It removes the navigate-to-workspace tool entirely, adds required projectId and workspaceId parameters to multiple tools, eliminates the getActiveWorkspaceId context method, and updates output schemas to include worktreePath.

Changes

Cohort / File(s) Summary
Navigation Tool Removal
apps/desktop/.../navigate-to-workspace.ts, packages/mcp/src/tools/devices/navigate-to-workspace/*, apps/desktop/.../tools/index.ts, packages/mcp/src/tools/index.ts
Removed entire navigate-to-workspace tool implementation and exports from both desktop and MCP layers. Also updated switch-workspace.ts to use alternative navigation approach.
ProjectId Parameterization
apps/desktop/.../create-worktree.ts, packages/mcp/src/tools/devices/create-workspace/create-workspace.ts
Added projectId as required input parameter and removed runtime derivation from context/workspaces. Updated schemas to expect projectId directly in params.
WorkspaceId Parameterization
apps/desktop/.../start-claude-session.ts, apps/desktop/.../start-claude-subagent.ts, packages/mcp/src/tools/devices/start-claude-session/start-claude-session.ts
Added workspaceId as required input schema field. Replaced context-based active workspace lookups with explicit params.workspaceId throughout validation, error handling, and return payloads.
Context Simplification
apps/desktop/.../tools/types.ts, apps/desktop/.../useCommandWatcher.ts
Removed getActiveWorkspaceId() method from ToolContext interface. Eliminated route-based active workspace ID derivation logic and its references in ToolContext construction.
Output Schema Updates
apps/desktop/.../create-worktree.ts
Added worktreePath to CreatedWorkspace return structure and included it in accumulated created worktrees results.
Documentation Updates
packages/mcp/src/tools/devices/switch-workspace/switch-workspace.ts
Updated tool description to clarify switch-workspace is UI-only and does not change agent context or working directory.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

A rabbit's toolkit, now so clean,
No hidden context in between!
Each param passed, no guessing games,
The worktrees track their proper names. 🐰✨
Simpler paths for agents to take,
One less tool to navigate, for goodness' sake!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main refactoring effort: making workspace-related MCP tools require explicit IDs (projectId, workspaceId) and removing the active workspace dependency.
Description check ✅ Passed The PR description clearly outlines all major changes with concrete examples and includes a test plan with checkboxes. It deviates from the template structure but provides comprehensive context.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch kitenite/create-workspace-mcp-result

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 and usage tips.

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@apps/desktop/src/renderer/routes/_authenticated/components/AgentHooks/hooks/useCommandWatcher/tools/start-claude-subagent.ts`:
- Around line 10-12: The execute function in start-claude-subagent.ts currently
has the signature async function execute(params: z.infer<typeof schema>):
Promise<CommandResult> which violates the ToolDefinition contract used
elsewhere; update the signature to accept the ToolContext as a second parameter
(e.g., async function execute(params: z.infer<typeof schema>, _ctx:
ToolContext): Promise<CommandResult>) so it matches other tools
(create-worktree, delete-workspace, switch-workspace) and keeps type
consistency; ensure you import or reference ToolContext if needed and prefix the
parameter with an underscore if unused.
🧹 Nitpick comments (5)
packages/mcp/src/tools/devices/start-claude-session/start-claude-session.ts (1)

84-94: Consider leveraging the Zod inputSchema instead of manual validation with unsafe casts.

The as string casts on lines 89–91 bypass TypeScript's type checking — if a non-string value slips through, the cast won't catch it at runtime. Since the MCP SDK already validates against the Zod inputSchema (which declares all three fields as z.string()), validateArgs is likely redundant. If you want a belt-and-suspenders approach, consider parsing with a Zod schema instead:

♻️ Suggested refactor
+const argsSchema = z.object({
+	deviceId: z.string(),
+	taskId: z.string(),
+	workspaceId: z.string(),
+});
+
-function validateArgs(args: Record<string, unknown>): {
-	deviceId: string;
-	taskId: string;
-	workspaceId: string;
-} | null {
-	const deviceId = args.deviceId as string;
-	const taskId = args.taskId as string;
-	const workspaceId = args.workspaceId as string;
-	if (!deviceId || !taskId || !workspaceId) return null;
-	return { deviceId, taskId, workspaceId };
+function validateArgs(args: Record<string, unknown>) {
+	const result = argsSchema.safeParse(args);
+	return result.success ? result.data : null;
 }
packages/mcp/src/tools/devices/create-workspace/create-workspace.ts (2)

40-44: Type assertions (as string) bypass compile-time safety — pre-existing pattern.

These casts assume the MCP SDK passes validated args. If it doesn't, args.projectId could be undefined at runtime despite the as string assertion. The downstream !projectId guard mitigates this, but a safer approach would be to parse args through a Zod schema at the top of the handler (e.g., a combined input schema .parse(args)), which would give both runtime validation and proper typing in one step. Not blocking since this follows the existing deviceId pattern.


46-58: Schema and runtime validation are subtly inconsistent for empty strings.

z.string() in the input schema (lines 27-30) permits "", but the runtime guards !deviceId / !projectId reject it. If the MCP SDK validates against the schema first, an empty string would pass schema validation but then hit these error branches.

Consider adding .min(1) to the deviceId and projectId Zod declarations so the two layers agree. This is a pre-existing inconsistency for deviceId, and the new projectId check just follows the same pattern, so not blocking.

Proposed fix to align schema with runtime checks
-			deviceId: z.string().describe("Target device ID"),
-			projectId: z
-				.string()
-				.describe("Project ID to create workspaces in (use list_projects to find)"),
+			deviceId: z.string().min(1).describe("Target device ID"),
+			projectId: z
+				.string()
+				.min(1)
+				.describe("Project ID to create workspaces in (use list_projects to find)"),
apps/desktop/src/renderer/routes/_authenticated/components/AgentHooks/hooks/useCommandWatcher/tools/create-worktree.ts (1)

16-19: Consider adding .min(1) to projectId to reject empty strings.

z.string() accepts empty strings. Since projectId is a required identifier passed to createWorktree.mutateAsync, an empty string would likely cause a downstream failure with a less helpful error message. The same applies to the workspaceId fields added in other tools in this PR.

Suggested fix
 const schema = z.object({
-	projectId: z.string(),
+	projectId: z.string().min(1),
 	workspaces: z.array(workspaceInputSchema).min(1).max(5),
 });
apps/desktop/src/renderer/routes/_authenticated/components/AgentHooks/hooks/useCommandWatcher/tools/start-claude-session.ts (1)

30-30: Stale step number in comment.

The comment reads // 3. Append command to pending terminal setup — the preceding numbered steps were likely removed during this refactor, making the "3." misleading.

Suggested fix
-		// 3. Append command to pending terminal setup
+		// Append command to pending terminal setup

Comment on lines 10 to 12
async function execute(
params: z.infer<typeof schema>,
ctx: ToolContext,
): Promise<CommandResult> {

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.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find the ToolDefinition interface
find . -name 'types.ts' -path '*/useCommandWatcher/*' -o -name 'types.ts' -path '*/tools/*' | head -20

Repository: superset-sh/superset

Length of output: 174


🏁 Script executed:

# Search for ToolDefinition type definition
rg -n 'interface ToolDefinition|type ToolDefinition' --type=ts

Repository: superset-sh/superset

Length of output: 230


🏁 Script executed:

# Check how execute is called in the command watcher
rg -n 'tool\.execute\|\.execute\(' --type=ts -B2 -A3 | head -100

Repository: superset-sh/superset

Length of output: 46


🏁 Script executed:

# List all tool files to see what tools exist
fd '\.ts$' -path '*/useCommandWatcher/tools/*'

Repository: superset-sh/superset

Length of output: 232


🏁 Script executed:

# Read the ToolDefinition interface
cat -n apps/desktop/src/renderer/routes/_authenticated/components/AgentHooks/hooks/useCommandWatcher/tools/types.ts | head -100

Repository: superset-sh/superset

Length of output: 2293


🏁 Script executed:

# Find all tool files
fd -g '*.ts' apps/desktop/src/renderer/routes/_authenticated/components/AgentHooks/hooks/useCommandWatcher/tools/

Repository: superset-sh/superset

Length of output: 1364


🏁 Script executed:

# Search for where execute function is called/invoked
rg -n 'execute\(' --type=ts apps/desktop/src/renderer/routes/_authenticated/components/AgentHooks/hooks/useCommandWatcher/ -B2 -A2

Repository: superset-sh/superset

Length of output: 7040


Add ctx parameter to match the ToolDefinition interface and other tools.

The ToolDefinition interface requires execute to accept (params: z.infer<T>, ctx: ToolContext), but start-claude-subagent.ts omits the ctx parameter entirely. All other tools (create-worktree, delete-workspace, switch-workspace, etc.) include ctx, even when unused (prefixed with _). Add _ctx: ToolContext as the second parameter to maintain type contract consistency:

async function execute(
	params: z.infer<typeof schema>,
	_ctx: ToolContext,
): Promise<CommandResult> {
🤖 Prompt for AI Agents
In
`@apps/desktop/src/renderer/routes/_authenticated/components/AgentHooks/hooks/useCommandWatcher/tools/start-claude-subagent.ts`
around lines 10 - 12, The execute function in start-claude-subagent.ts currently
has the signature async function execute(params: z.infer<typeof schema>):
Promise<CommandResult> which violates the ToolDefinition contract used
elsewhere; update the signature to accept the ToolContext as a second parameter
(e.g., async function execute(params: z.infer<typeof schema>, _ctx:
ToolContext): Promise<CommandResult>) so it matches other tools
(create-worktree, delete-workspace, switch-workspace) and keeps type
consistency; ensure you import or reference ToolContext if needed and prefix the
parameter with an underscore if unused.

@github-actions

github-actions Bot commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

🚀 Preview Deployment

🔗 Preview Links

Service Status Link
Neon Database (Neon) ✅ View Branch
Fly.io Electric (Fly.io) ✅ View App
Vercel API (Vercel) ✅ Open Preview
Vercel Web (Vercel) ✅ Open Preview
Vercel Marketing (Vercel) ✅ Open Preview
Vercel Admin (Vercel) ✅ Open Preview
Vercel Docs (Vercel) ✅ Open Preview

Preview updates automatically with new commits

@Kitenite Kitenite closed this Feb 7, 2026
@Kitenite
Kitenite deleted the kitenite/create-workspace-mcp-result branch February 7, 2026 05:54

This branch was previously deployed

1 inactive deployment
preview — c9b3b651 Deployed Feb 7, 2026 by Kitenite via Deploy API #1603
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant