postmark-mcp 1.0.1 → 1.0.2
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/index.js +24 -29
- package/package.json +1 -1
package/index.js
CHANGED
@@ -50,10 +50,10 @@ async function initializeServices() {
|
|
50
50
|
|
51
51
|
// Initialize Postmark client
|
52
52
|
const client = new postmark.ServerClient(serverToken);
|
53
|
-
|
53
|
+
|
54
54
|
// Verify Postmark client by making a test API call
|
55
55
|
await client.getServer();
|
56
|
-
|
56
|
+
|
57
57
|
// Create MCP server
|
58
58
|
const mcpServer = new McpServer({
|
59
59
|
name: "postmark-mcp",
|
@@ -73,16 +73,16 @@ async function initializeServices() {
|
|
73
73
|
async function main() {
|
74
74
|
try {
|
75
75
|
const { postmarkClient, mcpServer: server } = await initializeServices();
|
76
|
-
|
76
|
+
|
77
77
|
// Register tools with validated client
|
78
78
|
registerTools(server, postmarkClient);
|
79
|
-
|
79
|
+
|
80
80
|
console.error('Connecting to MCP transport...');
|
81
81
|
const transport = new StdioServerTransport();
|
82
82
|
await server.connect(transport);
|
83
|
-
|
83
|
+
|
84
84
|
console.error('Postmark MCP server is running and ready!');
|
85
|
-
|
85
|
+
|
86
86
|
// Setup graceful shutdown
|
87
87
|
process.on('SIGTERM', () => handleShutdown(server));
|
88
88
|
process.on('SIGINT', () => handleShutdown(server));
|
@@ -122,12 +122,7 @@ function registerTools(server, postmarkClient) {
|
|
122
122
|
server.tool(
|
123
123
|
"sendEmail",
|
124
124
|
{
|
125
|
-
to: z.string().
|
126
|
-
subject: z.string().optional().describe("Email subject"),
|
127
|
-
textBody: z.string().optional().describe("Plain text body of the email"),
|
128
|
-
htmlBody: z.string().optional().describe("HTML body of the email (optional)"),
|
129
|
-
from: z.string().optional().describe("Sender email address (optional)"),
|
130
|
-
tag: z.string().optional().describe("Optional tag for categorization")
|
125
|
+
to: z.string().email().describe("Recipient email address"),
|
131
126
|
},
|
132
127
|
async ({ to, subject, textBody, htmlBody, from, tag }) => {
|
133
128
|
const emailData = {
|
@@ -146,7 +141,7 @@ function registerTools(server, postmarkClient) {
|
|
146
141
|
console.error('Sending email...', { to, subject });
|
147
142
|
const result = await postmarkClient.sendEmail(emailData);
|
148
143
|
console.error('Email sent successfully:', result.MessageID);
|
149
|
-
|
144
|
+
|
150
145
|
return {
|
151
146
|
content: [{
|
152
147
|
type: "text",
|
@@ -192,10 +187,10 @@ function registerTools(server, postmarkClient) {
|
|
192
187
|
console.error('Sending template email...', { to, templateId: templateId || templateAlias });
|
193
188
|
const result = await postmarkClient.sendEmailWithTemplate(emailData);
|
194
189
|
console.error('Template email sent successfully:', result.MessageID);
|
195
|
-
|
190
|
+
|
196
191
|
return {
|
197
192
|
content: [{
|
198
|
-
type: "text",
|
193
|
+
type: "text",
|
199
194
|
text: `Template email sent successfully!\nMessageID: ${result.MessageID}\nTo: ${to}\nTemplate: ${templateId || templateAlias}`
|
200
195
|
}]
|
201
196
|
};
|
@@ -210,11 +205,11 @@ function registerTools(server, postmarkClient) {
|
|
210
205
|
console.error('Fetching templates...');
|
211
206
|
const result = await postmarkClient.getTemplates();
|
212
207
|
console.error(`Found ${result.Templates.length} templates`);
|
213
|
-
|
214
|
-
const templateList = result.Templates.map(t =>
|
208
|
+
|
209
|
+
const templateList = result.Templates.map(t =>
|
215
210
|
`• **${t.Name}**\n - ID: ${t.TemplateId}\n - Alias: ${t.Alias || 'none'}\n - Subject: ${t.Subject || 'none'}`
|
216
211
|
).join('\n\n');
|
217
|
-
|
212
|
+
|
218
213
|
return {
|
219
214
|
content: [{
|
220
215
|
type: "text",
|
@@ -237,11 +232,11 @@ function registerTools(server, postmarkClient) {
|
|
237
232
|
if (fromDate) query.push(`fromdate=${encodeURIComponent(fromDate)}`);
|
238
233
|
if (toDate) query.push(`todate=${encodeURIComponent(toDate)}`);
|
239
234
|
if (tag) query.push(`tag=${encodeURIComponent(tag)}`);
|
240
|
-
|
235
|
+
|
241
236
|
const url = `https://api.postmarkapp.com/stats/outbound${query.length ? '?' + query.join('&') : ''}`;
|
242
|
-
|
237
|
+
|
243
238
|
console.error('Fetching delivery stats...');
|
244
|
-
|
239
|
+
|
245
240
|
const response = await fetch(url, {
|
246
241
|
headers: {
|
247
242
|
"Accept": "application/json",
|
@@ -255,25 +250,25 @@ function registerTools(server, postmarkClient) {
|
|
255
250
|
|
256
251
|
const data = await response.json();
|
257
252
|
console.error('Stats retrieved successfully');
|
258
|
-
|
253
|
+
|
259
254
|
const sent = data.Sent || 0;
|
260
255
|
const tracked = data.Tracked || 0;
|
261
256
|
const uniqueOpens = data.UniqueOpens || 0;
|
262
257
|
const totalTrackedLinks = data.TotalTrackedLinksSent || 0;
|
263
258
|
const uniqueLinksClicked = data.UniqueLinksClicked || 0;
|
264
|
-
|
259
|
+
|
265
260
|
const openRate = tracked > 0 ? ((uniqueOpens / tracked) * 100).toFixed(1) : '0.0';
|
266
261
|
const clickRate = totalTrackedLinks > 0 ? ((uniqueLinksClicked / totalTrackedLinks) * 100).toFixed(1) : '0.0';
|
267
|
-
|
262
|
+
|
268
263
|
return {
|
269
264
|
content: [{
|
270
265
|
type: "text",
|
271
266
|
text: `Email Statistics Summary\n\n` +
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
267
|
+
`Sent: ${sent} emails\n` +
|
268
|
+
`Open Rate: ${openRate}% (${uniqueOpens}/${tracked} tracked emails)\n` +
|
269
|
+
`Click Rate: ${clickRate}% (${uniqueLinksClicked}/${totalTrackedLinks} tracked links)\n\n` +
|
270
|
+
`${fromDate || toDate ? `Period: ${fromDate || 'start'} to ${toDate || 'now'}\n` : ''}` +
|
271
|
+
`${tag ? `Tag: ${tag}\n` : ''}`
|
277
272
|
}]
|
278
273
|
};
|
279
274
|
}
|