From 86016e92a483233740e1d8e831f92767f1212985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Sat, 10 Oct 2026 14:48:30 +0200 Subject: [PATCH] Reject unknown params in t3_thread_read The MCP server ignored unknown tool arguments and advertised additionalProperties: true, so paging with cursor/position/order was silently dropped and every read started at position 0. Marking the tool strict closes the schema and returns an error for unknown params. --- .../src/mcp/OrchestratorMcpToolkit.integration.test.ts | 6 ++++++ apps/server/src/mcp/toolkits/orchestrator/tools.ts | 2 ++ 2 files changed, 8 insertions(+) diff --git a/apps/server/src/mcp/OrchestratorMcpToolkit.integration.test.ts b/apps/server/src/mcp/OrchestratorMcpToolkit.integration.test.ts index e7e82eaddffb..3c8cd2cb0502 100644 --- a/apps/server/src/mcp/OrchestratorMcpToolkit.integration.test.ts +++ b/apps/server/src/mcp/OrchestratorMcpToolkit.integration.test.ts @@ -1416,6 +1416,12 @@ describe("orchestrator MCP toolkit", () => { expect(threadListTool?.tool.annotations?.idempotentHint).toBe(true); const threadReadTool = server.tools.find(({ tool }) => tool.name === "t3_thread_read"); expect(threadReadTool?.tool.annotations?.readOnlyHint).toBe(false); + expect(threadReadTool?.tool.inputSchema).toMatchObject({ additionalProperties: false }); + const unknownPagingParamError = yield* invoke("t3_thread_read", { + threadId: parentThreadId, + cursor: 90, + }).pipe(Effect.flip); + expect(unknownPagingParamError.message).toContain("Expected no excess property"); const threadUpdateTool = server.tools.find( ({ tool }) => tool.name === "t3_thread_update", ); diff --git a/apps/server/src/mcp/toolkits/orchestrator/tools.ts b/apps/server/src/mcp/toolkits/orchestrator/tools.ts index 33be4d24cb1f..2c328bbe1fe9 100644 --- a/apps/server/src/mcp/toolkits/orchestrator/tools.ts +++ b/apps/server/src/mcp/toolkits/orchestrator/tools.ts @@ -200,6 +200,8 @@ const ThreadReadTool = Tool.make("t3_thread_read", { dependencies, }) .annotate(Tool.Title, "Read a T3 thread") + // Strict so a misspelled paging param fails instead of silently reading from position 0. + .annotate(Tool.Strict, true) .annotate(Tool.Readonly, false) .annotate(Tool.Destructive, false) .annotate(Tool.Idempotent, true);