From d70738a4ce11ae7bb6b86abd8643d5bb4f4ad4b5 Mon Sep 17 00:00:00 2001 From: Kotesh Kumar Yelamati Date: Fri, 12 Jun 2026 19:24:41 -0400 Subject: [PATCH 1/2] fix(mcp): add minItems/maxItems to ctx_get ids schema The ctx_get handler enforces that ids must have 1-GET_IDS_MAX elements, but the inputSchema declared neither minItems nor maxItems. MCP clients had no way to know the array bounds up front. Adds minItems: 1 and maxItems: GET_IDS_MAX to the ids schema and updates the description to mention the lower bound. Runtime checks in ctxGet remain as the authoritative guard. Closes #34 --- packages/agentctx/src/mcp/tools.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/agentctx/src/mcp/tools.ts b/packages/agentctx/src/mcp/tools.ts index 5a566f6..0fdef2c 100644 --- a/packages/agentctx/src/mcp/tools.ts +++ b/packages/agentctx/src/mcp/tools.ts @@ -357,7 +357,9 @@ export function toolDefinitions(): ToolDefinition[] { ids: { type: "array", items: { type: "string" }, - description: `Record ids from ctx_search/ctx_related (max ${GET_IDS_MAX})`, + minItems: 1, + maxItems: GET_IDS_MAX, + description: `Record ids from ctx_search/ctx_related (at least 1, max ${GET_IDS_MAX})`, }, }, required: ["ids"], From cb3648c0f9a68565b966b7075169e5974d58bd47 Mon Sep 17 00:00:00 2001 From: Kotesh Kumar Yelamati Date: Tue, 14 Jul 2026 23:49:17 -0400 Subject: [PATCH 2/2] test(mcp): assert minItems/maxItems bounds on ctx_get ids schema --- packages/agentctx/test/mcp/tools.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/agentctx/test/mcp/tools.test.ts b/packages/agentctx/test/mcp/tools.test.ts index 2eddda3..9c2bb8c 100644 --- a/packages/agentctx/test/mcp/tools.test.ts +++ b/packages/agentctx/test/mcp/tools.test.ts @@ -171,6 +171,14 @@ describe("ctx_search", () => { }); describe("ctx_get", () => { + it("declares minItems/maxItems bounds on the ids schema", () => { + const schema = tools.find((tool) => tool.name === "ctx_get"); + const ids = (schema?.inputSchema as { properties: { ids: Record } }) + .properties.ids; + expect(ids.minItems).toBe(1); + expect(ids.maxItems).toBe(GET_IDS_MAX); + }); + it("returns full records, reports unknown ids as missing, and bumps access stats", () => { const record = seed({ title: "Full record", body: "the whole body" }); const { payload, isError } = call("ctx_get", { ids: [record.id, "nope"] });