@misarmail/mcp 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +69 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +104 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/lib/api-client.d.ts +6 -0
  7. package/dist/lib/api-client.d.ts.map +1 -0
  8. package/dist/lib/api-client.js +64 -0
  9. package/dist/lib/api-client.js.map +1 -0
  10. package/dist/lib/auth.d.ts +10 -0
  11. package/dist/lib/auth.d.ts.map +1 -0
  12. package/dist/lib/auth.js +43 -0
  13. package/dist/lib/auth.js.map +1 -0
  14. package/dist/lib/errors.d.ts +3 -0
  15. package/dist/lib/errors.d.ts.map +1 -0
  16. package/dist/lib/errors.js +14 -0
  17. package/dist/lib/errors.js.map +1 -0
  18. package/dist/tools/ab-tests.d.ts +4 -0
  19. package/dist/tools/ab-tests.d.ts.map +1 -0
  20. package/dist/tools/ab-tests.js +81 -0
  21. package/dist/tools/ab-tests.js.map +1 -0
  22. package/dist/tools/ai.d.ts +4 -0
  23. package/dist/tools/ai.d.ts.map +1 -0
  24. package/dist/tools/ai.js +45 -0
  25. package/dist/tools/ai.js.map +1 -0
  26. package/dist/tools/analytics.d.ts +4 -0
  27. package/dist/tools/analytics.d.ts.map +1 -0
  28. package/dist/tools/analytics.js +46 -0
  29. package/dist/tools/analytics.js.map +1 -0
  30. package/dist/tools/automations.d.ts +4 -0
  31. package/dist/tools/automations.d.ts.map +1 -0
  32. package/dist/tools/automations.js +62 -0
  33. package/dist/tools/automations.js.map +1 -0
  34. package/dist/tools/campaigns.d.ts +4 -0
  35. package/dist/tools/campaigns.d.ts.map +1 -0
  36. package/dist/tools/campaigns.js +88 -0
  37. package/dist/tools/campaigns.js.map +1 -0
  38. package/dist/tools/contacts.d.ts +4 -0
  39. package/dist/tools/contacts.d.ts.map +1 -0
  40. package/dist/tools/contacts.js +98 -0
  41. package/dist/tools/contacts.js.map +1 -0
  42. package/dist/tools/domains.d.ts +4 -0
  43. package/dist/tools/domains.d.ts.map +1 -0
  44. package/dist/tools/domains.js +57 -0
  45. package/dist/tools/domains.js.map +1 -0
  46. package/dist/tools/forms.d.ts +4 -0
  47. package/dist/tools/forms.d.ts.map +1 -0
  48. package/dist/tools/forms.js +59 -0
  49. package/dist/tools/forms.js.map +1 -0
  50. package/dist/tools/inbox.d.ts +4 -0
  51. package/dist/tools/inbox.d.ts.map +1 -0
  52. package/dist/tools/inbox.js +69 -0
  53. package/dist/tools/inbox.js.map +1 -0
  54. package/dist/tools/integrations.d.ts +4 -0
  55. package/dist/tools/integrations.d.ts.map +1 -0
  56. package/dist/tools/integrations.js +58 -0
  57. package/dist/tools/integrations.js.map +1 -0
  58. package/dist/tools/marketplace.d.ts +4 -0
  59. package/dist/tools/marketplace.d.ts.map +1 -0
  60. package/dist/tools/marketplace.js +41 -0
  61. package/dist/tools/marketplace.js.map +1 -0
  62. package/dist/tools/sandbox.d.ts +4 -0
  63. package/dist/tools/sandbox.d.ts.map +1 -0
  64. package/dist/tools/sandbox.js +34 -0
  65. package/dist/tools/sandbox.js.map +1 -0
  66. package/dist/tools/send.d.ts +4 -0
  67. package/dist/tools/send.d.ts.map +1 -0
  68. package/dist/tools/send.js +85 -0
  69. package/dist/tools/send.js.map +1 -0
  70. package/dist/tools/templates.d.ts +4 -0
  71. package/dist/tools/templates.d.ts.map +1 -0
  72. package/dist/tools/templates.js +82 -0
  73. package/dist/tools/templates.js.map +1 -0
  74. package/dist/tools/validate.d.ts +4 -0
  75. package/dist/tools/validate.d.ts.map +1 -0
  76. package/dist/tools/validate.js +41 -0
  77. package/dist/tools/validate.js.map +1 -0
  78. package/package.json +47 -0
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # MisarMail MCP Server
2
+
3
+ Model Context Protocol server for the MisarMail API. Exposes email sending, campaign management, contact management, and analytics as MCP tools.
4
+
5
+ ## Tools
6
+
7
+ | Tool | Description |
8
+ |------|-------------|
9
+ | `send_email` | Send a transactional email |
10
+ | `list_campaigns` | List campaigns with filtering |
11
+ | `get_campaign` | Get a campaign by ID |
12
+ | `create_campaign` | Create a new campaign |
13
+ | `send_campaign` | Send a campaign immediately |
14
+ | `list_contacts` | List contacts with search |
15
+ | `create_contact` | Create a new contact |
16
+ | `import_contacts` | Bulk import contacts |
17
+ | `get_analytics` | Get aggregate or per-campaign analytics |
18
+ | `validate_email` | Validate an email address for deliverability |
19
+ | `list_sandbox_sends` | List emails sent in sandbox (test) mode |
20
+ | `clear_sandbox` | Clear all sandbox send records |
21
+ | `generate_subject_lines` | AI-generate subject line suggestions for a campaign |
22
+ | `list_ab_tests` | List A/B tests for a campaign |
23
+ | `create_ab_test` | Create a new A/B test for a campaign |
24
+ | `select_ab_test_winner` | Select the winning variant of an A/B test |
25
+ | `list_templates` | List saved email templates |
26
+ | `create_template` | Create a new email template |
27
+ | `render_template` | Render a template with variable substitution |
28
+
29
+ ## Setup
30
+
31
+ ### 1. Get an API key
32
+
33
+ Log in to [mail.misar.io](https://mail.misar.io), go to [Account → API Keys](https://mail.misar.io/account/api-keys), and create a key with the scopes you need (`send`, `read`, `contacts`, `analytics`).
34
+
35
+ ### 2. Configure your MCP client
36
+
37
+ Add the following to your MCP client config (e.g. `claude_desktop_config.json`):
38
+
39
+ ```json
40
+ {
41
+ "mcpServers": {
42
+ "misarmail": {
43
+ "command": "npx",
44
+ "args": ["-y", "@misarmail/mcp"],
45
+ "env": {
46
+ "MISARMAIL_API_KEY": "your_api_key_here"
47
+ }
48
+ }
49
+ }
50
+ }
51
+ ```
52
+
53
+ Claude Desktop config location:
54
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
55
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
56
+
57
+ ## Environment Variables
58
+
59
+ | Variable | Required | Description |
60
+ |----------|----------|-------------|
61
+ | `MISARMAIL_API_KEY` | Yes | MisarMail API key (`msk_...`) |
62
+ | `MISARMAIL_BASE_URL` | No | Override API base URL (default: `https://api.misar.io/mail/v1`) |
63
+
64
+ ## API Key Scopes Required
65
+
66
+ - `send` — required for `send_email`
67
+ - `read` or `send:marketing` — required for `list_campaigns`, `get_campaign`, `create_campaign`
68
+ - `read` or `contacts` — required for `list_contacts`, `create_contact`, `import_contacts`
69
+ - `analytics` — required for `get_analytics`
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import { campaignTools, handleCampaignTool } from "./tools/campaigns.js";
6
+ import { contactTools, handleContactTool } from "./tools/contacts.js";
7
+ import { sendTools, handleSendTool } from "./tools/send.js";
8
+ import { analyticsTools, handleAnalyticsTool } from "./tools/analytics.js";
9
+ import { templateTools, handleTemplateTool } from "./tools/templates.js";
10
+ import { validateTools, handleValidateTool } from "./tools/validate.js";
11
+ import { sandboxTools, handleSandboxTool } from "./tools/sandbox.js";
12
+ import { aiTools, handleAiTool } from "./tools/ai.js";
13
+ import { abTestTools, handleAbTestTool } from "./tools/ab-tests.js";
14
+ import { inboxTools, handleInboxTool } from "./tools/inbox.js";
15
+ import { automationTools, handleAutomationTool } from "./tools/automations.js";
16
+ import { domainTools, handleDomainTool } from "./tools/domains.js";
17
+ import { formTools, handleFormTool } from "./tools/forms.js";
18
+ import { marketplaceTools, handleMarketplaceTool } from "./tools/marketplace.js";
19
+ import { integrationTools, handleIntegrationTool } from "./tools/integrations.js";
20
+ if (!process.env.MISARMAIL_API_KEY) {
21
+ console.error("Error: MISARMAIL_API_KEY is not set. Get your API key at https://mail.misar.io/account/api-keys");
22
+ process.exit(1);
23
+ }
24
+ const ALL_TOOLS = [
25
+ ...sendTools,
26
+ ...campaignTools,
27
+ ...contactTools,
28
+ ...analyticsTools,
29
+ ...templateTools,
30
+ ...validateTools,
31
+ ...sandboxTools,
32
+ ...aiTools,
33
+ ...abTestTools,
34
+ ...inboxTools,
35
+ ...automationTools,
36
+ ...domainTools,
37
+ ...formTools,
38
+ ...marketplaceTools,
39
+ ...integrationTools,
40
+ ];
41
+ const TOOL_HANDLERS = {
42
+ send_email: handleSendTool,
43
+ list_campaigns: handleCampaignTool,
44
+ get_campaign: handleCampaignTool,
45
+ create_campaign: handleCampaignTool,
46
+ send_campaign: handleCampaignTool,
47
+ list_contacts: handleContactTool,
48
+ create_contact: handleContactTool,
49
+ import_contacts: handleContactTool,
50
+ get_analytics: handleAnalyticsTool,
51
+ list_templates: handleTemplateTool,
52
+ create_template: handleTemplateTool,
53
+ render_template: handleTemplateTool,
54
+ validate_email: handleValidateTool,
55
+ list_sandbox_sends: handleSandboxTool,
56
+ clear_sandbox: handleSandboxTool,
57
+ generate_subject_lines: handleAiTool,
58
+ list_ab_tests: handleAbTestTool,
59
+ create_ab_test: handleAbTestTool,
60
+ select_ab_test_winner: handleAbTestTool,
61
+ list_inbox_conversations: handleInboxTool,
62
+ get_inbox_conversation_messages: handleInboxTool,
63
+ categorize_inbox_emails: handleInboxTool,
64
+ list_automations: handleAutomationTool,
65
+ get_automation: handleAutomationTool,
66
+ toggle_automation: handleAutomationTool,
67
+ list_domains: handleDomainTool,
68
+ add_domain: handleDomainTool,
69
+ verify_domain: handleDomainTool,
70
+ list_forms: handleFormTool,
71
+ get_form: handleFormTool,
72
+ get_form_submissions: handleFormTool,
73
+ list_marketplace_items: handleMarketplaceTool,
74
+ get_marketplace_item: handleMarketplaceTool,
75
+ list_integrations: handleIntegrationTool,
76
+ get_integration: handleIntegrationTool,
77
+ toggle_integration: handleIntegrationTool,
78
+ };
79
+ const server = new Server({ name: "misar-mail", version: "1.0.0" }, { capabilities: { tools: {} } });
80
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: ALL_TOOLS }));
81
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
82
+ const { name, arguments: args = {} } = request.params;
83
+ const handler = TOOL_HANDLERS[name];
84
+ if (!handler) {
85
+ return {
86
+ content: [{ type: "text", text: `Unknown tool: ${name}` }],
87
+ isError: true,
88
+ };
89
+ }
90
+ try {
91
+ const text = await handler(name, args);
92
+ return { content: [{ type: "text", text }] };
93
+ }
94
+ catch (err) {
95
+ const message = err instanceof Error ? err.message : String(err);
96
+ return {
97
+ content: [{ type: "text", text: `Error: ${message}` }],
98
+ isError: true,
99
+ };
100
+ }
101
+ });
102
+ const transport = new StdioServerTransport();
103
+ await server.connect(transport);
104
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function buildQuery(params: Record<string, unknown>): string;
2
+ export declare function apiFetch<T>(path: string, options?: RequestInit): Promise<T>;
3
+ /** Like apiFetch, but targets a non-versioned (`/v1`-stripped) route. */
4
+ export declare function apiFetchRoot<T>(path: string, options?: RequestInit): Promise<T>;
5
+ export declare function apiUpload<T>(path: string, form: FormData): Promise<T>;
6
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAMlE;AAED,wBAAsB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,CAAC,CAAC,CAcrF;AAaD,yEAAyE;AACzE,wBAAsB,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,CAAC,CAAC,CAczF;AAED,wBAAsB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CAU3E"}
@@ -0,0 +1,64 @@
1
+ import { getApiKey, getBaseUrl } from "./auth.js";
2
+ import { apiError } from "./errors.js";
3
+ export function buildQuery(params) {
4
+ const entries = Object.entries(params).filter(([, v]) => v !== undefined && v !== null && v !== "");
5
+ if (!entries.length)
6
+ return "";
7
+ return "?" + new URLSearchParams(entries.map(([k, v]) => [k, String(v)])).toString();
8
+ }
9
+ export async function apiFetch(path, options = {}) {
10
+ const key = getApiKey();
11
+ const res = await fetch(`${getBaseUrl()}${path}`, {
12
+ ...options,
13
+ headers: {
14
+ "Content-Type": "application/json",
15
+ Authorization: `Bearer ${key}`,
16
+ "X-MCP-Source": "mcp_claude",
17
+ ...options.headers,
18
+ },
19
+ });
20
+ const body = await res.json().catch(() => ({}));
21
+ if (!res.ok)
22
+ throw apiError(res.status, body);
23
+ return body;
24
+ }
25
+ /**
26
+ * Base URL for routes that live OUTSIDE the versioned `/v1` namespace.
27
+ *
28
+ * Several MisarMail API groups (automations, domains, forms, marketplace,
29
+ * integrations, inbox, etc.) are served at `api.misar.io/mail/<group>` — NOT
30
+ * under `/mail/v1/<group>`. Strip the trailing `/v1` so those routes resolve.
31
+ */
32
+ function getRootBaseUrl() {
33
+ return getBaseUrl().replace(/\/v1$/, "");
34
+ }
35
+ /** Like apiFetch, but targets a non-versioned (`/v1`-stripped) route. */
36
+ export async function apiFetchRoot(path, options = {}) {
37
+ const key = getApiKey();
38
+ const res = await fetch(`${getRootBaseUrl()}${path}`, {
39
+ ...options,
40
+ headers: {
41
+ "Content-Type": "application/json",
42
+ Authorization: `Bearer ${key}`,
43
+ "X-MCP-Source": "mcp_claude",
44
+ ...options.headers,
45
+ },
46
+ });
47
+ const body = await res.json().catch(() => ({}));
48
+ if (!res.ok)
49
+ throw apiError(res.status, body);
50
+ return body;
51
+ }
52
+ export async function apiUpload(path, form) {
53
+ const key = getApiKey();
54
+ const res = await fetch(`${getBaseUrl()}${path}`, {
55
+ method: "POST",
56
+ headers: { Authorization: `Bearer ${key}`, "X-MCP-Source": "mcp_claude" },
57
+ body: form,
58
+ });
59
+ const body = await res.json().catch(() => ({}));
60
+ if (!res.ok)
61
+ throw apiError(res.status, body);
62
+ return body;
63
+ }
64
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ interface MisarConfig {
2
+ api_key?: string;
3
+ base_url?: string;
4
+ }
5
+ export declare function saveConfig(config: MisarConfig): void;
6
+ export declare function getApiKey(): string;
7
+ export declare function tryGetApiKey(): string | null;
8
+ export declare function getBaseUrl(): string;
9
+ export {};
10
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAMA,UAAU,WAAW;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAUD,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAGpD;AAED,wBAAgB,SAAS,IAAI,MAAM,CAQlC;AAED,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAM5C;AAED,wBAAgB,UAAU,IAAI,MAAM,CAMnC"}
@@ -0,0 +1,43 @@
1
+ import { readFileSync, writeFileSync, mkdirSync } from "fs";
2
+ import { homedir } from "os";
3
+ import { join } from "path";
4
+ const CONFIG_PATH = join(homedir(), ".misarmail", "config.json");
5
+ function loadConfig() {
6
+ try {
7
+ return JSON.parse(readFileSync(CONFIG_PATH, "utf8"));
8
+ }
9
+ catch {
10
+ return {};
11
+ }
12
+ }
13
+ export function saveConfig(config) {
14
+ mkdirSync(join(homedir(), ".misarmail"), { recursive: true });
15
+ writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
16
+ }
17
+ export function getApiKey() {
18
+ const envKey = process.env.MISARMAIL_API_KEY?.trim();
19
+ if (envKey)
20
+ return envKey;
21
+ const cfg = loadConfig();
22
+ if (cfg.api_key)
23
+ return cfg.api_key;
24
+ throw new Error("Not configured. Set MISARMAIL_API_KEY environment variable or run the login tool.");
25
+ }
26
+ export function tryGetApiKey() {
27
+ try {
28
+ return getApiKey();
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ export function getBaseUrl() {
35
+ const envUrl = (process.env.MISARMAIL_BASE_URL ?? "").trim();
36
+ if (envUrl)
37
+ return envUrl.replace(/\/$/, "");
38
+ const cfg = loadConfig();
39
+ if (cfg.base_url)
40
+ return cfg.base_url.replace(/\/$/, "");
41
+ return "https://api.misar.io/mail/v1";
42
+ }
43
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;AAOjE,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAmB;IAC5C,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;IACrD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;IACzB,IAAI,GAAG,CAAC,OAAO;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IACpC,MAAM,IAAI,KAAK,CACb,mFAAmF,CACpF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC;QACH,OAAO,SAAS,EAAE,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7D,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;IACzB,IAAI,GAAG,CAAC,QAAQ;QAAE,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACzD,OAAO,8BAA8B,CAAC;AACxC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function formatError(error: unknown): string;
2
+ export declare function apiError(status: number, body: unknown): Error;
3
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIlD;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,KAAK,CAM7D"}
@@ -0,0 +1,14 @@
1
+ export function formatError(error) {
2
+ if (error instanceof Error)
3
+ return error.message;
4
+ if (typeof error === "string")
5
+ return error;
6
+ return "An unknown error occurred";
7
+ }
8
+ export function apiError(status, body) {
9
+ const msg = typeof body === "object" && body !== null && "error" in body
10
+ ? String(body.error)
11
+ : `HTTP ${status}`;
12
+ return new Error(msg);
13
+ }
14
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,KAAK,YAAY,KAAK;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IACjD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,2BAA2B,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,IAAa;IACpD,MAAM,GAAG,GACP,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,IAAI;QAC1D,CAAC,CAAC,MAAM,CAAE,IAA2B,CAAC,KAAK,CAAC;QAC5C,CAAC,CAAC,QAAQ,MAAM,EAAE,CAAC;IACvB,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ export declare const abTestTools: Tool[];
3
+ export declare function handleAbTestTool(name: string, args: Record<string, unknown>): Promise<string>;
4
+ //# sourceMappingURL=ab-tests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ab-tests.d.ts","sourceRoot":"","sources":["../../src/tools/ab-tests.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAG/D,eAAO,MAAM,WAAW,EAAE,IAAI,EA0D7B,CAAC;AAEF,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
@@ -0,0 +1,81 @@
1
+ import { apiFetch, buildQuery } from "../lib/api-client.js";
2
+ export const abTestTools = [
3
+ {
4
+ name: "list_ab_tests",
5
+ description: "List A/B tests (campaign and subject line tests) with pagination.",
6
+ inputSchema: {
7
+ type: "object",
8
+ properties: {
9
+ page: { type: "number", description: "Page number (default: 1)" },
10
+ limit: { type: "number", description: "Results per page, max 50 (default: 20)" },
11
+ type: {
12
+ type: "string",
13
+ enum: ["campaign", "subject"],
14
+ description: "Filter by test type",
15
+ },
16
+ },
17
+ },
18
+ },
19
+ {
20
+ name: "create_ab_test",
21
+ description: "Create a new A/B test variant for a campaign.",
22
+ inputSchema: {
23
+ type: "object",
24
+ required: ["campaign_id", "variant"],
25
+ properties: {
26
+ campaign_id: { type: "string", description: "Campaign UUID" },
27
+ variant: { type: "string", description: "Variant label (1-5 chars), e.g. 'B'" },
28
+ test_type: {
29
+ type: "string",
30
+ enum: ["content", "subject", "send_time", "from_name", "preheader"],
31
+ description: "What to test (default: content)",
32
+ },
33
+ subject: { type: "string", description: "Variant subject line (max 255 chars)" },
34
+ preheader: { type: "string", description: "Variant preheader text (max 255 chars)" },
35
+ body_html: { type: "string", description: "Variant HTML body (max 500KB)" },
36
+ from_name: { type: "string", description: "Variant sender name (max 100 chars)" },
37
+ send_percent: { type: "number", description: "Percentage of audience for this variant (1-99, default: 50)" },
38
+ auto_select_winner: { type: "boolean", description: "Automatically select winner after wait period" },
39
+ winner_wait_hours: { type: "number", description: "Hours to wait before auto-selecting winner (1-168, default: 4)" },
40
+ },
41
+ },
42
+ },
43
+ {
44
+ name: "select_ab_test_winner",
45
+ description: "Select the winning variant for a campaign A/B test. Copies winning content back onto the parent campaign.",
46
+ inputSchema: {
47
+ type: "object",
48
+ required: ["test_id", "winner_variant"],
49
+ properties: {
50
+ test_id: { type: "string", description: "A/B test UUID (campaign_ab_tests.id)" },
51
+ winner_variant: { type: "string", description: "Variant label to declare winner" },
52
+ metric: {
53
+ type: "string",
54
+ enum: ["opens", "clicks", "revenue", "conversions"],
55
+ description: "Metric used to determine winner (default: opens)",
56
+ },
57
+ },
58
+ },
59
+ },
60
+ ];
61
+ export async function handleAbTestTool(name, args) {
62
+ switch (name) {
63
+ case "list_ab_tests": {
64
+ const qs = buildQuery({ page: args.page, limit: args.limit, type: args.type });
65
+ const data = await apiFetch(`/ab-tests${qs}`);
66
+ return JSON.stringify(data, null, 2);
67
+ }
68
+ case "create_ab_test": {
69
+ const data = await apiFetch("/ab-tests", { method: "POST", body: JSON.stringify(args) });
70
+ return JSON.stringify(data, null, 2);
71
+ }
72
+ case "select_ab_test_winner": {
73
+ const { test_id, ...body } = args;
74
+ const data = await apiFetch(`/ab-tests/${String(test_id)}/winner`, { method: "POST", body: JSON.stringify(body) });
75
+ return JSON.stringify(data, null, 2);
76
+ }
77
+ default:
78
+ throw new Error(`Unknown A/B test tool: ${name}`);
79
+ }
80
+ }
81
+ //# sourceMappingURL=ab-tests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ab-tests.js","sourceRoot":"","sources":["../../src/tools/ab-tests.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ export declare const aiTools: Tool[];
3
+ export declare function handleAiTool(name: string, args: Record<string, unknown>): Promise<string>;
4
+ //# sourceMappingURL=ai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/tools/ai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAG/D,eAAO,MAAM,OAAO,EAAE,IAAI,EAiCzB,CAAC;AAEF,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CASjB"}
@@ -0,0 +1,45 @@
1
+ import { apiFetch } from "../lib/api-client.js";
2
+ export const aiTools = [
3
+ {
4
+ name: "generate_subject_lines",
5
+ description: "Generate AI-optimized email subject lines for a campaign or newsletter. Returns up to 10 subject line suggestions with open-rate hints. Rate-limited to 10 requests/minute.",
6
+ inputSchema: {
7
+ type: "object",
8
+ required: ["topic"],
9
+ properties: {
10
+ topic: {
11
+ type: "string",
12
+ description: "Campaign topic or email content summary (min 5, max 500 chars)",
13
+ },
14
+ tone: {
15
+ type: "string",
16
+ enum: ["professional", "casual", "urgent", "playful", "informative"],
17
+ description: "Tone for the subject lines (default: professional)",
18
+ },
19
+ audience: {
20
+ type: "string",
21
+ description: "Target audience description, e.g. 'SaaS customers' (max 200 chars)",
22
+ },
23
+ count: {
24
+ type: "number",
25
+ description: "Number of subject lines to generate (1-10, default: 5)",
26
+ },
27
+ brand: {
28
+ type: "string",
29
+ description: "Brand name to include context (max 100 chars)",
30
+ },
31
+ },
32
+ },
33
+ },
34
+ ];
35
+ export async function handleAiTool(name, args) {
36
+ switch (name) {
37
+ case "generate_subject_lines": {
38
+ const data = await apiFetch("/ai/subject-lines", { method: "POST", body: JSON.stringify(args) });
39
+ return JSON.stringify(data, null, 2);
40
+ }
41
+ default:
42
+ throw new Error(`Unknown AI tool: ${name}`);
43
+ }
44
+ }
45
+ //# sourceMappingURL=ai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.js","sourceRoot":"","sources":["../../src/tools/ai.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,MAAM,CAAC,MAAM,OAAO,GAAW;IAC7B;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EACT,6KAA6K;QAC/K,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,CAAC,OAAO,CAAC;YACnB,UAAU,EAAE;gBACV,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,gEAAgE;iBAC9E;gBACD,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,CAAC;oBACpE,WAAW,EAAE,oDAAoD;iBAClE;gBACD,QAAQ,EAAE;oBACR,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,oEAAoE;iBAClF;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wDAAwD;iBACtE;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,+CAA+C;iBAC7D;aACF;SACF;KACF;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAY,EACZ,IAA6B;IAE7B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,wBAAwB,CAAC,CAAC,CAAC;YAC9B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjG,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ export declare const analyticsTools: Tool[];
3
+ export declare function handleAnalyticsTool(name: string, args: Record<string, unknown>): Promise<string>;
4
+ //# sourceMappingURL=analytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/tools/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAG/D,eAAO,MAAM,cAAc,EAAE,IAAI,EA4BhC,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAejB"}
@@ -0,0 +1,46 @@
1
+ import { apiFetch, buildQuery } from "../lib/api-client.js";
2
+ export const analyticsTools = [
3
+ {
4
+ name: "get_analytics",
5
+ description: "Get email analytics. Without campaign_id returns aggregate usage. With campaign_id returns stats for that campaign including open/click/bounce rates.",
6
+ inputSchema: {
7
+ type: "object",
8
+ properties: {
9
+ campaign_id: {
10
+ type: "string",
11
+ description: "Campaign UUID to get per-campaign stats",
12
+ },
13
+ startDate: {
14
+ type: "string",
15
+ description: "Start date in YYYY-MM-DD format (default: 30 days ago)",
16
+ },
17
+ endDate: {
18
+ type: "string",
19
+ description: "End date in YYYY-MM-DD format (default: today)",
20
+ },
21
+ groupBy: {
22
+ type: "string",
23
+ enum: ["day", "week", "month"],
24
+ description: "Time grouping (default: day)",
25
+ },
26
+ },
27
+ },
28
+ },
29
+ ];
30
+ export async function handleAnalyticsTool(name, args) {
31
+ switch (name) {
32
+ case "get_analytics": {
33
+ const qs = buildQuery({
34
+ campaignId: args.campaign_id,
35
+ startDate: args.startDate,
36
+ endDate: args.endDate,
37
+ groupBy: args.groupBy,
38
+ });
39
+ const data = await apiFetch(`/analytics${qs}`);
40
+ return JSON.stringify(data, null, 2);
41
+ }
42
+ default:
43
+ throw new Error(`Unknown analytics tool: ${name}`);
44
+ }
45
+ }
46
+ //# sourceMappingURL=analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../src/tools/analytics.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,CAAC,MAAM,cAAc,GAAW;IACpC;QACE,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,uJAAuJ;QACzJ,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,yCAAyC;iBACvD;gBACD,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wDAAwD;iBACtE;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,gDAAgD;iBAC9D;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC;oBAC9B,WAAW,EAAE,8BAA8B;iBAC5C;aACF;SACF;KACF;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAY,EACZ,IAA6B;IAE7B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,UAAU,EAAE,IAAI,CAAC,WAAW;gBAC5B,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;YAC/C,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
+ export declare const automationTools: Tool[];
3
+ export declare function handleAutomationTool(name: string, args: Record<string, unknown>): Promise<string>;
4
+ //# sourceMappingURL=automations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automations.d.ts","sourceRoot":"","sources":["../../src/tools/automations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAG/D,eAAO,MAAM,eAAe,EAAE,IAAI,EAwCjC,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBvG"}