add debug mcp tool for testing, fix transport issues

This commit is contained in:
Colin McDonnell
2025-11-25 17:07:40 -08:00
parent 106de07802
commit 4ff547f673
7 changed files with 67 additions and 6 deletions
+2 -2
View File
@@ -128,7 +128,7 @@ const messageHandlers: {
toolName: item.tool, toolName: item.tool,
input: { input: {
server: item.server, server: item.server,
...((item as any).args || {}), ...((item as any).arguments || {}),
}, },
}); });
} }
@@ -167,7 +167,7 @@ const messageHandlers: {
const reasoningText = item.text.trim(); const reasoningText = item.text.trim();
// Remove markdown bold markers if present for cleaner output // Remove markdown bold markers if present for cleaner output
const cleanText = reasoningText.replace(/\*\*/g, ""); const cleanText = reasoningText.replace(/\*\*/g, "");
log.info(cleanText); log.box(cleanText, { title: "Codex" });
} }
}, },
error: (event) => { error: (event) => {
+1 -1
View File
@@ -1 +1 @@
write a comment to https://github.com/pullfrogai/scratch/pull/29 that tells a joke use debug_shell_command tool to run 'git status' and explain the result
+45
View File
@@ -0,0 +1,45 @@
import { type } from "arktype";
import { $ } from "../utils/shell.ts";
import type { ToolResult } from "./shared.ts";
import { tool } from "./shared.ts";
export const DebugShellCommand = type({});
export const DebugShellCommandTool = tool({
name: "debug_shell_command",
description:
"debug tool: runs 'git status' and returns the output. use this to test shell command execution in the MCP server.",
parameters: DebugShellCommand,
execute: async (): Promise<ToolResult> => {
try {
const result = $("git", ["status"]);
return {
content: [
{
type: "text",
text: JSON.stringify(
{
success: true,
command: "git status",
output: result.trim(),
},
null,
2
),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
},
});
+2
View File
@@ -9,6 +9,7 @@ import {
EditCommentTool, EditCommentTool,
UpdateWorkingCommentTool, UpdateWorkingCommentTool,
} from "./comment.ts"; } from "./comment.ts";
import { DebugShellCommandTool } from "./debug.ts";
import { IssueTool } from "./issue.ts"; import { IssueTool } from "./issue.ts";
import { PullRequestTool } from "./pr.ts"; import { PullRequestTool } from "./pr.ts";
import { PullRequestInfoTool } from "./prInfo.ts"; import { PullRequestInfoTool } from "./prInfo.ts";
@@ -35,6 +36,7 @@ addTools(server, [
GetReviewCommentsTool, GetReviewCommentsTool,
ListPullRequestReviewsTool, ListPullRequestReviewsTool,
GetCheckSuiteLogsTool, GetCheckSuiteLogsTool,
DebugShellCommandTool,
]); ]);
server.start(); server.start();
+1 -1
View File
@@ -6,7 +6,7 @@ export interface Mode {
prompt: string; prompt: string;
} }
const initialCommentInstruction = `Use ${ghPullfrogMcpName}/create_working_comment to create an initial Working Comment with a conversational description of what work you are about to perform.`; const initialCommentInstruction = `When the task is associated with an issue/PR, use ${ghPullfrogMcpName}/create_working_comment to create an initial Working Comment with a conversational description of what work you are about to perform.`;
export const modes: Mode[] = [ export const modes: Mode[] = [
{ {
+2
View File
@@ -141,6 +141,8 @@ Examples:
if (!result.success) { if (!result.success) {
process.exit(1); process.exit(1);
} }
process.exit(0);
} catch (err) { } catch (err) {
log.error((err as Error).message); log.error((err as Error).message);
process.exit(1); process.exit(1);
+14 -2
View File
@@ -29,8 +29,11 @@ interface ShellOptions {
*/ */
export function $(cmd: string, args: string[], options?: ShellOptions): string { export function $(cmd: string, args: string[], options?: ShellOptions): string {
const encoding = options?.encoding ?? "utf-8"; const encoding = options?.encoding ?? "utf-8";
// CRITICAL: use "ignore" for stdin instead of "inherit" to avoid breaking MCP transport
// when running inside an MCP server, stdin is used for JSON-RPC protocol
const result = spawnSync(cmd, args, { const result = spawnSync(cmd, args, {
stdio: ["inherit", "pipe", "pipe"], stdio: ["ignore", "pipe", "pipe"],
encoding, encoding,
cwd: options?.cwd, cwd: options?.cwd,
}); });
@@ -39,10 +42,19 @@ export function $(cmd: string, args: string[], options?: ShellOptions): string {
const stderr = result.stderr ?? ""; const stderr = result.stderr ?? "";
// Write output to process streams so it behaves like stdio: "inherit" // Write output to process streams so it behaves like stdio: "inherit"
// CRITICAL: when running inside an MCP server, stdout is used for JSON-RPC protocol
// so we must write to stderr instead to avoid corrupting the protocol
// Only log if log option is not explicitly set to false // Only log if log option is not explicitly set to false
if (options?.log !== false) { if (options?.log !== false) {
// if stdout is a TTY, it's safe to write to it; otherwise it's likely a pipe used for JSON-RPC
const canWriteToStdout = process.stdout.isTTY === true;
if (stdout) { if (stdout) {
process.stdout.write(stdout); if (canWriteToStdout) {
process.stdout.write(stdout);
} else {
// stdout is a pipe (MCP context) - write to stderr instead
process.stderr.write(stdout);
}
} }
if (stderr) { if (stderr) {
process.stderr.write(stderr); process.stderr.write(stderr);