Files
oh-my-pi/packages/coding-agent/test/mcp-tool-args.test.ts
T
roboomp 60348404a0 fix(mcp): omitted unused optional tool args
Pruned empty optional MCP argument placeholders before tools/call while preserving required fields and meaningful falsy values.

Added regression coverage for active and deferred MCP tools.

Fixes #3302
2026-06-23 10:29:36 +00:00

90 lines
2.5 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import type { CustomToolContext } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools";
import { DeferredMCPTool, MCPTool, type MCPToolDefinition } from "@oh-my-pi/pi-coding-agent/mcp";
import type { MCPServerConnection } from "@oh-my-pi/pi-coding-agent/mcp/types";
import { createMockConnection, createMockTransport } from "./mcp-test-utils";
type CapturedRequest = {
method: string;
params: Record<string, unknown> | undefined;
};
const unusedContext = {} as CustomToolContext;
function createSearchToolDefinition(): MCPToolDefinition {
return {
name: "search",
description: "Search symbols or file locations",
inputSchema: {
type: "object",
properties: {
symbol: { type: "string" },
language: { type: "string" },
file: { type: "string" },
line: { type: "number" },
column: { type: "number" },
filters: { type: "object" },
exact: { type: "boolean" },
},
required: ["symbol", "language"],
},
};
}
function createCapturedConnection(calls: CapturedRequest[]): MCPServerConnection {
const transport = createMockTransport(
new Map([["tools/call", [{ content: [{ type: "text", text: "ok" }] }]]]),
(method, params) => calls.push({ method, params }),
);
return createMockConnection({ tools: {} }, transport);
}
describe("MCP tool arguments", () => {
it("omits optional empty placeholders before tools/call", async () => {
const calls: CapturedRequest[] = [];
const tool = new MCPTool(createCapturedConnection(calls), createSearchToolDefinition());
await tool.execute(
"call-1",
{ symbol: "Foo", language: "", file: "", line: 0, filters: {}, exact: false },
undefined,
unusedContext,
undefined,
);
expect(calls).toEqual([
{
method: "tools/call",
params: {
name: "search",
arguments: { symbol: "Foo", language: "", line: 0, exact: false },
},
},
]);
});
it("omits optional empty placeholders for deferred MCP tools", async () => {
const calls: CapturedRequest[] = [];
const connection = createCapturedConnection(calls);
const tool = new DeferredMCPTool("intellij-index", createSearchToolDefinition(), async () => connection);
await tool.execute(
"call-1",
{ symbol: "Foo", language: "TypeScript", file: "", column: "", filters: {} },
undefined,
unusedContext,
undefined,
);
expect(calls).toEqual([
{
method: "tools/call",
params: {
name: "search",
arguments: { symbol: "Foo", language: "TypeScript" },
},
},
]);
});
});