cleanup mcp server too

This commit is contained in:
Mateusz Burzyński
2026-01-08 11:21:23 +01:00
parent 2bd12b9553
commit 317ebd3431
3 changed files with 125 additions and 131 deletions
+114 -112
View File
@@ -126416,7 +126416,7 @@ async function startMcpHttpServer(ctx) {
const url2 = `http://${host}:${port}${endpoint2}`; const url2 = `http://${host}:${port}${endpoint2}`;
return { return {
url: url2, url: url2,
close: async () => { [Symbol.asyncDispose]: async () => {
await server.stop(); await server.stop();
} }
}; };
@@ -126556,120 +126556,125 @@ var Inputs = type({
...keyInputDefs ...keyInputDefs
}); });
async function main(inputs) { async function main(inputs) {
var _stack = []; var _stack2 = [];
try { try {
const timer = new Timer(); const timer = new Timer();
const installationToken = __using(_stack, await setupGitHubInstallationToken(), true); const tokenRef = __using(_stack2, await setupGitHubInstallationToken(), true);
let mcpServerClose;
let payload; let payload;
try { try {
payload = parsePayload(inputs); var _stack = [];
Inputs.assert(inputs); try {
setupGitConfig(); payload = parsePayload(inputs);
const [githubSetup, sharedTempDir] = await Promise.all([ Inputs.assert(inputs);
initializeGitHub(installationToken.token), setupGitConfig();
createTempDirectory() const [githubSetup, sharedTempDir] = await Promise.all([
]); initializeGitHub(tokenRef.token),
timer.checkpoint("githubSetup"); createTempDirectory()
const agent2 = resolveAgent({ ]);
inputs, timer.checkpoint("githubSetup");
payload, const agent2 = resolveAgent({
repoSettings: githubSetup.repoSettings inputs,
}); payload,
const resolvedPayload = { ...payload, agent: agent2.name }; repoSettings: githubSetup.repoSettings
const apiKeySetup = validateApiKey({ });
agent: agent2, const resolvedPayload = { ...payload, agent: agent2.name };
inputs, const apiKeySetup = validateApiKey({
owner: githubSetup.owner, agent: agent2,
name: githubSetup.name inputs,
}); owner: githubSetup.owner,
if (!apiKeySetup.success) { name: githubSetup.name
await reportErrorToComment({ error: apiKeySetup.error }); });
return { success: false, error: apiKeySetup.error }; if (!apiKeySetup.success) {
} await reportErrorToComment({ error: apiKeySetup.error });
const toolState = {}; return { success: false, error: apiKeySetup.error };
const [cliPath] = await Promise.all([ }
installAgentCli({ agent: agent2, token: installationToken.token }), const toolState = {};
setupGitAuth({ const [cliPath] = await Promise.all([
token: installationToken.token, installAgentCli({ agent: agent2, token: tokenRef.token }),
setupGitAuth({
token: tokenRef.token,
owner: githubSetup.owner,
name: githubSetup.name,
payload: resolvedPayload,
octokit: githubSetup.octokit,
toolState
})
]);
timer.checkpoint("agentSetup+gitAuth");
const computedModes = [
...getModes({
disableProgressComment: resolvedPayload.disableProgressComment
}),
...resolvedPayload.modes || []
];
const runId = process.env.GITHUB_RUN_ID || "";
if (runId) {
const workflowRunInfo = await fetchWorkflowRunInfo(runId);
if (workflowRunInfo.progressCommentId) {
process.env.PULLFROG_PROGRESS_COMMENT_ID = workflowRunInfo.progressCommentId;
log.info(`\u{1F4DD} Using pre-created progress comment: ${workflowRunInfo.progressCommentId}`);
}
}
let jobId;
const jobName = process.env.GITHUB_JOB;
if (jobName && runId) {
const jobs = await githubSetup.octokit.rest.actions.listJobsForWorkflowRun({
owner: githubSetup.owner,
repo: githubSetup.name,
run_id: parseInt(runId, 10)
});
const matchingJob = jobs.data.jobs.find((job) => job.name === jobName);
if (matchingJob) {
jobId = String(matchingJob.id);
log.info(`\u{1F4CB} Found job ID: ${jobId}`);
}
}
const toolContext = {
owner: githubSetup.owner, owner: githubSetup.owner,
name: githubSetup.name, name: githubSetup.name,
payload: resolvedPayload, githubInstallationToken: tokenRef.token,
octokit: githubSetup.octokit, octokit: githubSetup.octokit,
toolState payload: resolvedPayload,
}) repo: githubSetup.repo,
]); repoSettings: githubSetup.repoSettings,
timer.checkpoint("agentSetup+gitAuth"); modes: computedModes,
const computedModes = [ toolState,
...getModes({ agent: agent2,
disableProgressComment: resolvedPayload.disableProgressComment sharedTempDir,
}), runId,
...resolvedPayload.modes || [] jobId
]; };
const runId = process.env.GITHUB_RUN_ID || ""; const mcpHttpServer = __using(_stack, await startMcpHttpServer(toolContext), true);
if (runId) { log.info(`\u{1F680} MCP server started at ${mcpHttpServer.url}`);
const workflowRunInfo = await fetchWorkflowRunInfo(runId); const mcpServers = createMcpConfigs(mcpHttpServer.url);
if (workflowRunInfo.progressCommentId) { log.debug(`\u{1F4CB} MCP Config: ${JSON.stringify(mcpServers, null, 2)}`);
process.env.PULLFROG_PROGRESS_COMMENT_ID = workflowRunInfo.progressCommentId; timer.checkpoint("mcpServer");
log.info(`\u{1F4DD} Using pre-created progress comment: ${workflowRunInfo.progressCommentId}`); const ctx = {
} ...toolContext,
} inputs,
let jobId; mcpServerUrl: mcpHttpServer.url,
const jobName = process.env.GITHUB_JOB; mcpServers,
if (jobName && runId) { cliPath,
const jobs = await githubSetup.octokit.rest.actions.listJobsForWorkflowRun({ apiKey: apiKeySetup.apiKey,
owner: githubSetup.owner, apiKeys: apiKeySetup.apiKeys
repo: githubSetup.name, };
run_id: parseInt(runId, 10) if (ctx.payload.event.trigger === "fix_review" && Array.isArray(ctx.payload.event.comment_ids) && ctx.payload.event.comment_ids.length === 0) {
}); const noThumbsMessage = `\u{1F44D} **No approved comments found**
const matchingJob = jobs.data.jobs.find((job) => job.name === jobName);
if (matchingJob) {
jobId = String(matchingJob.id);
log.info(`\u{1F4CB} Found job ID: ${jobId}`);
}
}
const toolContext = {
owner: githubSetup.owner,
name: githubSetup.name,
githubInstallationToken: installationToken.token,
octokit: githubSetup.octokit,
payload: resolvedPayload,
repo: githubSetup.repo,
repoSettings: githubSetup.repoSettings,
modes: computedModes,
toolState,
agent: agent2,
sharedTempDir,
runId,
jobId
};
const { url: mcpServerUrl, close: mcpServerCloseFunc } = await startMcpHttpServer(toolContext);
mcpServerClose = mcpServerCloseFunc;
log.info(`\u{1F680} MCP server started at ${mcpServerUrl}`);
const mcpServers = createMcpConfigs(mcpServerUrl);
log.debug(`\u{1F4CB} MCP Config: ${JSON.stringify(mcpServers, null, 2)}`);
timer.checkpoint("mcpServer");
const ctx = {
...toolContext,
inputs,
mcpServerUrl,
mcpServerClose: mcpServerCloseFunc,
mcpServers,
cliPath,
apiKey: apiKeySetup.apiKey,
apiKeys: apiKeySetup.apiKeys
};
if (ctx.payload.event.trigger === "fix_review" && Array.isArray(ctx.payload.event.comment_ids) && ctx.payload.event.comment_ids.length === 0) {
const noThumbsMessage = `\u{1F44D} **No approved comments found**
To use "Fix \u{1F44D}s", add a \u{1F44D} reaction to one or more inline review comments you want fixed.`; To use "Fix \u{1F44D}s", add a \u{1F44D} reaction to one or more inline review comments you want fixed.`;
log.error(noThumbsMessage); log.error(noThumbsMessage);
await reportProgress(ctx, { body: noThumbsMessage }); await reportProgress(ctx, { body: noThumbsMessage });
return { success: true }; return { success: true };
}
const result = await runAgent(ctx);
const mainResult = await handleAgentResult(result);
return mainResult;
} catch (_) {
var _error = _, _hasError = true;
} finally {
var _promise2 = __callDispose(_stack, _error, _hasError);
_promise2 && await _promise2;
} }
const result = await runAgent(ctx);
const mainResult = await handleAgentResult(result);
return mainResult;
} catch (error41) { } catch (error41) {
const errorMessage = error41 instanceof Error ? error41.message : "Unknown error occurred"; const errorMessage = error41 instanceof Error ? error41.message : "Unknown error occurred";
log.error(errorMessage); log.error(errorMessage);
@@ -126687,15 +126692,12 @@ To use "Fix \u{1F44D}s", add a \u{1F44D} reaction to one or more inline review c
await ensureProgressCommentUpdated(payload); await ensureProgressCommentUpdated(payload);
} catch { } catch {
} }
if (mcpServerClose) {
await mcpServerClose();
}
} }
} catch (_) { } catch (_2) {
var _error = _, _hasError = true; var _error2 = _2, _hasError2 = true;
} finally { } finally {
var _promise2 = __callDispose(_stack, _error, _hasError); var _promise3 = __callDispose(_stack2, _error2, _hasError2);
_promise2 && await _promise2; _promise3 && await _promise3;
} }
} }
function agentHasApiKeys(agent2, inputs) { function agentHasApiKeys(agent2, inputs) {
+9 -17
View File
@@ -66,8 +66,7 @@ type ApiKeySetup =
export async function main(inputs: Inputs): Promise<MainResult> { export async function main(inputs: Inputs): Promise<MainResult> {
const timer = new Timer(); const timer = new Timer();
await using installationToken = await setupGitHubInstallationToken(); await using tokenRef = await setupGitHubInstallationToken();
let mcpServerClose: (() => Promise<void>) | undefined;
let payload: Payload | undefined; let payload: Payload | undefined;
try { try {
@@ -78,7 +77,7 @@ export async function main(inputs: Inputs): Promise<MainResult> {
// phase 2: fast setup (github + temp dir) // phase 2: fast setup (github + temp dir)
const [githubSetup, sharedTempDir] = await Promise.all([ const [githubSetup, sharedTempDir] = await Promise.all([
initializeGitHub(installationToken.token), initializeGitHub(tokenRef.token),
createTempDirectory(), createTempDirectory(),
]); ]);
timer.checkpoint("githubSetup"); timer.checkpoint("githubSetup");
@@ -106,9 +105,9 @@ export async function main(inputs: Inputs): Promise<MainResult> {
// phase 5: parallel long-running operations (agent install + git auth) // phase 5: parallel long-running operations (agent install + git auth)
const toolState: ToolState = {}; const toolState: ToolState = {};
const [cliPath] = await Promise.all([ const [cliPath] = await Promise.all([
installAgentCli({ agent, token: installationToken.token }), installAgentCli({ agent, token: tokenRef.token }),
setupGitAuth({ setupGitAuth({
token: installationToken.token, token: tokenRef.token,
owner: githubSetup.owner, owner: githubSetup.owner,
name: githubSetup.name, name: githubSetup.name,
payload: resolvedPayload, payload: resolvedPayload,
@@ -155,7 +154,7 @@ export async function main(inputs: Inputs): Promise<MainResult> {
const toolContext: ToolContext = { const toolContext: ToolContext = {
owner: githubSetup.owner, owner: githubSetup.owner,
name: githubSetup.name, name: githubSetup.name,
githubInstallationToken: installationToken.token, githubInstallationToken: tokenRef.token,
octokit: githubSetup.octokit, octokit: githubSetup.octokit,
payload: resolvedPayload, payload: resolvedPayload,
repo: githubSetup.repo, repo: githubSetup.repo,
@@ -168,11 +167,10 @@ export async function main(inputs: Inputs): Promise<MainResult> {
jobId, jobId,
}; };
const { url: mcpServerUrl, close: mcpServerCloseFunc } = await startMcpHttpServer(toolContext); await using mcpHttpServer = await startMcpHttpServer(toolContext);
mcpServerClose = mcpServerCloseFunc; log.info(`🚀 MCP server started at ${mcpHttpServer.url}`);
log.info(`🚀 MCP server started at ${mcpServerUrl}`);
const mcpServers = createMcpConfigs(mcpServerUrl); const mcpServers = createMcpConfigs(mcpHttpServer.url);
log.debug(`📋 MCP Config: ${JSON.stringify(mcpServers, null, 2)}`); log.debug(`📋 MCP Config: ${JSON.stringify(mcpServers, null, 2)}`);
timer.checkpoint("mcpServer"); timer.checkpoint("mcpServer");
@@ -180,8 +178,7 @@ export async function main(inputs: Inputs): Promise<MainResult> {
const ctx: AgentContext = { const ctx: AgentContext = {
...toolContext, ...toolContext,
inputs, inputs,
mcpServerUrl, mcpServerUrl: mcpHttpServer.url,
mcpServerClose: mcpServerCloseFunc,
mcpServers, mcpServers,
cliPath, cliPath,
apiKey: apiKeySetup.apiKey, apiKey: apiKeySetup.apiKey,
@@ -224,10 +221,6 @@ export async function main(inputs: Inputs): Promise<MainResult> {
} catch { } catch {
// error updating comment, but don't let it mask the original error // error updating comment, but don't let it mask the original error
} }
if (mcpServerClose) {
await mcpServerClose();
}
} }
} }
@@ -319,7 +312,6 @@ export interface ToolContext {
export interface AgentContext extends Readonly<ToolContext> { export interface AgentContext extends Readonly<ToolContext> {
readonly inputs: Inputs; readonly inputs: Inputs;
readonly mcpServerUrl: string; readonly mcpServerUrl: string;
readonly mcpServerClose: () => Promise<void>;
readonly mcpServers: ReturnType<typeof createMcpConfigs>; readonly mcpServers: ReturnType<typeof createMcpConfigs>;
readonly cliPath: string; readonly cliPath: string;
readonly apiKey: string; readonly apiKey: string;
+2 -2
View File
@@ -64,7 +64,7 @@ async function findAvailablePort(startPort: number): Promise<number> {
*/ */
export async function startMcpHttpServer( export async function startMcpHttpServer(
ctx: ToolContext ctx: ToolContext
): Promise<{ url: string; close: () => Promise<void> }> { ): Promise<{ url: string; [Symbol.asyncDispose]: () => Promise<void> }> {
const server = new FastMCP({ const server = new FastMCP({
name: ghPullfrogMcpName, name: ghPullfrogMcpName,
version: "0.0.1", version: "0.0.1",
@@ -119,7 +119,7 @@ export async function startMcpHttpServer(
return { return {
url, url,
close: async () => { [Symbol.asyncDispose]: async () => {
await server.stop(); await server.stop();
}, },
}; };