From 8ccb3db0a4cd30c0a3f12d1a240372f30d2147a0 Mon Sep 17 00:00:00 2001 From: Greg Methvin Date: Tue, 25 Nov 2025 15:07:59 -0800 Subject: [PATCH] Work around schema parsing issue in Cursor --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- src/tools/snippets.ts | 35 +++++++++++++++++++++++++++++------ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 61e050b..f1d0474 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ }, "dependencies": { "@alcyone-labs/zod-to-json-schema": "4.0.10", - "@iterable/api": "0.5.0", + "@iterable/api": "0.5.1", "@modelcontextprotocol/sdk": "1.18.1", "@primno/dpapi": "2.0.1", "@types/json-schema": "7.0.15", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 66cd0ef..b1b14aa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: 4.0.10 version: 4.0.10(zod@4.1.11) '@iterable/api': - specifier: 0.5.0 - version: 0.5.0(typescript@5.9.3) + specifier: 0.5.1 + version: 0.5.1(typescript@5.9.3) '@modelcontextprotocol/sdk': specifier: 1.18.1 version: 1.18.1 @@ -654,8 +654,8 @@ packages: resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} - '@iterable/api@0.5.0': - resolution: {integrity: sha512-cxFhTzirG6kxr7DdgvRvBxZWoYX7NUPrebpxQsqfRFOwsnXdAA8nQVo5lnCtWmsmQHIp21hsXtL2A5kDIO6jzA==} + '@iterable/api@0.5.1': + resolution: {integrity: sha512-+tqqTANK9oGjmCKi/Z/WilcOjO79rQ9UuVZu4mKYWrsIv8xjYahSqLs9Lg0ZyM74yM+OdXUhh5l09UB5v+boUQ==} engines: {node: '>=18.0.0'} '@jest/console@30.2.0': @@ -3226,7 +3226,7 @@ snapshots: '@istanbuljs/schema@0.1.3': {} - '@iterable/api@0.5.0(typescript@5.9.3)': + '@iterable/api@0.5.1(typescript@5.9.3)': dependencies: '@t3-oss/env-core': 0.13.8(typescript@5.9.3)(zod@4.1.11) axios: 1.13.2 diff --git a/src/tools/snippets.ts b/src/tools/snippets.ts index abcc287..3f016d9 100644 --- a/src/tools/snippets.ts +++ b/src/tools/snippets.ts @@ -15,6 +15,19 @@ import { z } from "zod"; import { createTool } from "../schema-utils.js"; export function createSnippetTools(client: IterableClient): Tool[] { + // WORKAROUND: Cursor rejects valid JSON Schema with "type": ["string", "number"]. + // We accept strings only and convert numeric strings back to numbers. + // See: https://github.com/cursor/cursor/issues/3778 + const identifier: z.ZodString = z + .string() + .describe( + "Snippet ID or name (stringified). Provide either a snippet name (string) or snippet ID (as a string)." + ); + + function maybeConvertNumericString(value: string): string | number { + return /^\d+$/.test(value) ? Number(value) : value; + } + return [ createTool({ name: "get_snippets", @@ -33,22 +46,32 @@ export function createSnippetTools(client: IterableClient): Tool[] { createTool({ name: "get_snippet", description: "Get a snippet by ID (numeric) or name (string)", - schema: GetSnippetParamsSchema, - execute: (params) => client.getSnippet(params), + schema: GetSnippetParamsSchema.extend({ identifier }), + execute: ({ identifier }) => + client.getSnippet({ + identifier: maybeConvertNumericString(identifier), + }), }), createTool({ name: "update_snippet", description: "Update a snippet by ID (numeric) or name (string)", - schema: UpdateSnippetParamsSchema, - execute: (params) => client.updateSnippet(params), + schema: UpdateSnippetParamsSchema.extend({ identifier }), + execute: (params) => + client.updateSnippet({ + ...params, + identifier: maybeConvertNumericString(params.identifier), + }), }), createTool({ name: "delete_snippet", description: "Delete a snippet by ID (numeric) or name (string)", - schema: DeleteSnippetParamsSchema, - execute: (params) => client.deleteSnippet(params), + schema: DeleteSnippetParamsSchema.extend({ identifier }), + execute: ({ identifier }) => + client.deleteSnippet({ + identifier: maybeConvertNumericString(identifier), + }), }), ]; }