diff --git a/src/server/retainedSummaryDelivery.ts b/src/server/retainedSummaryDelivery.ts index 0bc703a7c..2ff7cee3d 100644 --- a/src/server/retainedSummaryDelivery.ts +++ b/src/server/retainedSummaryDelivery.ts @@ -1,3 +1,5 @@ +import { analysisDetailSchema } from "../contracts/analysisDetail.js"; + import type { EvidenceWriter } from "../application/investigation/InvestigationRecordPort.js"; import type { EvidenceLookup } from "../application/EvidenceInputResolver.js"; import { @@ -57,6 +59,7 @@ export const withoutDeliveryDetail = (operations: ReadonlySet) => (operation: string, parameters: Parameters): Parameters => { if (!operations.has(operation)) return parameters; + analysisDetailSchema.unwrap().optional().parse(parameters.detail); const { detail: _detail, ...selected } = parameters; return selected; }; diff --git a/tests/boundary/mcp/interfaceBuilderSummaryMcp.test.ts b/tests/boundary/mcp/interfaceBuilderSummaryMcp.test.ts index b62fcdf53..a33059c38 100644 --- a/tests/boundary/mcp/interfaceBuilderSummaryMcp.test.ts +++ b/tests/boundary/mcp/interfaceBuilderSummaryMcp.test.ts @@ -67,6 +67,14 @@ mcpTest( const app = await fixtureApp(); const client = await openProductionTarget(mcp, onTestFinished, app); + const invalidDetail = await client.callTool({ + name: "decode_interface_builder", + arguments: { detail: "brief" }, + }); + expect(parseMcpToolError(invalidDetail)).toMatchObject({ + error: { code: "invalid_request" }, + }); + // Summary first: its own retained parent must serve every later page. const summarized = await client.callTool({ name: "decode_interface_builder",