Files
claude-code-action/src/entrypoints/prepare.ts
km-anthropic d5fbc80b71 Fix MCP tool availability and shell escaping in tag mode
Pass MCP config and allowed tools through claude_args to ensure tools like
mcp__github_comment__update_claude_comment are properly available to Claude CLI.

Key changes:
- Tag mode outputs claude_args with MCP config (as JSON string) and allowed tools
- Fixed shell escaping vulnerability when JSON contains single quotes
- Agent mode passes through user-provided claude_args unchanged
- Re-added mcp_config input for users to provide custom MCP servers
- Cleaned up misleading comments and unused file operations
- Clarified test workflow is for fork testing

Security fix: Properly escape single quotes in MCP config JSON to prevent
shell injection vulnerabilities.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 06:42:03 -07:00

86 lines
2.6 KiB
TypeScript

#!/usr/bin/env bun
/**
* Prepare the Claude action by checking trigger conditions, verifying human actor,
* and creating the initial tracking comment
*/
import * as core from "@actions/core";
import { setupGitHubToken } from "../github/token";
import { checkWritePermissions } from "../github/validation/permissions";
import { createOctokit } from "../github/api/client";
import { parseGitHubContext, isEntityContext } from "../github/context";
import { getMode } from "../modes/registry";
import { prepare } from "../prepare";
async function run() {
try {
// Parse GitHub context first to enable mode detection
const context = parseGitHubContext();
// Auto-detect mode based on context
const mode = getMode(context);
// Setup GitHub token
const githubToken = await setupGitHubToken();
const octokit = createOctokit(githubToken);
// Step 3: Check write permissions (only for entity contexts)
if (isEntityContext(context)) {
const hasWritePermissions = await checkWritePermissions(
octokit.rest,
context,
);
if (!hasWritePermissions) {
throw new Error(
"Actor does not have write permissions to the repository",
);
}
}
// Check trigger conditions
const containsTrigger = mode.shouldTrigger(context);
// Set output for action.yml to check
core.setOutput("contains_trigger", containsTrigger.toString());
if (!containsTrigger) {
console.log("No trigger found, skipping remaining steps");
return;
}
// Step 5: Use the new modular prepare function
const result = await prepare({
context,
octokit,
mode,
githubToken,
});
// MCP config is handled by individual modes (tag/agent) and included in their claude_args output
// Step 6: Get system prompt from mode if available
if (mode.getSystemPrompt) {
const modeContext = mode.prepareContext(context, {
commentId: result.commentId,
baseBranch: result.branchInfo.baseBranch,
claudeBranch: result.branchInfo.claudeBranch,
});
const systemPrompt = mode.getSystemPrompt(modeContext);
if (systemPrompt) {
core.exportVariable("APPEND_SYSTEM_PROMPT", systemPrompt);
}
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
core.setFailed(`Prepare step failed with error: ${errorMessage}`);
// Also output the clean error message for the action to capture
core.setOutput("prepare_error", errorMessage);
process.exit(1);
}
}
if (import.meta.main) {
run();
}