feat: add MCP servers to agent mode

- Update agent mode to use prepareMcpConfig instead of empty config
- Update prepareMcpConfig to accept both ParsedGitHubContext and AutomationContext
- Add type guards for context-specific properties (isPR, entityNumber)
- This enables bot actors to use full MCP capabilities via workflow_dispatch
This commit is contained in:
km-anthropic
2025-08-01 13:54:35 -07:00
parent b4cc5cd6c5
commit 7cc3cff20b
2 changed files with 39 additions and 45 deletions

View File

@@ -1,6 +1,6 @@
import * as core from "@actions/core"; import * as core from "@actions/core";
import { GITHUB_API_URL, GITHUB_SERVER_URL } from "../github/api/config"; import { GITHUB_API_URL, GITHUB_SERVER_URL } from "../github/api/config";
import type { ParsedGitHubContext } from "../github/context"; import type { GitHubContext } from "../github/context";
import { Octokit } from "@octokit/rest"; import { Octokit } from "@octokit/rest";
type PrepareConfigParams = { type PrepareConfigParams = {
@@ -12,7 +12,7 @@ type PrepareConfigParams = {
additionalMcpConfig?: string; additionalMcpConfig?: string;
claudeCommentId?: string; claudeCommentId?: string;
allowedTools: string[]; allowedTools: string[];
context: ParsedGitHubContext; context: GitHubContext;
}; };
async function checkActionsReadPermission( async function checkActionsReadPermission(
@@ -115,7 +115,7 @@ export async function prepareMcpConfig(
const hasActionsReadPermission = const hasActionsReadPermission =
context.inputs.additionalPermissions.get("actions") === "read"; context.inputs.additionalPermissions.get("actions") === "read";
if (context.isPR && hasActionsReadPermission) { if ('isPR' in context && context.isPR && hasActionsReadPermission) {
// Verify the token actually has actions:read permission // Verify the token actually has actions:read permission
const actuallyHasPermission = await checkActionsReadPermission( const actuallyHasPermission = await checkActionsReadPermission(
process.env.ACTIONS_TOKEN || "", process.env.ACTIONS_TOKEN || "",
@@ -141,7 +141,7 @@ export async function prepareMcpConfig(
GITHUB_TOKEN: process.env.ACTIONS_TOKEN, GITHUB_TOKEN: process.env.ACTIONS_TOKEN,
REPO_OWNER: owner, REPO_OWNER: owner,
REPO_NAME: repo, REPO_NAME: repo,
PR_NUMBER: context.entityNumber?.toString() || "", PR_NUMBER: 'entityNumber' in context ? context.entityNumber?.toString() || "" : "",
RUNNER_TEMP: process.env.RUNNER_TEMP || "/tmp", RUNNER_TEMP: process.env.RUNNER_TEMP || "/tmp",
}, },
}; };

View File

@@ -1,7 +1,8 @@
import * as core from "@actions/core"; import * as core from "@actions/core";
import { mkdir, writeFile } from "fs/promises";
import type { Mode, ModeOptions, ModeResult } from "../types"; import type { Mode, ModeOptions, ModeResult } from "../types";
import { isAutomationContext } from "../../github/context"; import { isAutomationContext } from "../../github/context";
import type { PreparedContext } from "../../create-prompt/types";
import { prepareMcpConfig } from "../../mcp/install-mcp-server";
/** /**
* Agent mode implementation. * Agent mode implementation.
@@ -39,27 +40,10 @@ export const agentMode: Mode = {
return false; return false;
}, },
async prepare({ context }: ModeOptions): Promise<ModeResult> { async prepare({ context, githubToken }: ModeOptions): Promise<ModeResult> {
// Agent mode handles automation events (workflow_dispatch, schedule) only // Agent mode handles automation events (workflow_dispatch, schedule) only
// Create prompt directory // Agent mode doesn't need to create prompt files here - handled by createPrompt
await mkdir(`${process.env.RUNNER_TEMP}/claude-prompts`, {
recursive: true,
});
// Write the prompt file - the base action requires a prompt_file parameter,
// so we must create this file even though agent mode typically uses
// override_prompt or direct_prompt. If neither is provided, we write
// a minimal prompt with just the repository information.
const promptContent =
context.inputs.overridePrompt ||
context.inputs.directPrompt ||
`Repository: ${context.repository.owner}/${context.repository.repo}`;
await writeFile(
`${process.env.RUNNER_TEMP}/claude-prompts/claude-prompt.txt`,
promptContent,
);
// Export tool environment variables for agent mode // Export tool environment variables for agent mode
const baseTools = [ const baseTools = [
@@ -80,29 +64,25 @@ export const agentMode: Mode = {
...context.inputs.disallowedTools, ...context.inputs.disallowedTools,
]; ];
core.exportVariable("ALLOWED_TOOLS", allowedTools.join(",")); // Export as INPUT_ prefixed variables for the base action
core.exportVariable("DISALLOWED_TOOLS", disallowedTools.join(",")); core.exportVariable("INPUT_ALLOWED_TOOLS", allowedTools.join(","));
core.exportVariable("INPUT_DISALLOWED_TOOLS", disallowedTools.join(","));
// Agent mode uses a minimal MCP configuration // Get MCP configuration using the same setup as other modes
// We don't need comment servers or PR-specific tools for automation
const mcpConfig: any = {
mcpServers: {},
};
// Add user-provided additional MCP config if any
const additionalMcpConfig = process.env.MCP_CONFIG || ""; const additionalMcpConfig = process.env.MCP_CONFIG || "";
if (additionalMcpConfig.trim()) { const mcpConfig = await prepareMcpConfig({
try { githubToken,
const additional = JSON.parse(additionalMcpConfig); owner: context.repository.owner,
if (additional && typeof additional === "object") { repo: context.repository.repo,
Object.assign(mcpConfig, additional); branch: "", // Agent mode doesn't use branches
} baseBranch: "",
} catch (error) { additionalMcpConfig,
core.warning(`Failed to parse additional MCP config: ${error}`); claudeCommentId: undefined, // Agent mode doesn't track comments
} allowedTools: [...baseTools, ...context.inputs.allowedTools],
} context,
});
core.setOutput("mcp_config", JSON.stringify(mcpConfig)); core.setOutput("mcp_config", mcpConfig);
return { return {
commentId: undefined, commentId: undefined,
@@ -111,7 +91,21 @@ export const agentMode: Mode = {
currentBranch: "", currentBranch: "",
claudeBranch: undefined, claudeBranch: undefined,
}, },
mcpConfig: JSON.stringify(mcpConfig), mcpConfig: mcpConfig,
}; };
}, },
generatePrompt(context: PreparedContext): string {
// Agent mode uses override or direct prompt, no GitHub data needed
if (context.overridePrompt) {
return context.overridePrompt;
}
if (context.directPrompt) {
return context.directPrompt;
}
// Minimal fallback - repository is a string in PreparedContext
return `Repository: ${context.repository}`;
},
}; };