diff --git a/src/resources/extensions/claude-code-cli/stream-adapter.ts b/src/resources/extensions/claude-code-cli/stream-adapter.ts index bd9bcf853..70c30e641 100644 --- a/src/resources/extensions/claude-code-cli/stream-adapter.ts +++ b/src/resources/extensions/claude-code-cli/stream-adapter.ts @@ -612,6 +612,13 @@ export function buildSdkOptions( const mcpServers = buildWorkflowMcpServers(); const permissionMode = overrides?.permissionMode ?? "bypassPermissions"; const disallowedTools = ["AskUserQuestion"]; + // Pre-authorize every registered workflow MCP server's tools. Without this, + // `acceptEdits` mode (the interactive default) auto-approves built-in + // Edit/Write/Bash but still gates MCP calls like `mcp__gsd-workflow__*`, + // surfacing "This command requires approval" on every GSD action (#4099). + const allowedTools = mcpServers + ? Object.keys(mcpServers).map((serverName) => `mcp__${serverName}__*`) + : []; return { pathToClaudeCodeExecutable: getClaudePath(), model: modelId, @@ -623,6 +630,7 @@ export function buildSdkOptions( settingSources: ["project"], systemPrompt: { type: "preset", preset: "claude_code" }, disallowedTools, + ...(allowedTools.length > 0 ? { allowedTools } : {}), ...(mcpServers ? { mcpServers } : {}), betas: modelId.includes("sonnet") ? ["context-1m-2025-08-07"] : [], ...extraOptions, diff --git a/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts b/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts index 056a15e01..3a9ce8934 100644 --- a/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +++ b/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts @@ -369,6 +369,7 @@ describe("stream-adapter — session persistence (#2859)", () => { assert.equal(srv.env.GSD_PERSIST_WRITE_GATE_STATE, "1"); assert.equal(srv.env.GSD_WORKFLOW_PROJECT_ROOT, "/tmp/project"); assert.deepEqual(options.disallowedTools, ["AskUserQuestion"]); + assert.deepEqual(options.allowedTools, ["mcp__gsd-workflow__*"]); } finally { process.env.GSD_WORKFLOW_MCP_COMMAND = prev.GSD_WORKFLOW_MCP_COMMAND; process.env.GSD_WORKFLOW_MCP_NAME = prev.GSD_WORKFLOW_MCP_NAME; @@ -397,6 +398,7 @@ describe("stream-adapter — session persistence (#2859)", () => { const mcpServers = options.mcpServers as Record; assert.ok(mcpServers?.["custom-workflow"], "expected custom workflow server config"); assert.deepEqual(options.disallowedTools, ["AskUserQuestion"]); + assert.deepEqual(options.allowedTools, ["mcp__custom-workflow__*"]); } finally { process.env.GSD_WORKFLOW_MCP_COMMAND = prev.GSD_WORKFLOW_MCP_COMMAND; process.env.GSD_WORKFLOW_MCP_NAME = prev.GSD_WORKFLOW_MCP_NAME;