switch to http mcp
This commit is contained in:
+1
-1
@@ -8,5 +8,5 @@ if git diff --cached --name-only | grep -q "^package.json$"; then
|
|||||||
pnpm build
|
pnpm build
|
||||||
|
|
||||||
# Add the built files and lockfile to the commit
|
# Add the built files and lockfile to the commit
|
||||||
git add entry mcp-server pnpm-lock.yaml
|
git add entry pnpm-lock.yaml
|
||||||
fi
|
fi
|
||||||
|
|||||||
+17
-21
@@ -177,34 +177,30 @@ const messageHandlers: {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure MCP servers for Codex using the CLI.
|
* Configure MCP servers for Codex using the CLI.
|
||||||
* Codex CLI syntax: codex mcp add <name> --env KEY=value -- <command> [args...]
|
* For HTTP-based servers, use: codex mcp add <name> --url <url>
|
||||||
*/
|
*/
|
||||||
function configureCodexMcpServers({ mcpServers, cliPath }: ConfigureMcpServersParams): void {
|
function configureCodexMcpServers({ mcpServers, cliPath }: ConfigureMcpServersParams): void {
|
||||||
for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
|
for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
|
||||||
const command = serverConfig.command;
|
if (serverConfig.type === "http") {
|
||||||
const args = serverConfig.args || [];
|
// HTTP-based MCP server - use --url flag
|
||||||
const envVars = serverConfig.env || {};
|
const addArgs = ["mcp", "add", serverName, "--url", serverConfig.url];
|
||||||
|
|
||||||
const addArgs = ["mcp", "add", serverName];
|
log.info(`Adding MCP server '${serverName}' at ${serverConfig.url}...`);
|
||||||
|
const addResult = spawnSync("node", [cliPath, ...addArgs], {
|
||||||
|
stdio: "pipe",
|
||||||
|
encoding: "utf-8",
|
||||||
|
});
|
||||||
|
|
||||||
// Add environment variables as --env flags first
|
if (addResult.status !== 0) {
|
||||||
for (const [key, value] of Object.entries(envVars)) {
|
throw new Error(
|
||||||
addArgs.push("--env", `${key}=${value}`);
|
`codex mcp add failed: ${addResult.stderr || addResult.stdout || "Unknown error"}`
|
||||||
}
|
);
|
||||||
|
}
|
||||||
addArgs.push("--", command, ...args);
|
log.info(`✓ MCP server '${serverName}' configured`);
|
||||||
|
} else {
|
||||||
log.info(`Adding MCP server '${serverName}'...`);
|
|
||||||
const addResult = spawnSync("node", [cliPath, ...addArgs], {
|
|
||||||
stdio: "pipe",
|
|
||||||
encoding: "utf-8",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (addResult.status !== 0) {
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`codex mcp add failed: ${addResult.stderr || addResult.stdout || "Unknown error"}`
|
`Unsupported MCP server type for Codex: ${(serverConfig as any).type || "unknown"}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
log.info(`✓ MCP server '${serverName}' configured`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-1
@@ -269,6 +269,22 @@ function configureCursorMcpServers({ mcpServers }: ConfigureMcpServersParams) {
|
|||||||
const cursorConfigDir = join(realHome, ".cursor");
|
const cursorConfigDir = join(realHome, ".cursor");
|
||||||
const mcpConfigPath = join(cursorConfigDir, "mcp.json");
|
const mcpConfigPath = join(cursorConfigDir, "mcp.json");
|
||||||
mkdirSync(cursorConfigDir, { recursive: true });
|
mkdirSync(cursorConfigDir, { recursive: true });
|
||||||
writeFileSync(mcpConfigPath, JSON.stringify({ mcpServers }, null, 2), "utf-8");
|
|
||||||
|
// Convert to Cursor's expected format (HTTP config)
|
||||||
|
const cursorMcpServers: Record<string, { type: string; url: string }> = {};
|
||||||
|
for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
|
||||||
|
if (serverConfig.type !== "http") {
|
||||||
|
throw new Error(
|
||||||
|
`Unsupported MCP server type for Cursor: ${(serverConfig as any).type || "unknown"}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
cursorMcpServers[serverName] = {
|
||||||
|
type: "http",
|
||||||
|
url: serverConfig.url,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFileSync(mcpConfigPath, JSON.stringify({ mcpServers: cursorMcpServers }, null, 2), "utf-8");
|
||||||
log.info(`MCP config written to ${mcpConfigPath}`);
|
log.info(`MCP config written to ${mcpConfigPath}`);
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-18
@@ -249,31 +249,31 @@ export const gemini = agent({
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure MCP servers for Gemini using the CLI.
|
* Configure MCP servers for Gemini using the CLI.
|
||||||
* Gemini CLI syntax: gemini mcp add <name> <commandOrUrl> [args...] --env KEY=value
|
* Gemini CLI syntax: gemini mcp add <name> <commandOrUrl> [args...] --transport <type>
|
||||||
|
* For HTTP-based servers, use: gemini mcp add <name> <url> --transport http
|
||||||
*/
|
*/
|
||||||
function configureGeminiMcpServers({ mcpServers, cliPath }: ConfigureMcpServersParams): void {
|
function configureGeminiMcpServers({ mcpServers, cliPath }: ConfigureMcpServersParams): void {
|
||||||
for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
|
for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
|
||||||
const command = serverConfig.command;
|
if (serverConfig.type === "http") {
|
||||||
const args = serverConfig.args || [];
|
// HTTP-based MCP server - use URL with --transport http flag
|
||||||
const envVars = serverConfig.env || {};
|
const addArgs = ["mcp", "add", serverName, serverConfig.url, "--transport", "http"];
|
||||||
|
|
||||||
const addArgs = ["mcp", "add", serverName, command, ...args];
|
log.info(`Adding MCP server '${serverName}' at ${serverConfig.url}...`);
|
||||||
|
const addResult = spawnSync("node", [cliPath, ...addArgs], {
|
||||||
|
stdio: "pipe",
|
||||||
|
encoding: "utf-8",
|
||||||
|
});
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(envVars)) {
|
if (addResult.status !== 0) {
|
||||||
addArgs.push("--env", `${key}=${value}`);
|
throw new Error(
|
||||||
}
|
`gemini mcp add failed: ${addResult.stderr || addResult.stdout || "Unknown error"}`
|
||||||
|
);
|
||||||
log.info(`Adding MCP server '${serverName}'...`);
|
}
|
||||||
const addResult = spawnSync("node", [cliPath, ...addArgs], {
|
log.info(`✓ MCP server '${serverName}' configured`);
|
||||||
stdio: "pipe",
|
} else {
|
||||||
encoding: "utf-8",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (addResult.status !== 0) {
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`gemini mcp add failed: ${addResult.stderr || addResult.stdout || "Unknown error"}`
|
`Unsupported MCP server type for Gemini: ${(serverConfig as any).type || "unknown"}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
log.info(`✓ MCP server '${serverName}' configured`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -4,7 +4,7 @@ import { mkdtemp } from "node:fs/promises";
|
|||||||
import { tmpdir } from "node:os";
|
import { tmpdir } from "node:os";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import { pipeline } from "node:stream/promises";
|
import { pipeline } from "node:stream/promises";
|
||||||
import type { McpStdioServerConfig } from "@anthropic-ai/claude-agent-sdk";
|
import type { McpHttpServerConfig } from "@anthropic-ai/claude-agent-sdk";
|
||||||
import type { show } from "@ark/util";
|
import type { show } from "@ark/util";
|
||||||
import { type AgentManifest, type AgentName, agentsManifest, type Payload } from "../external.ts";
|
import { type AgentManifest, type AgentName, agentsManifest, type Payload } from "../external.ts";
|
||||||
import { log } from "../utils/cli.ts";
|
import { log } from "../utils/cli.ts";
|
||||||
@@ -26,7 +26,7 @@ export interface AgentConfig {
|
|||||||
apiKey: string;
|
apiKey: string;
|
||||||
githubInstallationToken: string;
|
githubInstallationToken: string;
|
||||||
payload: Payload;
|
payload: Payload;
|
||||||
mcpServers: Record<string, McpStdioServerConfig>;
|
mcpServers: Record<string, McpHttpServerConfig>;
|
||||||
cliPath: string;
|
cliPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ export interface AgentConfig {
|
|||||||
* Parameters for configuring MCP servers
|
* Parameters for configuring MCP servers
|
||||||
*/
|
*/
|
||||||
export interface ConfigureMcpServersParams {
|
export interface ConfigureMcpServersParams {
|
||||||
mcpServers: Record<string, McpStdioServerConfig>;
|
mcpServers: Record<string, McpHttpServerConfig>;
|
||||||
cliPath: string;
|
cliPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-9
@@ -59,7 +59,7 @@ const sharedConfig = {
|
|||||||
drop: [],
|
drop: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build the main entry bundle (without MCP)
|
// Build the main entry bundle
|
||||||
await build({
|
await build({
|
||||||
...sharedConfig,
|
...sharedConfig,
|
||||||
entryPoints: ["./entry.ts"],
|
entryPoints: ["./entry.ts"],
|
||||||
@@ -67,12 +67,4 @@ await build({
|
|||||||
plugins: [stripShebangPlugin],
|
plugins: [stripShebangPlugin],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Build the MCP server bundle
|
|
||||||
await build({
|
|
||||||
...sharedConfig,
|
|
||||||
entryPoints: ["./mcp/server.ts"],
|
|
||||||
outfile: "./mcp-server",
|
|
||||||
plugins: [stripShebangPlugin],
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("✅ Build completed successfully!");
|
console.log("✅ Build completed successfully!");
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import type { AgentResult } from "./agents/shared.ts";
|
|||||||
import type { AgentName, AgentName as AgentNameType, Payload } from "./external.ts";
|
import type { AgentName, AgentName as AgentNameType, Payload } from "./external.ts";
|
||||||
import { agentsManifest } from "./external.ts";
|
import { agentsManifest } from "./external.ts";
|
||||||
import { createMcpConfigs } from "./mcp/config.ts";
|
import { createMcpConfigs } from "./mcp/config.ts";
|
||||||
|
import { startMcpHttpServer } from "./mcp/server.ts";
|
||||||
import { modes } from "./modes.ts";
|
import { modes } from "./modes.ts";
|
||||||
import packageJson from "./package.json" with { type: "json" };
|
import packageJson from "./package.json" with { type: "json" };
|
||||||
import { fetchRepoSettings } from "./utils/api.ts";
|
import { fetchRepoSettings } from "./utils/api.ts";
|
||||||
@@ -17,6 +18,7 @@ import { log } from "./utils/cli.ts";
|
|||||||
import {
|
import {
|
||||||
parseRepoContext,
|
parseRepoContext,
|
||||||
type RepoContext,
|
type RepoContext,
|
||||||
|
revokeInstallationToken,
|
||||||
setupGitHubInstallationToken,
|
setupGitHubInstallationToken,
|
||||||
} from "./utils/github.ts";
|
} from "./utils/github.ts";
|
||||||
import { setupGitAuth, setupGitBranch, setupGitConfig } from "./utils/setup.ts";
|
import { setupGitAuth, setupGitBranch, setupGitConfig } from "./utils/setup.ts";
|
||||||
@@ -48,6 +50,8 @@ export interface MainResult {
|
|||||||
|
|
||||||
export async function main(inputs: Inputs): Promise<MainResult> {
|
export async function main(inputs: Inputs): Promise<MainResult> {
|
||||||
let pollInterval: NodeJS.Timeout | null = null;
|
let pollInterval: NodeJS.Timeout | null = null;
|
||||||
|
let mcpServerClose: (() => Promise<void>) | undefined;
|
||||||
|
let githubInstallationToken: string | undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// parse payload early to extract agent
|
// parse payload early to extract agent
|
||||||
@@ -55,13 +59,19 @@ export async function main(inputs: Inputs): Promise<MainResult> {
|
|||||||
|
|
||||||
const partialCtx = await initializeContext(inputs, payload);
|
const partialCtx = await initializeContext(inputs, payload);
|
||||||
const ctx = partialCtx as MainContext;
|
const ctx = partialCtx as MainContext;
|
||||||
|
githubInstallationToken = ctx.githubInstallationToken;
|
||||||
|
|
||||||
setupGitAuth(ctx);
|
setupGitAuth({
|
||||||
|
githubInstallationToken: ctx.githubInstallationToken,
|
||||||
|
repoContext: ctx.repoContext,
|
||||||
|
});
|
||||||
await setupTempDirectory(ctx);
|
await setupTempDirectory(ctx);
|
||||||
setupMcpLogPolling(ctx);
|
setupMcpLogPolling(ctx);
|
||||||
pollInterval = ctx.pollInterval;
|
pollInterval = ctx.pollInterval;
|
||||||
|
|
||||||
setupGitBranch(ctx.payload);
|
setupGitBranch(ctx.payload);
|
||||||
|
await startMcpServer(ctx);
|
||||||
|
mcpServerClose = ctx.mcpServerClose;
|
||||||
setupMcpServers(ctx);
|
setupMcpServers(ctx);
|
||||||
await installAgentCli(ctx);
|
await installAgentCli(ctx);
|
||||||
validateApiKey(ctx);
|
validateApiKey(ctx);
|
||||||
@@ -80,6 +90,12 @@ export async function main(inputs: Inputs): Promise<MainResult> {
|
|||||||
if (pollInterval) {
|
if (pollInterval) {
|
||||||
clearInterval(pollInterval);
|
clearInterval(pollInterval);
|
||||||
}
|
}
|
||||||
|
if (mcpServerClose) {
|
||||||
|
await mcpServerClose();
|
||||||
|
}
|
||||||
|
if (githubInstallationToken) {
|
||||||
|
await revokeInstallationToken(githubInstallationToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,6 +173,8 @@ interface MainContext {
|
|||||||
mcpLogPath: string;
|
mcpLogPath: string;
|
||||||
pollInterval: NodeJS.Timeout | null;
|
pollInterval: NodeJS.Timeout | null;
|
||||||
payload: Payload;
|
payload: Payload;
|
||||||
|
mcpServerUrl: string;
|
||||||
|
mcpServerClose: () => Promise<void>;
|
||||||
mcpServers: ReturnType<typeof createMcpConfigs>;
|
mcpServers: ReturnType<typeof createMcpConfigs>;
|
||||||
cliPath: string;
|
cliPath: string;
|
||||||
apiKey: string;
|
apiKey: string;
|
||||||
@@ -165,7 +183,9 @@ interface MainContext {
|
|||||||
async function initializeContext(
|
async function initializeContext(
|
||||||
inputs: Inputs,
|
inputs: Inputs,
|
||||||
payload: Payload
|
payload: Payload
|
||||||
): Promise<Omit<MainContext, "mcpServers" | "cliPath" | "apiKey">> {
|
): Promise<
|
||||||
|
Omit<MainContext, "mcpServerUrl" | "mcpServerClose" | "mcpServers" | "cliPath" | "apiKey">
|
||||||
|
> {
|
||||||
log.info(`🐸 Running pullfrog/action@${packageJson.version}...`);
|
log.info(`🐸 Running pullfrog/action@${packageJson.version}...`);
|
||||||
Inputs.assert(inputs);
|
Inputs.assert(inputs);
|
||||||
setupGitConfig();
|
setupGitConfig();
|
||||||
@@ -281,9 +301,27 @@ function parsePayload(inputs: Inputs): Payload {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupMcpServers(ctx: MainContext): void {
|
async function startMcpServer(ctx: MainContext): Promise<void> {
|
||||||
|
// Set environment variables for MCP server tools
|
||||||
|
const repoContext = parseRepoContext();
|
||||||
|
const githubRepository = `${repoContext.owner}/${repoContext.name}`;
|
||||||
const allModes = [...modes, ...(ctx.payload.modes || [])];
|
const allModes = [...modes, ...(ctx.payload.modes || [])];
|
||||||
ctx.mcpServers = createMcpConfigs(ctx.githubInstallationToken, allModes, ctx.payload);
|
|
||||||
|
process.env.GITHUB_INSTALLATION_TOKEN = ctx.githubInstallationToken;
|
||||||
|
process.env.GITHUB_REPOSITORY = githubRepository;
|
||||||
|
process.env.PULLFROG_MODES = JSON.stringify(allModes);
|
||||||
|
process.env.PULLFROG_PAYLOAD = JSON.stringify(ctx.payload);
|
||||||
|
|
||||||
|
// GITHUB_RUN_ID is already set in GitHub Actions, no need to set it here
|
||||||
|
|
||||||
|
const { url, close } = await startMcpHttpServer();
|
||||||
|
ctx.mcpServerUrl = url;
|
||||||
|
ctx.mcpServerClose = close;
|
||||||
|
log.info(`🚀 MCP server started at ${url}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupMcpServers(ctx: MainContext): void {
|
||||||
|
ctx.mcpServers = createMcpConfigs(ctx.mcpServerUrl);
|
||||||
log.debug(`📋 MCP Config: ${JSON.stringify(ctx.mcpServers, null, 2)}`);
|
log.debug(`📋 MCP Config: ${JSON.stringify(ctx.mcpServers, null, 2)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-107871
File diff suppressed because one or more lines are too long
+5
-35
@@ -2,48 +2,18 @@
|
|||||||
* Simple MCP configuration helper for adding our minimal GitHub comment server
|
* Simple MCP configuration helper for adding our minimal GitHub comment server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { McpStdioServerConfig } from "@anthropic-ai/claude-agent-sdk";
|
import type { McpHttpServerConfig } from "@anthropic-ai/claude-agent-sdk";
|
||||||
import { fromHere } from "@ark/fs";
|
|
||||||
import type { Payload } from "../external.ts";
|
|
||||||
import { ghPullfrogMcpName } from "../external.ts";
|
import { ghPullfrogMcpName } from "../external.ts";
|
||||||
import type { Mode } from "../modes.ts";
|
|
||||||
import { parseRepoContext } from "../utils/github.ts";
|
|
||||||
|
|
||||||
export type McpName = typeof ghPullfrogMcpName;
|
export type McpName = typeof ghPullfrogMcpName;
|
||||||
|
|
||||||
export type McpConfigs = Record<McpName, McpStdioServerConfig>;
|
export type McpConfigs = Record<McpName, McpHttpServerConfig>;
|
||||||
|
|
||||||
export function createMcpConfigs(
|
|
||||||
githubInstallationToken: string,
|
|
||||||
modes: Mode[],
|
|
||||||
payload: Payload
|
|
||||||
): McpConfigs {
|
|
||||||
const repoContext = parseRepoContext();
|
|
||||||
const githubRepository = `${repoContext.owner}/${repoContext.name}`;
|
|
||||||
|
|
||||||
// In production (GitHub Actions), mcp-server is in same directory as entry.js (where this is bundled)
|
|
||||||
// In development, server.ts is in the same directory as this file (config.ts)
|
|
||||||
const serverPath = process.env.GITHUB_ACTIONS ? fromHere("mcp-server") : fromHere("server.ts");
|
|
||||||
|
|
||||||
const env: Record<string, string> = {
|
|
||||||
GITHUB_INSTALLATION_TOKEN: githubInstallationToken,
|
|
||||||
GITHUB_REPOSITORY: githubRepository,
|
|
||||||
PULLFROG_MODES: JSON.stringify(modes),
|
|
||||||
PULLFROG_PAYLOAD: JSON.stringify(payload),
|
|
||||||
PULLFROG_TEMP_DIR: process.env.PULLFROG_TEMP_DIR!,
|
|
||||||
};
|
|
||||||
|
|
||||||
// pass through GITHUB_RUN_ID if available (automatically set in GitHub Actions)
|
|
||||||
// this is used to build the "View workflow run" link in comments
|
|
||||||
if (process.env.GITHUB_RUN_ID) {
|
|
||||||
env.GITHUB_RUN_ID = process.env.GITHUB_RUN_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
export function createMcpConfigs(mcpServerUrl: string): McpConfigs {
|
||||||
return {
|
return {
|
||||||
[ghPullfrogMcpName]: {
|
[ghPullfrogMcpName]: {
|
||||||
command: "node",
|
type: "http",
|
||||||
args: [serverPath],
|
url: mcpServerUrl,
|
||||||
env,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+75
-20
@@ -1,5 +1,6 @@
|
|||||||
import "./arkConfig.ts";
|
import "./arkConfig.ts";
|
||||||
// this must be imported first
|
// this must be imported first
|
||||||
|
import { createServer } from "node:net";
|
||||||
import { FastMCP } from "fastmcp";
|
import { FastMCP } from "fastmcp";
|
||||||
import { ghPullfrogMcpName } from "../external.ts";
|
import { ghPullfrogMcpName } from "../external.ts";
|
||||||
import { GetCheckSuiteLogsTool } from "./checkSuite.ts";
|
import { GetCheckSuiteLogsTool } from "./checkSuite.ts";
|
||||||
@@ -18,25 +19,79 @@ import { GetReviewCommentsTool, ListPullRequestReviewsTool } from "./reviewComme
|
|||||||
import { SelectModeTool } from "./selectMode.ts";
|
import { SelectModeTool } from "./selectMode.ts";
|
||||||
import { addTools } from "./shared.ts";
|
import { addTools } from "./shared.ts";
|
||||||
|
|
||||||
const server = new FastMCP({
|
/**
|
||||||
name: ghPullfrogMcpName,
|
* Find an available port starting from the given port
|
||||||
version: "0.0.1",
|
*/
|
||||||
});
|
async function findAvailablePort(startPort: number): Promise<number> {
|
||||||
|
const checkPort = (port: number): Promise<boolean> => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const server = createServer();
|
||||||
|
server.once("error", () => {
|
||||||
|
server.close();
|
||||||
|
resolve(false);
|
||||||
|
});
|
||||||
|
server.listen(port, () => {
|
||||||
|
server.close(() => {
|
||||||
|
resolve(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
addTools(server, [
|
let port = startPort;
|
||||||
SelectModeTool,
|
while (port < startPort + 100) {
|
||||||
CreateCommentTool,
|
if (await checkPort(port)) {
|
||||||
EditCommentTool,
|
return port;
|
||||||
CreateWorkingCommentTool,
|
}
|
||||||
UpdateWorkingCommentTool,
|
port++;
|
||||||
IssueTool,
|
}
|
||||||
PullRequestTool,
|
throw new Error(`Could not find available port starting from ${startPort}`);
|
||||||
ReviewTool,
|
}
|
||||||
PullRequestInfoTool,
|
|
||||||
GetReviewCommentsTool,
|
|
||||||
ListPullRequestReviewsTool,
|
|
||||||
GetCheckSuiteLogsTool,
|
|
||||||
DebugShellCommandTool,
|
|
||||||
]);
|
|
||||||
|
|
||||||
server.start();
|
/**
|
||||||
|
* Start the MCP HTTP server and return the URL and close function
|
||||||
|
*/
|
||||||
|
export async function startMcpHttpServer(): Promise<{ url: string; close: () => Promise<void> }> {
|
||||||
|
const server = new FastMCP({
|
||||||
|
name: ghPullfrogMcpName,
|
||||||
|
version: "0.0.1",
|
||||||
|
});
|
||||||
|
|
||||||
|
addTools(server, [
|
||||||
|
SelectModeTool,
|
||||||
|
CreateCommentTool,
|
||||||
|
EditCommentTool,
|
||||||
|
CreateWorkingCommentTool,
|
||||||
|
UpdateWorkingCommentTool,
|
||||||
|
IssueTool,
|
||||||
|
PullRequestTool,
|
||||||
|
ReviewTool,
|
||||||
|
PullRequestInfoTool,
|
||||||
|
GetReviewCommentsTool,
|
||||||
|
ListPullRequestReviewsTool,
|
||||||
|
GetCheckSuiteLogsTool,
|
||||||
|
DebugShellCommandTool,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const port = await findAvailablePort(3764);
|
||||||
|
const host = "127.0.0.1";
|
||||||
|
const endpoint = "/mcp";
|
||||||
|
|
||||||
|
await server.start({
|
||||||
|
transportType: "httpStream",
|
||||||
|
httpStream: {
|
||||||
|
port,
|
||||||
|
host,
|
||||||
|
endpoint,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = `http://${host}:${port}${endpoint}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
close: async () => {
|
||||||
|
await server.stop();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@pullfrog/action",
|
"name": "@pullfrog/action",
|
||||||
"version": "0.0.112",
|
"version": "0.0.113",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"files": [
|
"files": [
|
||||||
"index.js",
|
"index.js",
|
||||||
|
|||||||
Reference in New Issue
Block a user