Skip to content

Commit a38e29c

Browse files
committed
test(mcp): lock required and optional arguments through promotion
1 parent d97cf3a commit a38e29c

1 file changed

Lines changed: 78 additions & 0 deletions

File tree

‎tests/integration/mcp-late-dispatch.test.ts‎

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,82 @@ describe("integration — late MCP dispatch", () => {
191191
}
192192
},
193193
);
194+
195+
test.serial(
196+
"tool_search promotion preserves required and optional MCP arguments",
197+
async () => {
198+
const session = await openIntegrationSession({
199+
permissionGate: permissionGate(),
200+
createAgentFn: createAgentWithLiveToolDispatch,
201+
});
202+
let receivedArgs: Record<string, unknown> | undefined;
203+
const schema = {
204+
type: "object" as const,
205+
properties: {
206+
limit: { type: "integer" },
207+
team: { type: "string" },
208+
customView: { type: "string" },
209+
},
210+
required: ["limit"],
211+
};
212+
213+
try {
214+
const client: MCPClient = {
215+
serverName: "linear",
216+
tools: [
217+
{
218+
name: "list_issues",
219+
description: "list issues",
220+
inputSchema: schema,
221+
},
222+
],
223+
async call(toolName, args) {
224+
if (toolName === "list_issues") {
225+
receivedArgs = args;
226+
}
227+
return "ISSUE-1";
228+
},
229+
async close() {
230+
return undefined;
231+
},
232+
};
233+
session.toolset.dynamicRunner.addTools(mcpClientTools(client));
234+
session.toolset.setToolPromoter(() => {
235+
session.updateToolDefinitions(
236+
session.toolset.dynamicRunner.currentDefinitions(),
237+
);
238+
});
239+
session.harness.scenario.replyOnce("anthropic", {
240+
toolCalls: [
241+
{ name: "tool_search", args: { query: "linear list issues" } },
242+
],
243+
});
244+
session.harness.scenario.replyOnce("anthropic", {
245+
toolCalls: [{ name: LATE_MCP, args: { limit: 1 } }],
246+
});
247+
session.harness.scenario.replyOnce("anthropic", { text: "listed" });
248+
249+
const { events } = await runUntilDone(session, "list one linear issue");
250+
const bodies = await Promise.all(
251+
session.harness.scenario
252+
.matchedRequests()
253+
.map(
254+
async (request) =>
255+
JSON.parse(
256+
await (request.clone() as unknown as Request).text(),
257+
) as AnthropicRequestBody,
258+
),
259+
);
260+
const publishedTool = bodies
261+
.flatMap((body) => body.tools ?? [])
262+
.find((tool) => tool.name === LATE_MCP);
263+
264+
expect(publishedTool?.input_schema).toEqual(schema);
265+
expect(receivedArgs).toEqual({ limit: 1 });
266+
expect(toolDoneContents(events)).toContain("ISSUE-1");
267+
} finally {
268+
await closeIntegrationSession(session);
269+
}
270+
},
271+
);
194272
});

0 commit comments

Comments
 (0)