alienmail-mcp 1.0.0
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.
- package/README.md +90 -0
- package/mcp-server.mjs +719 -0
- package/package.json +24 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# alienmail-mcp
|
|
2
|
+
|
|
3
|
+
Model Context Protocol (MCP) server for **AlienMail**. This package allows AI assistants (like Cursor, Claude, or Gemini) to securely interact with the AlienMail API to manage workspaces, marketing campaigns, leads, templates, and SMTP mailboxes directly from your AI workflows.
|
|
4
|
+
|
|
5
|
+
## 🚀 Usage
|
|
6
|
+
|
|
7
|
+
You do not need to clone this repository to use the MCP server. You can run it directly using `npx` in your favorite MCP-compatible AI assistant.
|
|
8
|
+
|
|
9
|
+
### MCP Configuration
|
|
10
|
+
|
|
11
|
+
Add the following configuration to your MCP client (e.g., Cursor or Claude Desktop):
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"alienmail-mcp": {
|
|
17
|
+
"command": "npx",
|
|
18
|
+
"args": [
|
|
19
|
+
"-y",
|
|
20
|
+
"alienmail-mcp"
|
|
21
|
+
],
|
|
22
|
+
"env": {
|
|
23
|
+
"MCP_API_TOKEN": "your-alienmail-api-token"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## ⚙️ Environment Variables
|
|
31
|
+
|
|
32
|
+
The server requires the following environment variables to authenticate with the AlienMail backend:
|
|
33
|
+
|
|
34
|
+
- `MCP_API_TOKEN` (or `API_TOKEN`): **Required.** Your authentication JWT token to access the AlienMail API securely.
|
|
35
|
+
- `NEXT_PUBLIC_APP_URL`: *Optional.* The base URL of the AlienMail API. Defaults to `https://app.alienmail.io` if not provided.
|
|
36
|
+
|
|
37
|
+
## 🛠️ Available Tools
|
|
38
|
+
|
|
39
|
+
Once connected, your AI assistant will have access to the following tools to manage your AlienMail platform:
|
|
40
|
+
|
|
41
|
+
### 🏢 Workspaces
|
|
42
|
+
- `list_workspaces`: List all your accessible workspaces.
|
|
43
|
+
- `create_workspace`: Create a new workspace.
|
|
44
|
+
|
|
45
|
+
### 📢 Campaigns
|
|
46
|
+
- `list_campaigns`: List campaigns for a workspace.
|
|
47
|
+
- `create_campaign`, `get_campaign`, `update_campaign`, `delete_campaign`
|
|
48
|
+
- `duplicate_campaign`, `start_campaign`, `toggle_campaign_status`, `update_campaign_settings`
|
|
49
|
+
|
|
50
|
+
### 📧 Templates & Flow
|
|
51
|
+
- `list_templates`, `create_template`: Manage email templates for a campaign.
|
|
52
|
+
- `get_campaign_flow`, `save_campaign_flow`: Manage the nodes and edges for visual campaign flows.
|
|
53
|
+
- `get_campaign_conditions`, `create_campaign_condition`: Manage campaign trigger conditions (e.g., Opened an email).
|
|
54
|
+
|
|
55
|
+
### 👥 Leads
|
|
56
|
+
- `list_leads`: List leads with pagination and search.
|
|
57
|
+
- `create_lead`, `import_leads_csv`, `get_lead`
|
|
58
|
+
- `bulk_update_lead_status`, `bulk_enroll_leads`
|
|
59
|
+
- `enroll_leads_in_campaign`: Enroll leads into a specific campaign.
|
|
60
|
+
- `get_lead_email_timeline`: Get email interaction timeline for a specific lead.
|
|
61
|
+
|
|
62
|
+
### 📮 SMTP / Mailboxes
|
|
63
|
+
- `list_smtp_accounts`: View configured SMTP accounts.
|
|
64
|
+
- `add_smtp_account`, `update_smtp_account`, `delete_smtp_account`
|
|
65
|
+
- `test_smtp_connection`: Test your SMTP credentials.
|
|
66
|
+
|
|
67
|
+
### 📊 Analytics
|
|
68
|
+
- `get_workspace_analytics`: Get aggregated analytics for a workspace within a date range.
|
|
69
|
+
|
|
70
|
+
## 👨💻 Local Development
|
|
71
|
+
|
|
72
|
+
If you are developing or testing this package locally:
|
|
73
|
+
|
|
74
|
+
1. Clone the repository and navigate into the directory.
|
|
75
|
+
2. Install dependencies:
|
|
76
|
+
```bash
|
|
77
|
+
npm install
|
|
78
|
+
```
|
|
79
|
+
3. Symlink the package globally to test `npx alienmail-mcp`:
|
|
80
|
+
```bash
|
|
81
|
+
npm link
|
|
82
|
+
```
|
|
83
|
+
4. Run locally:
|
|
84
|
+
```bash
|
|
85
|
+
npm start
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 📝 License
|
|
89
|
+
|
|
90
|
+
ISC
|
package/mcp-server.mjs
ADDED
|
@@ -0,0 +1,719 @@
|
|
|
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 {
|
|
5
|
+
CallToolRequestSchema,
|
|
6
|
+
ListToolsRequestSchema,
|
|
7
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
8
|
+
import "dotenv/config";
|
|
9
|
+
|
|
10
|
+
// --- API State ---
|
|
11
|
+
const API_BASE_URL = process.env.NEXT_PUBLIC_APP_URL || "https://app.alienmail.io";
|
|
12
|
+
const API_TOKEN = process.env.MCP_API_TOKEN || process.env.API_TOKEN;
|
|
13
|
+
|
|
14
|
+
const server = new Server(
|
|
15
|
+
{
|
|
16
|
+
name: "project-access-mcp",
|
|
17
|
+
version: "1.0.0",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
capabilities: {
|
|
21
|
+
tools: {},
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
async function makeApiCall(method, endpoint, body = null) {
|
|
27
|
+
const url = `${API_BASE_URL}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;
|
|
28
|
+
const headers = { "Content-Type": "application/json" };
|
|
29
|
+
|
|
30
|
+
if (API_TOKEN) {
|
|
31
|
+
headers.Authorization = `Bearer ${API_TOKEN}`;
|
|
32
|
+
headers.Cookie = `authToken=${API_TOKEN}`;
|
|
33
|
+
} else {
|
|
34
|
+
throw new Error("No API token configured. Please set MCP_API_TOKEN or API_TOKEN in your .env file or environment.");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const fetchOptions = {
|
|
38
|
+
method: method.toUpperCase(),
|
|
39
|
+
headers,
|
|
40
|
+
};
|
|
41
|
+
if (body && ["POST", "PUT", "PATCH"].includes(fetchOptions.method)) {
|
|
42
|
+
fetchOptions.body = JSON.stringify(body);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const response = await fetch(url, fetchOptions);
|
|
46
|
+
let responseBody;
|
|
47
|
+
const contentType = response.headers.get("content-type");
|
|
48
|
+
if (contentType && contentType.includes("application/json")) {
|
|
49
|
+
responseBody = await response.json();
|
|
50
|
+
} else {
|
|
51
|
+
responseBody = await response.text();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
content: [
|
|
56
|
+
{ type: "text", text: `Status: ${response.status} ${response.statusText}\n\nResponse:\n${typeof responseBody === "string" ? responseBody : JSON.stringify(responseBody, null, 2)}` }
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Define tools
|
|
62
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
63
|
+
return {
|
|
64
|
+
tools: [
|
|
65
|
+
// WORKSPACES
|
|
66
|
+
{
|
|
67
|
+
name: "list_workspaces",
|
|
68
|
+
description: "List all workspaces.",
|
|
69
|
+
inputSchema: { type: "object", properties: {} },
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "create_workspace",
|
|
73
|
+
description: "Create a new workspace.",
|
|
74
|
+
inputSchema: {
|
|
75
|
+
type: "object",
|
|
76
|
+
properties: { name: { type: "string" } },
|
|
77
|
+
required: ["name"],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
// CAMPAIGNS
|
|
81
|
+
{
|
|
82
|
+
name: "list_campaigns",
|
|
83
|
+
description: "List campaigns for a workspace.",
|
|
84
|
+
inputSchema: {
|
|
85
|
+
type: "object",
|
|
86
|
+
properties: {
|
|
87
|
+
workspaceUID: { type: "string" },
|
|
88
|
+
workspaceId: { type: "number" },
|
|
89
|
+
search: { type: "string" },
|
|
90
|
+
status: { type: "string" },
|
|
91
|
+
},
|
|
92
|
+
required: ["workspaceUID"],
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "create_campaign",
|
|
97
|
+
description: "Create a new campaign.",
|
|
98
|
+
inputSchema: {
|
|
99
|
+
type: "object",
|
|
100
|
+
properties: {
|
|
101
|
+
workspaceUID: { type: "string" },
|
|
102
|
+
workspaceId: { type: "number" },
|
|
103
|
+
name: { type: "string" },
|
|
104
|
+
},
|
|
105
|
+
required: ["workspaceUID", "workspaceId", "name"],
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "get_campaign",
|
|
110
|
+
description: "Get a campaign by ID.",
|
|
111
|
+
inputSchema: {
|
|
112
|
+
type: "object",
|
|
113
|
+
properties: {
|
|
114
|
+
workspaceUID: { type: "string" },
|
|
115
|
+
campaignId: { type: "number" },
|
|
116
|
+
},
|
|
117
|
+
required: ["workspaceUID", "campaignId"],
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: "update_campaign",
|
|
122
|
+
description: "Update a campaign name.",
|
|
123
|
+
inputSchema: {
|
|
124
|
+
type: "object",
|
|
125
|
+
properties: {
|
|
126
|
+
workspaceUID: { type: "string" },
|
|
127
|
+
campaignId: { type: "number" },
|
|
128
|
+
name: { type: "string" },
|
|
129
|
+
},
|
|
130
|
+
required: ["workspaceUID", "campaignId", "name"],
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "delete_campaign",
|
|
135
|
+
description: "Soft delete a campaign.",
|
|
136
|
+
inputSchema: {
|
|
137
|
+
type: "object",
|
|
138
|
+
properties: {
|
|
139
|
+
workspaceUID: { type: "string" },
|
|
140
|
+
campaignId: { type: "number" },
|
|
141
|
+
},
|
|
142
|
+
required: ["workspaceUID", "campaignId"],
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: "duplicate_campaign",
|
|
147
|
+
description: "Duplicate a campaign.",
|
|
148
|
+
inputSchema: {
|
|
149
|
+
type: "object",
|
|
150
|
+
properties: {
|
|
151
|
+
workspaceUID: { type: "string" },
|
|
152
|
+
campaignId: { type: "number" },
|
|
153
|
+
},
|
|
154
|
+
required: ["workspaceUID", "campaignId"],
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: "start_campaign",
|
|
159
|
+
description: "Start a campaign.",
|
|
160
|
+
inputSchema: {
|
|
161
|
+
type: "object",
|
|
162
|
+
properties: {
|
|
163
|
+
workspaceUID: { type: "string" },
|
|
164
|
+
campaignId: { type: "number" },
|
|
165
|
+
},
|
|
166
|
+
required: ["workspaceUID", "campaignId"],
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
name: "toggle_campaign_status",
|
|
171
|
+
description: "Toggle a campaign's status.",
|
|
172
|
+
inputSchema: {
|
|
173
|
+
type: "object",
|
|
174
|
+
properties: {
|
|
175
|
+
workspaceUID: { type: "string" },
|
|
176
|
+
campaignId: { type: "number" },
|
|
177
|
+
status: { type: "string", description: "DRAFT, ACTIVE, PAUSED, COMPLETED" },
|
|
178
|
+
},
|
|
179
|
+
required: ["workspaceUID", "campaignId", "status"],
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: "update_campaign_settings",
|
|
184
|
+
description: "Update campaign settings.",
|
|
185
|
+
inputSchema: {
|
|
186
|
+
type: "object",
|
|
187
|
+
properties: {
|
|
188
|
+
workspaceUID: { type: "string" },
|
|
189
|
+
campaignId: { type: "number" },
|
|
190
|
+
emailsPerDay: { type: "number" },
|
|
191
|
+
gapBwEmail: { type: "number" },
|
|
192
|
+
startScheduleAt: { type: "string" },
|
|
193
|
+
endScheduleAt: { type: "string" },
|
|
194
|
+
},
|
|
195
|
+
required: ["workspaceUID", "campaignId", "emailsPerDay", "gapBwEmail"],
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
// CAMPAIGN TEMPLATES
|
|
199
|
+
{
|
|
200
|
+
name: "list_templates",
|
|
201
|
+
description: "List templates for a campaign.",
|
|
202
|
+
inputSchema: {
|
|
203
|
+
type: "object",
|
|
204
|
+
properties: {
|
|
205
|
+
workspaceUID: { type: "string" },
|
|
206
|
+
campaignId: { type: "number" },
|
|
207
|
+
},
|
|
208
|
+
required: ["workspaceUID", "campaignId"],
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
name: "create_template",
|
|
213
|
+
description: "Create a template for a campaign.",
|
|
214
|
+
inputSchema: {
|
|
215
|
+
type: "object",
|
|
216
|
+
properties: {
|
|
217
|
+
workspaceUID: { type: "string" },
|
|
218
|
+
campaignId: { type: "number" },
|
|
219
|
+
name: { type: "string" },
|
|
220
|
+
subject: { type: "string" },
|
|
221
|
+
html: { type: "string" },
|
|
222
|
+
enabled: { type: "boolean" },
|
|
223
|
+
stepIndex: { type: "number" },
|
|
224
|
+
},
|
|
225
|
+
required: ["workspaceUID", "campaignId", "name", "subject", "html"],
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
// CAMPAIGN FLOW
|
|
229
|
+
{
|
|
230
|
+
name: "get_campaign_flow",
|
|
231
|
+
description: "Get the flow (nodes and edges) of a campaign.",
|
|
232
|
+
inputSchema: {
|
|
233
|
+
type: "object",
|
|
234
|
+
properties: {
|
|
235
|
+
workspaceUID: { type: "string" },
|
|
236
|
+
campaignId: { type: "number" },
|
|
237
|
+
},
|
|
238
|
+
required: ["workspaceUID", "campaignId"],
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
name: "save_campaign_flow",
|
|
243
|
+
description: "Save the flow (nodes and edges) for a campaign.",
|
|
244
|
+
inputSchema: {
|
|
245
|
+
type: "object",
|
|
246
|
+
properties: {
|
|
247
|
+
workspaceUID: { type: "string" },
|
|
248
|
+
campaignId: { type: "number" },
|
|
249
|
+
nodes: { type: "array" },
|
|
250
|
+
edges: { type: "array" },
|
|
251
|
+
},
|
|
252
|
+
required: ["workspaceUID", "campaignId", "nodes", "edges"],
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
// CAMPAIGN CONDITIONS
|
|
256
|
+
{
|
|
257
|
+
name: "get_campaign_conditions",
|
|
258
|
+
description: "Get conditions for a campaign.",
|
|
259
|
+
inputSchema: {
|
|
260
|
+
type: "object",
|
|
261
|
+
properties: {
|
|
262
|
+
workspaceUID: { type: "string" },
|
|
263
|
+
campaignId: { type: "number" },
|
|
264
|
+
},
|
|
265
|
+
required: ["workspaceUID", "campaignId"],
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
name: "create_campaign_condition",
|
|
270
|
+
description: "Create a condition for a campaign.",
|
|
271
|
+
inputSchema: {
|
|
272
|
+
type: "object",
|
|
273
|
+
properties: {
|
|
274
|
+
workspaceUID: { type: "string" },
|
|
275
|
+
campaignId: { type: "number" },
|
|
276
|
+
name: { type: "string" },
|
|
277
|
+
condition: { type: "string", description: "Opened an email, Clicked on link, Has replied, All Leads" },
|
|
278
|
+
templateId: { type: "number" },
|
|
279
|
+
enabled: { type: "boolean" },
|
|
280
|
+
},
|
|
281
|
+
required: ["workspaceUID", "campaignId", "name", "condition", "templateId"],
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
// LEADS
|
|
285
|
+
{
|
|
286
|
+
name: "list_leads",
|
|
287
|
+
description: "List leads with pagination and optional search.",
|
|
288
|
+
inputSchema: {
|
|
289
|
+
type: "object",
|
|
290
|
+
properties: {
|
|
291
|
+
workspaceUID: { type: "string" },
|
|
292
|
+
page: { type: "number" },
|
|
293
|
+
pageSize: { type: "number" },
|
|
294
|
+
search: { type: "string" },
|
|
295
|
+
},
|
|
296
|
+
required: ["workspaceUID"],
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: "create_lead",
|
|
301
|
+
description: "Create a single lead.",
|
|
302
|
+
inputSchema: {
|
|
303
|
+
type: "object",
|
|
304
|
+
properties: {
|
|
305
|
+
workspaceUID: { type: "string" },
|
|
306
|
+
workspaceId: { type: "number" },
|
|
307
|
+
email: { type: "string" },
|
|
308
|
+
firstName: { type: "string" },
|
|
309
|
+
lastName: { type: "string" },
|
|
310
|
+
company: { type: "string" },
|
|
311
|
+
source: { type: "string" },
|
|
312
|
+
},
|
|
313
|
+
required: ["workspaceUID", "workspaceId", "email", "firstName"],
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
name: "import_leads_csv",
|
|
318
|
+
description: "Import leads via CSV.",
|
|
319
|
+
inputSchema: {
|
|
320
|
+
type: "object",
|
|
321
|
+
properties: {
|
|
322
|
+
workspaceUID: { type: "string" },
|
|
323
|
+
workspaceId: { type: "number" },
|
|
324
|
+
csv: { type: "string" },
|
|
325
|
+
},
|
|
326
|
+
required: ["workspaceUID", "workspaceId", "csv"],
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
name: "get_lead",
|
|
331
|
+
description: "Get a lead by ID with campaign analytics.",
|
|
332
|
+
inputSchema: {
|
|
333
|
+
type: "object",
|
|
334
|
+
properties: {
|
|
335
|
+
workspaceUID: { type: "string" },
|
|
336
|
+
leadId: { type: "number" },
|
|
337
|
+
},
|
|
338
|
+
required: ["workspaceUID", "leadId"],
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
name: "bulk_update_lead_status",
|
|
343
|
+
description: "Bulk update lead statuses.",
|
|
344
|
+
inputSchema: {
|
|
345
|
+
type: "object",
|
|
346
|
+
properties: {
|
|
347
|
+
workspaceUID: { type: "string" },
|
|
348
|
+
workspaceId: { type: "number" },
|
|
349
|
+
status: { type: "string" },
|
|
350
|
+
mode: { type: "string" },
|
|
351
|
+
selectedIds: { type: "array" },
|
|
352
|
+
excludedIds: { type: "array" },
|
|
353
|
+
search: { type: "string" },
|
|
354
|
+
},
|
|
355
|
+
required: ["workspaceUID", "workspaceId", "status", "mode"],
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
name: "bulk_enroll_leads",
|
|
360
|
+
description: "Bulk enroll leads into a campaign.",
|
|
361
|
+
inputSchema: {
|
|
362
|
+
type: "object",
|
|
363
|
+
properties: {
|
|
364
|
+
workspaceUID: { type: "string" },
|
|
365
|
+
workspaceId: { type: "number" },
|
|
366
|
+
campaignId: { type: "number" },
|
|
367
|
+
leads: { type: "array" },
|
|
368
|
+
},
|
|
369
|
+
required: ["workspaceUID", "workspaceId", "campaignId", "leads"],
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
// ENROLL LEADS INTO CAMPAIGN
|
|
373
|
+
{
|
|
374
|
+
name: "enroll_leads_in_campaign",
|
|
375
|
+
description: "Enroll leads into a specific campaign (by IDs or query).",
|
|
376
|
+
inputSchema: {
|
|
377
|
+
type: "object",
|
|
378
|
+
properties: {
|
|
379
|
+
workspaceUID: { type: "string" },
|
|
380
|
+
campaignId: { type: "number" },
|
|
381
|
+
workspaceId: { type: "number" },
|
|
382
|
+
mode: { type: "string" },
|
|
383
|
+
leadIds: { type: "array" },
|
|
384
|
+
search: { type: "string" },
|
|
385
|
+
excludedIds: { type: "array" },
|
|
386
|
+
},
|
|
387
|
+
required: ["workspaceUID", "campaignId", "workspaceId", "mode"],
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
name: "get_lead_email_timeline",
|
|
392
|
+
description: "Get email timeline for a lead in a campaign.",
|
|
393
|
+
inputSchema: {
|
|
394
|
+
type: "object",
|
|
395
|
+
properties: {
|
|
396
|
+
workspaceUID: { type: "string" },
|
|
397
|
+
campaignId: { type: "number" },
|
|
398
|
+
leadId: { type: "number" },
|
|
399
|
+
},
|
|
400
|
+
required: ["workspaceUID", "campaignId", "leadId"],
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
// SMTP / MAILBOX
|
|
404
|
+
{
|
|
405
|
+
name: "list_smtp_accounts",
|
|
406
|
+
description: "List SMTP accounts for a workspace.",
|
|
407
|
+
inputSchema: {
|
|
408
|
+
type: "object",
|
|
409
|
+
properties: {
|
|
410
|
+
workspaceUID: { type: "string" },
|
|
411
|
+
workspaceId: { type: "number" },
|
|
412
|
+
},
|
|
413
|
+
required: ["workspaceUID"],
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
name: "add_smtp_account",
|
|
418
|
+
description: "Add an SMTP account.",
|
|
419
|
+
inputSchema: {
|
|
420
|
+
type: "object",
|
|
421
|
+
properties: {
|
|
422
|
+
workspaceUID: { type: "string" },
|
|
423
|
+
workspaceId: { type: "number" },
|
|
424
|
+
host: { type: "string" },
|
|
425
|
+
port: { type: "number" },
|
|
426
|
+
username: { type: "string" },
|
|
427
|
+
password: { type: "string" },
|
|
428
|
+
fromEmail: { type: "string" },
|
|
429
|
+
fromName: { type: "string" },
|
|
430
|
+
},
|
|
431
|
+
required: ["workspaceUID", "workspaceId", "host", "port", "username", "password", "fromEmail", "fromName"],
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
name: "update_smtp_account",
|
|
436
|
+
description: "Update an SMTP account.",
|
|
437
|
+
inputSchema: {
|
|
438
|
+
type: "object",
|
|
439
|
+
properties: {
|
|
440
|
+
workspaceUID: { type: "string" },
|
|
441
|
+
id: { type: "number" },
|
|
442
|
+
host: { type: "string" },
|
|
443
|
+
port: { type: "number" },
|
|
444
|
+
username: { type: "string" },
|
|
445
|
+
fromEmail: { type: "string" },
|
|
446
|
+
fromName: { type: "string" },
|
|
447
|
+
},
|
|
448
|
+
required: ["workspaceUID", "id", "host", "port", "username", "fromEmail", "fromName"],
|
|
449
|
+
},
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
name: "delete_smtp_account",
|
|
453
|
+
description: "Delete an SMTP account.",
|
|
454
|
+
inputSchema: {
|
|
455
|
+
type: "object",
|
|
456
|
+
properties: {
|
|
457
|
+
workspaceUID: { type: "string" },
|
|
458
|
+
id: { type: "number" },
|
|
459
|
+
},
|
|
460
|
+
required: ["workspaceUID", "id"],
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
name: "test_smtp_connection",
|
|
465
|
+
description: "Test an SMTP connection.",
|
|
466
|
+
inputSchema: {
|
|
467
|
+
type: "object",
|
|
468
|
+
properties: {
|
|
469
|
+
workspaceUID: { type: "string" },
|
|
470
|
+
id: { type: "number" },
|
|
471
|
+
},
|
|
472
|
+
required: ["workspaceUID", "id"],
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
// ANALYTICS
|
|
476
|
+
{
|
|
477
|
+
name: "get_workspace_analytics",
|
|
478
|
+
description: "Get workspace analytics.",
|
|
479
|
+
inputSchema: {
|
|
480
|
+
type: "object",
|
|
481
|
+
properties: {
|
|
482
|
+
workspaceUID: { type: "string" },
|
|
483
|
+
from: { type: "string" },
|
|
484
|
+
to: { type: "string" },
|
|
485
|
+
status: { type: "string" },
|
|
486
|
+
},
|
|
487
|
+
required: ["workspaceUID", "from", "to"],
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
],
|
|
491
|
+
};
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
// Handle tool execution
|
|
495
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
496
|
+
const { name, arguments: args } = request.params;
|
|
497
|
+
|
|
498
|
+
try {
|
|
499
|
+
// WORKSPACES
|
|
500
|
+
if (name === "list_workspaces") {
|
|
501
|
+
return await makeApiCall("GET", "/api/workspaces");
|
|
502
|
+
}
|
|
503
|
+
if (name === "create_workspace") {
|
|
504
|
+
return await makeApiCall("POST", "/api/workspaces", { name: args.name });
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// CAMPAIGNS
|
|
508
|
+
if (name === "list_campaigns") {
|
|
509
|
+
const params = new URLSearchParams();
|
|
510
|
+
if (args.workspaceId) params.append("workspaceId", args.workspaceId.toString());
|
|
511
|
+
if (args.search) params.append("search", args.search);
|
|
512
|
+
if (args.status) params.append("status", args.status);
|
|
513
|
+
const queryStr = params.toString() ? `?${params.toString()}` : "";
|
|
514
|
+
return await makeApiCall("GET", `/api/${args.workspaceUID}/campaigns${queryStr}`);
|
|
515
|
+
}
|
|
516
|
+
if (name === "create_campaign") {
|
|
517
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/campaigns`, {
|
|
518
|
+
name: args.name,
|
|
519
|
+
workspaceId: args.workspaceId,
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
if (name === "get_campaign") {
|
|
523
|
+
return await makeApiCall("GET", `/api/${args.workspaceUID}/campaigns/${args.campaignId}`);
|
|
524
|
+
}
|
|
525
|
+
if (name === "update_campaign") {
|
|
526
|
+
return await makeApiCall("PATCH", `/api/${args.workspaceUID}/campaigns/${args.campaignId}`, {
|
|
527
|
+
name: args.name,
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
if (name === "delete_campaign") {
|
|
531
|
+
return await makeApiCall("PATCH", `/api/${args.workspaceUID}/campaigns/${args.campaignId}/delete`);
|
|
532
|
+
}
|
|
533
|
+
if (name === "duplicate_campaign") {
|
|
534
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/campaigns/${args.campaignId}/duplicate`);
|
|
535
|
+
}
|
|
536
|
+
if (name === "start_campaign") {
|
|
537
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/campaigns/${args.campaignId}/start`);
|
|
538
|
+
}
|
|
539
|
+
if (name === "toggle_campaign_status") {
|
|
540
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/campaigns/toggle`, {
|
|
541
|
+
id: args.campaignId,
|
|
542
|
+
status: args.status,
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
if (name === "update_campaign_settings") {
|
|
546
|
+
return await makeApiCall("PUT", `/api/${args.workspaceUID}/campaigns/${args.campaignId}/settings`, {
|
|
547
|
+
emailsPerDay: args.emailsPerDay,
|
|
548
|
+
gapBwEmail: args.gapBwEmail,
|
|
549
|
+
startScheduleAt: args.startScheduleAt,
|
|
550
|
+
endScheduleAt: args.endScheduleAt,
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// CAMPAIGN TEMPLATES
|
|
555
|
+
if (name === "list_templates") {
|
|
556
|
+
return await makeApiCall("GET", `/api/${args.workspaceUID}/campaigns/${args.campaignId}/templates`);
|
|
557
|
+
}
|
|
558
|
+
if (name === "create_template") {
|
|
559
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/campaigns/${args.campaignId}/templates`, {
|
|
560
|
+
name: args.name,
|
|
561
|
+
subject: args.subject,
|
|
562
|
+
html: args.html,
|
|
563
|
+
enabled: args.enabled !== undefined ? args.enabled : true,
|
|
564
|
+
stepIndex: args.stepIndex || 0,
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// CAMPAIGN FLOW
|
|
569
|
+
if (name === "get_campaign_flow") {
|
|
570
|
+
return await makeApiCall("GET", `/api/${args.workspaceUID}/campaigns/${args.campaignId}/steps`);
|
|
571
|
+
}
|
|
572
|
+
if (name === "save_campaign_flow") {
|
|
573
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/campaigns/${args.campaignId}/steps`, {
|
|
574
|
+
nodes: args.nodes,
|
|
575
|
+
edges: args.edges,
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// CAMPAIGN CONDITIONS
|
|
580
|
+
if (name === "get_campaign_conditions") {
|
|
581
|
+
return await makeApiCall("GET", `/api/${args.workspaceUID}/campaigns/${args.campaignId}/conditions`);
|
|
582
|
+
}
|
|
583
|
+
if (name === "create_campaign_condition") {
|
|
584
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/campaigns/${args.campaignId}/conditions`, {
|
|
585
|
+
name: args.name,
|
|
586
|
+
condition: args.condition,
|
|
587
|
+
templateId: args.templateId,
|
|
588
|
+
enabled: args.enabled !== undefined ? args.enabled : true,
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// LEADS
|
|
593
|
+
if (name === "list_leads") {
|
|
594
|
+
const params = new URLSearchParams();
|
|
595
|
+
if (args.page) params.append("page", args.page.toString());
|
|
596
|
+
if (args.pageSize) params.append("pageSize", args.pageSize.toString());
|
|
597
|
+
if (args.search) params.append("search", args.search);
|
|
598
|
+
const queryStr = params.toString() ? `?${params.toString()}` : "";
|
|
599
|
+
return await makeApiCall("GET", `/api/${args.workspaceUID}/leads${queryStr}`);
|
|
600
|
+
}
|
|
601
|
+
if (name === "create_lead") {
|
|
602
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/leads`, {
|
|
603
|
+
workspaceId: args.workspaceId,
|
|
604
|
+
email: args.email,
|
|
605
|
+
firstName: args.firstName,
|
|
606
|
+
lastName: args.lastName,
|
|
607
|
+
company: args.company,
|
|
608
|
+
source: args.source || "MANUAL",
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
if (name === "import_leads_csv") {
|
|
612
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/leads`, {
|
|
613
|
+
workspaceId: args.workspaceId,
|
|
614
|
+
csv: args.csv,
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
if (name === "get_lead") {
|
|
618
|
+
return await makeApiCall("GET", `/api/${args.workspaceUID}/leads/${args.leadId}`);
|
|
619
|
+
}
|
|
620
|
+
if (name === "bulk_update_lead_status") {
|
|
621
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/leads/bulk`, {
|
|
622
|
+
workspaceId: args.workspaceId,
|
|
623
|
+
status: args.status,
|
|
624
|
+
mode: args.mode,
|
|
625
|
+
selectedIds: args.selectedIds || [],
|
|
626
|
+
excludedIds: args.excludedIds || [],
|
|
627
|
+
search: args.search || "",
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
if (name === "bulk_enroll_leads") {
|
|
631
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/leads/bulkenroll`, {
|
|
632
|
+
workspaceId: args.workspaceId,
|
|
633
|
+
campaignId: args.campaignId,
|
|
634
|
+
leads: args.leads,
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// ENROLL LEADS INTO CAMPAIGN
|
|
639
|
+
if (name === "enroll_leads_in_campaign") {
|
|
640
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/campaigns/${args.campaignId}/enroll`, {
|
|
641
|
+
workspaceId: args.workspaceId,
|
|
642
|
+
mode: args.mode,
|
|
643
|
+
leadIds: args.leadIds,
|
|
644
|
+
search: args.search,
|
|
645
|
+
excludedIds: args.excludedIds,
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
if (name === "get_lead_email_timeline") {
|
|
649
|
+
return await makeApiCall("GET", `/api/${args.workspaceUID}/campaigns/${args.campaignId}/lead/${args.leadId}`);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// SMTP / MAILBOX
|
|
653
|
+
if (name === "list_smtp_accounts") {
|
|
654
|
+
const params = new URLSearchParams();
|
|
655
|
+
if (args.workspaceId) params.append("workspaceId", args.workspaceId.toString());
|
|
656
|
+
const queryStr = params.toString() ? `?${params.toString()}` : "";
|
|
657
|
+
return await makeApiCall("GET", `/api/${args.workspaceUID}/smtp${queryStr}`);
|
|
658
|
+
}
|
|
659
|
+
if (name === "add_smtp_account") {
|
|
660
|
+
return await makeApiCall("POST", `/api/${args.workspaceUID}/smtp`, {
|
|
661
|
+
workspaceId: args.workspaceId,
|
|
662
|
+
host: args.host,
|
|
663
|
+
port: args.port,
|
|
664
|
+
username: args.username,
|
|
665
|
+
password: args.password,
|
|
666
|
+
fromEmail: args.fromEmail,
|
|
667
|
+
fromName: args.fromName,
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
if (name === "update_smtp_account") {
|
|
671
|
+
return await makeApiCall("PUT", `/api/${args.workspaceUID}/smtp`, {
|
|
672
|
+
id: args.id,
|
|
673
|
+
host: args.host,
|
|
674
|
+
port: args.port,
|
|
675
|
+
username: args.username,
|
|
676
|
+
fromEmail: args.fromEmail,
|
|
677
|
+
fromName: args.fromName,
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
if (name === "delete_smtp_account") {
|
|
681
|
+
const params = new URLSearchParams();
|
|
682
|
+
if (args.id) params.append("id", args.id.toString());
|
|
683
|
+
const queryStr = params.toString() ? `?${params.toString()}` : "";
|
|
684
|
+
return await makeApiCall("DELETE", `/api/${args.workspaceUID}/smtp${queryStr}`);
|
|
685
|
+
}
|
|
686
|
+
if (name === "test_smtp_connection") {
|
|
687
|
+
const params = new URLSearchParams();
|
|
688
|
+
if (args.id) params.append("id", args.id.toString());
|
|
689
|
+
const queryStr = params.toString() ? `?${params.toString()}` : "";
|
|
690
|
+
return await makeApiCall("GET", `/api/${args.workspaceUID}/smtp/test${queryStr}`);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// ANALYTICS
|
|
694
|
+
if (name === "get_workspace_analytics") {
|
|
695
|
+
const params = new URLSearchParams();
|
|
696
|
+
if (args.from) params.append("from", args.from);
|
|
697
|
+
if (args.to) params.append("to", args.to);
|
|
698
|
+
if (args.status) params.append("status", args.status);
|
|
699
|
+
const queryStr = params.toString() ? `?${params.toString()}` : "";
|
|
700
|
+
return await makeApiCall("GET", `/api/${args.workspaceUID}/analytics${queryStr}`);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
704
|
+
} catch (error) {
|
|
705
|
+
return {
|
|
706
|
+
content: [{ type: "text", text: `Error: ${error.message}` }],
|
|
707
|
+
isError: true,
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
// Start server
|
|
713
|
+
async function run() {
|
|
714
|
+
const transport = new StdioServerTransport();
|
|
715
|
+
await server.connect(transport);
|
|
716
|
+
console.error("Project Access MCP Server running on stdio");
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
run().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "alienmail-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for AlienMail",
|
|
5
|
+
"main": "mcp-server.mjs",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"alienmail-mcp": "./mcp-server.mjs"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node mcp-server.mjs"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@modelcontextprotocol/sdk": "latest",
|
|
15
|
+
"dotenv": "latest"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"mcp",
|
|
19
|
+
"mcp-server",
|
|
20
|
+
"alienmail"
|
|
21
|
+
],
|
|
22
|
+
"author": "",
|
|
23
|
+
"license": "ISC"
|
|
24
|
+
}
|