diff --git a/TOOLS.md b/TOOLS.md index 4b1d0c9..a8770c7 100644 --- a/TOOLS.md +++ b/TOOLS.md @@ -1,4 +1,4 @@ -# Available Iterable MCP Tools (104 tools) +# Available Iterable MCP Tools (105 tools) **Legend:** - 🔒 = Requires enabling user PII access @@ -6,12 +6,13 @@ - ✉️ = Requires enabling sends -## Campaigns (13 tools) +## Campaigns (14 tools) - **abort_campaign** ✏️: Abort a campaign that is currently running - **activate_triggered_campaign** ✏️✉️: Activate a triggered campaign (requires API triggered campaign activation enabled) - **archive_campaigns** ✏️: Archive one or more campaigns. Scheduled/recurring campaigns will be cancelled, running campaigns will be aborted. - **cancel_campaign** ✏️: Cancel a scheduled or recurring campaign -- **create_campaign** ✏️✉️: Create a new blast or triggered campaign from an existing template. If listIds are provided, the campaign will be a blast campaign; it is created in Scheduled state and will be sent at the given sendAt time, which is required. If listIds are not provided, the campaign will be a triggered campaign in Ready state that must be activated before it can send. +- **create_and_schedule_campaign** ✏️✉️: Create a new blast campaign from an existing template and schedule it for delivery. The campaign is created in Scheduled state and will be sent to the specified lists at the given sendAt time. +- **create_triggered_campaign** ✏️: Create a new triggered campaign from an existing template. The campaign is created in Ready state and must be activated before it can send. - **deactivate_triggered_campaign** ✏️: Deactivate a triggered campaign (requires API triggered campaign deactivation enabled) - **get_campaign**: Get detailed information about a specific campaign - **get_campaign_metrics**: Get campaign performance metrics diff --git a/package.json b/package.json index f34cc09..7a82f21 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ }, "dependencies": { "@alcyone-labs/zod-to-json-schema": "4.0.10", - "@iterable/api": "0.6.1", + "@iterable/api": "0.7.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 ea192db..d75c028 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.6.1 - version: 0.6.1(typescript@5.9.3) + specifier: 0.7.0 + version: 0.7.0(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.6.1': - resolution: {integrity: sha512-Mh/CmmKllWs9dMMZa2wJM13bdMZ6+21m1xhJ41MtRJrK6vIj5EJuxNsUbRF4J4jxoK/m59pqybXhBR/JPpsb0w==} + '@iterable/api@0.7.0': + resolution: {integrity: sha512-VjO1nQt53VNoz/bADELKAJVdE9oUxXisSjMZdrp/Yo8r6+gxUxQohawQtfTr5ze0ygICmGDBC6Yrduec8oXlmA==} engines: {node: '>=18.0.0'} '@jest/console@30.2.0': @@ -3226,7 +3226,7 @@ snapshots: '@istanbuljs/schema@0.1.3': {} - '@iterable/api@0.6.1(typescript@5.9.3)': + '@iterable/api@0.7.0(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/tool-filter.ts b/src/tool-filter.ts index a4fc750..bec763c 100644 --- a/src/tool-filter.ts +++ b/src/tool-filter.ts @@ -13,7 +13,8 @@ export const NON_PII_TOOLS: Set = new Set([ "archive_campaigns", "bulk_delete_catalog_items", "cancel_campaign", - "create_campaign", + "create_and_schedule_campaign", + "create_triggered_campaign", "create_catalog", "create_list", "create_snippet", @@ -117,8 +118,8 @@ export const SEND_TOOLS: Set = new Set([ "send_campaign", "trigger_campaign", "schedule_campaign", - // Creating a blast campaign schedules a send (sendAt is required when listIds is provided) - "create_campaign", + // Creating a blast campaign schedules a send + "create_and_schedule_campaign", // Triggered campaigns can cause sends upon activation; block unless explicitly allowed "activate_triggered_campaign", // Journey triggers enqueue users which may send diff --git a/src/tools/campaigns.ts b/src/tools/campaigns.ts index c374484..47d9046 100644 --- a/src/tools/campaigns.ts +++ b/src/tools/campaigns.ts @@ -8,7 +8,8 @@ import { ActivateTriggeredCampaignParamsSchema, ArchiveCampaignsParamsSchema, CancelCampaignParamsSchema, - CreateCampaignParamsSchema, + CreateAndScheduleCampaignParamsSchema, + CreateTriggeredCampaignParamsSchema, DeactivateTriggeredCampaignParamsSchema, GetCampaignMetricsParamsSchema, GetCampaignParamsSchema, @@ -45,11 +46,18 @@ export function createCampaignTools(client: IterableClient): Tool[] { execute: (params) => client.getCampaignMetrics(params), }), createTool({ - name: "create_campaign", + name: "create_and_schedule_campaign", description: - "Create a new blast or triggered campaign from an existing template. If listIds are provided, the campaign will be a blast campaign; it is created in Scheduled state and will be sent at the given sendAt time, which is required. If listIds are not provided, the campaign will be a triggered campaign in Ready state that must be activated before it can send.", - schema: CreateCampaignParamsSchema, - execute: (params) => client.createCampaign(params), + "Create a new blast campaign from an existing template and schedule it for delivery. The campaign is created in Scheduled state and will be sent to the specified lists at the given sendAt time.", + schema: CreateAndScheduleCampaignParamsSchema, + execute: (params) => client.createAndScheduleCampaign(params), + }), + createTool({ + name: "create_triggered_campaign", + description: + "Create a new triggered campaign from an existing template. The campaign is created in Ready state and must be activated before it can send.", + schema: CreateTriggeredCampaignParamsSchema, + execute: (params) => client.createTriggeredCampaign(params), }), createTool({ name: "get_child_campaigns", diff --git a/tests/unit/prompts.test.ts b/tests/unit/prompts.test.ts index 0fdca60..23428f9 100644 --- a/tests/unit/prompts.test.ts +++ b/tests/unit/prompts.test.ts @@ -61,7 +61,8 @@ describe("MCP Prompts", () => { expect(promptNames).toContain("get-user-by-user-id"); expect(promptNames).toContain("get-campaigns"); expect(promptNames).toContain("get-experiment-metrics"); - expect(promptNames).toContain("create-campaign"); // Now included since we pass all tools + expect(promptNames).toContain("create-and-schedule-campaign"); + expect(promptNames).toContain("create-triggered-campaign"); expect(promptNames).toContain("get-child-campaigns"); }); @@ -131,7 +132,7 @@ describe("MCP Prompts", () => { expect(promptNames).toContain("get-campaigns"); // Should NOT include write or send tools - expect(promptNames).not.toContain("create-campaign"); + expect(promptNames).not.toContain("create-and-schedule-campaign"); expect(promptNames).not.toContain("update-user"); expect(promptNames).not.toContain("send-email"); expect(promptNames).not.toContain("send-email-template-proof"); diff --git a/tests/unit/send-tools-registry.test.ts b/tests/unit/send-tools-registry.test.ts index 4fc5a45..dd32258 100644 --- a/tests/unit/send-tools-registry.test.ts +++ b/tests/unit/send-tools-registry.test.ts @@ -28,7 +28,7 @@ describe("SEND_TOOLS registry", () => { "send_campaign", "trigger_campaign", "schedule_campaign", - "create_campaign", + "create_and_schedule_campaign", "activate_triggered_campaign", "trigger_journey", "track_event", diff --git a/tests/unit/tool-filter-defaults.test.ts b/tests/unit/tool-filter-defaults.test.ts index 9ca4d4b..71b10ae 100644 --- a/tests/unit/tool-filter-defaults.test.ts +++ b/tests/unit/tool-filter-defaults.test.ts @@ -10,7 +10,7 @@ describe("filterTools defaults", () => { } as any; const writeTool: any = { - name: "create_campaign", // NOT in READ_ONLY_TOOLS + name: "create_and_schedule_campaign", // NOT in READ_ONLY_TOOLS description: "", inputSchema: { type: "object", properties: {} }, handler: async () => ({}), @@ -26,7 +26,9 @@ describe("filterTools defaults", () => { }) ); expect(out.map((t) => t.name)).toContain("get_campaigns"); - expect(out.map((t) => t.name)).not.toContain("create_campaign"); + expect(out.map((t) => t.name)).not.toContain( + "create_and_schedule_campaign" + ); }); it("includes write tools when allowWrites=true", () => { @@ -38,6 +40,6 @@ describe("filterTools defaults", () => { allowSends: true, }) ); - expect(out.map((t) => t.name)).toContain("create_campaign"); + expect(out.map((t) => t.name)).toContain("create_and_schedule_campaign"); }); }); diff --git a/tests/unit/tool-filter-sends.test.ts b/tests/unit/tool-filter-sends.test.ts index 0a75912..add2d47 100644 --- a/tests/unit/tool-filter-sends.test.ts +++ b/tests/unit/tool-filter-sends.test.ts @@ -16,7 +16,7 @@ describe("filterTools with allowSends", () => { mkTool("send_campaign"), mkTool("trigger_campaign"), mkTool("schedule_campaign"), - mkTool("create_campaign"), + mkTool("create_and_schedule_campaign"), mkTool("track_event"), mkTool("track_bulk_events"), mkTool("trigger_journey"), @@ -47,7 +47,7 @@ describe("filterTools with allowSends", () => { expect(names.has("send_campaign")).toBe(false); expect(names.has("trigger_campaign")).toBe(false); expect(names.has("schedule_campaign")).toBe(false); - expect(names.has("create_campaign")).toBe(false); + expect(names.has("create_and_schedule_campaign")).toBe(false); expect(names.has("track_event")).toBe(false); expect(names.has("track_bulk_events")).toBe(false); expect(names.has("trigger_journey")).toBe(false); diff --git a/tests/unit/tool-filter.test.ts b/tests/unit/tool-filter.test.ts index df05190..ee80201 100644 --- a/tests/unit/tool-filter.test.ts +++ b/tests/unit/tool-filter.test.ts @@ -145,7 +145,8 @@ describe("Tool Filter", () => { const filteredNames = filteredTools.map((tool) => tool.name); const writeTools = [ - "create_campaign", + "create_and_schedule_campaign", + "create_triggered_campaign", "update_user", "delete_user_by_email", "delete_user_by_user_id", diff --git a/tests/unit/tools.test.ts b/tests/unit/tools.test.ts index d2ed048..ac7bd53 100644 --- a/tests/unit/tools.test.ts +++ b/tests/unit/tools.test.ts @@ -21,7 +21,8 @@ const EXPECTED_TOOLS = [ "cancel_sms", "cancel_web_push", "cancel_whatsapp", - "create_campaign", + "create_and_schedule_campaign", + "create_triggered_campaign", "create_catalog", "create_list", "create_snippet",