Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions TOOLS.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# Available Iterable MCP Tools (104 tools)
# Available Iterable MCP Tools (105 tools)

**Legend:**
- 🔒 = Requires enabling user PII access
- ✏️ = Requires enabling writes
- ✉️ = 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
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions src/tool-filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export const NON_PII_TOOLS: Set<string> = 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",
Expand Down Expand Up @@ -117,8 +118,8 @@ export const SEND_TOOLS: Set<string> = 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
Expand Down
18 changes: 13 additions & 5 deletions src/tools/campaigns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
ActivateTriggeredCampaignParamsSchema,
ArchiveCampaignsParamsSchema,
CancelCampaignParamsSchema,
CreateCampaignParamsSchema,
CreateAndScheduleCampaignParamsSchema,
CreateTriggeredCampaignParamsSchema,
DeactivateTriggeredCampaignParamsSchema,
GetCampaignMetricsParamsSchema,
GetCampaignParamsSchema,
Expand Down Expand Up @@ -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",
Expand Down
5 changes: 3 additions & 2 deletions tests/unit/prompts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
});

Expand Down Expand Up @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/send-tools-registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
8 changes: 5 additions & 3 deletions tests/unit/tool-filter-defaults.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => ({}),
Expand All @@ -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", () => {
Expand All @@ -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");
});
});
4 changes: 2 additions & 2 deletions tests/unit/tool-filter-sends.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/tool-filter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down