-
Notifications
You must be signed in to change notification settings - Fork 366
Fix MCP CLI bridge arg coercion, audit error envelopes, and logs cache readability #27020
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d76138e
d1c9aea
158995f
75fbbb5
754bf75
74d4cd9
f7376c4
03d0819
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; | ||
|
|
||
| import { formatResponse, parseToolArgs } from "./mcp_cli_bridge.cjs"; | ||
|
|
||
| describe("mcp_cli_bridge.cjs", () => { | ||
| let originalCore; | ||
| let stdoutSpy; | ||
| let stderrSpy; | ||
| /** @type {string[]} */ | ||
| let stdoutChunks; | ||
| /** @type {string[]} */ | ||
| let stderrChunks; | ||
|
|
||
| beforeEach(() => { | ||
| originalCore = global.core; | ||
| global.core = { | ||
| info: vi.fn(), | ||
| warning: vi.fn(), | ||
| error: vi.fn(), | ||
| setFailed: vi.fn(), | ||
| }; | ||
| process.exitCode = 0; | ||
| stdoutChunks = []; | ||
| stderrChunks = []; | ||
| stdoutSpy = vi.spyOn(process.stdout, "write").mockImplementation(chunk => { | ||
| stdoutChunks.push(String(chunk)); | ||
| return true; | ||
| }); | ||
| stderrSpy = vi.spyOn(process.stderr, "write").mockImplementation(chunk => { | ||
| stderrChunks.push(String(chunk)); | ||
| return true; | ||
| }); | ||
| }); | ||
|
|
||
| afterEach(() => { | ||
| stdoutSpy.mockRestore(); | ||
| stderrSpy.mockRestore(); | ||
| global.core = originalCore; | ||
| process.exitCode = 0; | ||
| }); | ||
|
|
||
| it("coerces integer and array arguments based on tool schema", () => { | ||
| const schemaProperties = { | ||
| count: { type: "integer" }, | ||
| workflows: { type: ["null", "array"] }, | ||
| }; | ||
|
|
||
| const { args } = parseToolArgs(["--count", "3", "--workflows", "daily-issues-report"], schemaProperties); | ||
|
|
||
| expect(args).toEqual({ | ||
| count: 3, | ||
| workflows: ["daily-issues-report"], | ||
| }); | ||
| }); | ||
|
|
||
| it("treats MCP result envelopes with isError=true as errors", () => { | ||
| formatResponse( | ||
| { | ||
| result: { | ||
| isError: true, | ||
| content: [{ type: "text", text: '{"error":"failed to audit workflow run"}' }], | ||
| }, | ||
| }, | ||
| "agenticworkflows" | ||
| ); | ||
|
|
||
| expect(stdoutChunks.join("")).toBe(""); | ||
| expect(stderrChunks.join("")).toContain("failed to audit workflow run"); | ||
| expect(process.exitCode).toBe(1); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -359,6 +359,7 @@ Returns JSON with the following structure: | |
| return nil, nil, newMCPError(jsonrpc.CodeInternalError, "failed to audit workflow run: "+mainMsg, nil) | ||
| } | ||
| return &mcp.CallToolResult{ | ||
| IsError: true, | ||
| Content: []mcp.Content{&mcp.TextContent{Text: string(jsonBytes)}}, | ||
| }, nil, nil | ||
|
Comment on lines
361
to
364
|
||
| } | ||
|
|
@@ -461,6 +462,7 @@ Returns JSON describing the differences between the base run and each comparison | |
| return nil, nil, newMCPError(jsonrpc.CodeInternalError, "failed to diff workflow runs: "+mainMsg, nil) | ||
| } | ||
| return &mcp.CallToolResult{ | ||
| IsError: true, | ||
| Content: []mcp.Content{&mcp.TextContent{Text: string(jsonBytes)}}, | ||
| }, nil, nil | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cache file permissions are only forced to mcpLogsCacheFilePerm in the “file already exists” path. When creating a new file, the effective mode is still subject to the process umask, so callers may still get a non-world-readable file (e.g., 0600) even though mcpLogsCacheFilePerm is 0644. Consider chmod’ing the file after a successful write/close (and handling errors) so readability is guaranteed regardless of umask.