diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9301284..ebd56c7 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -37,8 +37,8 @@ jobs: node-version: 22 cache: "pnpm" - - name: Install npm 11+ for OIDC provenance publishing - run: corepack enable npm && corepack install -g npm@latest + - name: Install npm 11 for OIDC provenance publishing + run: corepack enable npm && corepack install -g npm@11 env: COREPACK_ENABLE_STRICT: 0 diff --git a/TOOLS.md b/TOOLS.md index 83ea0cc..6e4b014 100644 --- a/TOOLS.md +++ b/TOOLS.md @@ -1,4 +1,4 @@ -# Available Iterable MCP Tools (108 tools) +# Available Iterable MCP Tools (109 tools) **Legend:** - 🔒 = Requires enabling user PII access @@ -22,7 +22,7 @@ - **send_campaign** ✏️✉️: Send an existing scheduled campaign immediately - **trigger_campaign** ✏️✉️: Trigger a campaign to send to specified lists -## Catalogs (12 tools) +## Catalogs (13 tools) - **bulk_delete_catalog_items** ✏️: Bulk delete catalog items by their IDs - **create_catalog** ✏️: Create a new catalog - **delete_catalog** ✏️: Delete a catalog @@ -32,9 +32,10 @@ - **get_catalog_items**: Get items from a catalog with optional pagination and sorting - **get_catalogs**: Get list of all catalogs with optional pagination - **partial_update_catalog_item** ✏️: Partial update (PATCH) a catalog item - updates only specified fields +- **partial_update_catalog_items** ✏️: Bulk partial update (upsert) up to 1000 catalog items. documents maps each item ID to fields to merge; omitted fields on existing items are preserved. Creates items that do not exist yet. - **replace_catalog_item** ✏️: Replace (PUT) a catalog item - replaces the entire item with new value +- **replace_catalog_items** ✏️: Bulk replace (upsert) up to 1000 catalog items. documents maps each item ID to the item's complete new value; fields not included are removed from existing items. Creates items that do not exist yet. - **update_catalog_field_mappings** ✏️: Update catalog field mappings (data types). Valid types: boolean, date, geo_location, long, double, object, and string -- **update_catalog_items** ✏️: Update catalog items ## Data Export (5 tools) - **cancel_export_job** 🔒✏️: Cancel a queued or running export job created with 'start_export_job'. Use the jobId returned from the start export endpoint. diff --git a/package.json b/package.json index b472878..df55d65 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ }, "dependencies": { "@alcyone-labs/zod-to-json-schema": "4.0.10", - "@iterable/api": "0.11.1", + "@iterable/api": "0.12.0", "@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 737b688..4544a74 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: 4.0.10 version: 4.0.10(zod@4.3.6) '@iterable/api': - specifier: 0.11.1 - version: 0.11.1(typescript@6.0.2) + specifier: 0.12.0 + version: 0.12.0(typescript@6.0.2) '@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.11.1': - resolution: {integrity: sha512-Srj7NcvnpDNNp5B75onkJyMkvFgtS01TIWVbTATZwegxZHlc99irlJZ3K3yPuP19AkEzEuRtcK1D90IZ4ZTVhw==} + '@iterable/api@0.12.0': + resolution: {integrity: sha512-EW4Uwbr1wWJ7sh5pi39b/U2aQvdQy62psu0ZMVqoO3j5lG1VegbOXD6FHM9FNuLRQAq8TuE5Gy9q/BKCIQHFrg==} engines: {node: '>=18.0.0'} '@jest/console@30.2.0': @@ -1661,8 +1661,8 @@ packages: fn.name@1.1.0: resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} - follow-redirects@1.15.11: - resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -1674,8 +1674,8 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} engines: {node: '>= 6'} forwarded@0.2.0: @@ -1779,6 +1779,10 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -3260,7 +3264,7 @@ snapshots: '@istanbuljs/schema@0.1.3': {} - '@iterable/api@0.11.1(typescript@6.0.2)': + '@iterable/api@0.12.0(typescript@6.0.2)': dependencies: '@t3-oss/env-core': 0.13.11(typescript@6.0.2)(zod@4.3.6) axios: 1.13.6 @@ -3900,8 +3904,8 @@ snapshots: axios@1.13.6: dependencies: - follow-redirects: 1.15.11 - form-data: 4.0.5 + follow-redirects: 1.16.0 + form-data: 4.0.6 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug @@ -4186,7 +4190,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 has-tostringtag: 1.0.2 - hasown: 2.0.2 + hasown: 2.0.4 esbuild@0.25.12: optionalDependencies: @@ -4440,19 +4444,19 @@ snapshots: fn.name@1.1.0: {} - follow-redirects@1.15.11: {} + follow-redirects@1.16.0: {} foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data@4.0.5: + form-data@4.0.6: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 es-set-tostringtag: 2.1.0 - hasown: 2.0.2 + hasown: 2.0.4 mime-types: 2.1.35 forwarded@0.2.0: {} @@ -4549,6 +4553,10 @@ snapshots: dependencies: function-bind: 1.1.2 + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + html-escaper@2.0.2: {} http-errors@2.0.1: diff --git a/src/tool-filter.ts b/src/tool-filter.ts index ea82964..8376dc3 100644 --- a/src/tool-filter.ts +++ b/src/tool-filter.ts @@ -59,7 +59,8 @@ export const NON_PII_TOOLS: Set = new Set([ "send_campaign", "trigger_campaign", "update_catalog_field_mappings", - "update_catalog_items", + "partial_update_catalog_items", + "replace_catalog_items", "update_email_template", "update_inapp_template", "update_push_template", diff --git a/src/tools/catalogs.ts b/src/tools/catalogs.ts index 7cc0356..da814dc 100644 --- a/src/tools/catalogs.ts +++ b/src/tools/catalogs.ts @@ -13,9 +13,10 @@ import { GetCatalogItemsParamsSchema, GetCatalogsParamsSchema, PartialUpdateCatalogItemParamsSchema, + PartialUpdateCatalogItemsParamsSchema, ReplaceCatalogItemParamsSchema, + ReplaceCatalogItemsParamsSchema, UpdateCatalogFieldMappingsParamsSchema, - UpdateCatalogItemParamsSchema, } from "@iterable/api"; import type { Tool } from "@modelcontextprotocol/sdk/types.js"; @@ -30,10 +31,18 @@ export function createCatalogTools(client: IterableClient): Tool[] { execute: (params) => client.createCatalog(params), }), createTool({ - name: "update_catalog_items", - description: "Update catalog items", - schema: UpdateCatalogItemParamsSchema, - execute: (params) => client.updateCatalogItems(params), + name: "partial_update_catalog_items", + description: + "Bulk partial update catalog items (up to 1000). Merges document fields per item ID.", + schema: PartialUpdateCatalogItemsParamsSchema, + execute: (params) => client.partialUpdateCatalogItems(params), + }), + createTool({ + name: "replace_catalog_items", + description: + "Bulk replace catalog items (up to 1000). Each item becomes only the document fields provided.", + schema: ReplaceCatalogItemsParamsSchema, + execute: (params) => client.replaceCatalogItems(params), }), createTool({ name: "get_catalog_item", diff --git a/tests/unit/tools.test.ts b/tests/unit/tools.test.ts index 221de8b..f008b92 100644 --- a/tests/unit/tools.test.ts +++ b/tests/unit/tools.test.ts @@ -101,7 +101,8 @@ const EXPECTED_TOOLS = [ "unsubscribe_user_by_email", "unsubscribe_user_by_userid", "update_catalog_field_mappings", - "update_catalog_items", + "partial_update_catalog_items", + "replace_catalog_items", "update_email", "update_email_template", "update_inapp_template",