groundmail-mcp 0.7.1 → 0.9.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.
Files changed (2) hide show
  1. package/dist/index.js +44 -8
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -150,6 +150,9 @@ var emailItem = object(
150
150
  heldBackItem(),
151
151
  "Recipients Groundmail validation held back before sending, with why; empty when none were"
152
152
  ),
153
+ test: boolean(
154
+ "True when the email never reached the mail server: sent with a test key (gm_test_\u2026) or only to simulator addresses. Its status and events are simulated"
155
+ ),
153
156
  tags: { description: "Tags attached to the email" },
154
157
  scheduled_at: nullableString("When the email is scheduled to send (ISO 8601)"),
155
158
  cancelled_at: nullableString("When the scheduled email was cancelled (ISO 8601)"),
@@ -267,7 +270,8 @@ var sendEmailOutput = object(
267
270
  held_back: arrayOf(
268
271
  heldBackItem(),
269
272
  "Present when Groundmail validation held some recipients back; the email went to the rest"
270
- )
273
+ ),
274
+ test: boolean("Present and true on a test send (test key or simulator addresses): nothing was delivered")
271
275
  },
272
276
  ["id", "status"]
273
277
  );
@@ -403,10 +407,14 @@ var migrationOutput = object(
403
407
  has_more: boolean("True if the import stopped early; call the tool again with `cursor` to continue"),
404
408
  next_cursor: nullableString("Pass as `cursor` to continue an import that stopped early"),
405
409
  retry_after_seconds: { type: ["number", "null"], description: "Wait this long before continuing" },
406
- domains: anyObject("Totals and one item per domain, with the DNS records to publish"),
410
+ domains: anyObject(
411
+ "Totals and one item per domain, with the DNS records and `dns_plan`: each record compared with what the domain publishes today (add, update an existing SPF record, keep the existing DMARC record, or already published), and which old-provider records to keep until the cutover"
412
+ ),
407
413
  webhooks: anyObject("Totals and one item per webhook (created disabled), with mapped events and the signing secret"),
408
414
  templates: anyObject("Totals and one item per template, with its alias and conversion notes"),
409
- suppressions: anyObject("Totals by type (bounce, complaint, unsubscribe, manual) and skip reasons"),
415
+ suppressions: anyObject(
416
+ "Totals by type (bounce, complaint, unsubscribe, manual, product_opt_out) and skip reasons (for example bounces caused by a block on the old provider, which are not suppressed)"
417
+ ),
410
418
  errors: arrayOf(anyObject("A resource that could not be read"), "Resources that could not be read at all"),
411
419
  notes: stringArray("What was left out on purpose, and why"),
412
420
  attention: stringArray("What the user still needs to do"),
@@ -496,7 +504,8 @@ async function callMcpTool(client, name, args) {
496
504
  case "list_emails": {
497
505
  const result = await client.emails.list({
498
506
  limit: optNumber(args, "limit"),
499
- cursor: optString(args, "cursor")
507
+ cursor: optString(args, "cursor"),
508
+ ...typeof args.test === "boolean" ? { test: args.test } : {}
500
509
  });
501
510
  return textResult(result);
502
511
  }
@@ -682,6 +691,15 @@ async function callMcpTool(client, name, args) {
682
691
  };
683
692
  return textResult({ migration: await client.migrations.run(params) });
684
693
  }
694
+ case "get_import_report": {
695
+ let id = optString(args, "id");
696
+ if (!id) {
697
+ const { data } = await client.migrations.list({ limit: 1 });
698
+ if (!data[0]) return textResult("No imports yet. Run import_from_provider first; previews are not stored.", true);
699
+ id = data[0].id;
700
+ }
701
+ return textResult(await client.migrations.get(id));
702
+ }
685
703
  default:
686
704
  return textResult(`Unknown tool: ${name}`, true);
687
705
  }
@@ -730,12 +748,15 @@ var readOnly = (title) => ({
730
748
  var MCP_TOOLS = [
731
749
  {
732
750
  name: "send_email",
733
- description: "Send a transactional email via Groundmail. Provide subject + html/text, or a published template_id / template_alias with optional variables.",
751
+ description: "Send a transactional email via Groundmail. Provide subject + html/text, or a published template_id / template_alias with optional variables. To test without delivering anything, send to a simulator address: delivered@, bounce@, block@, complaint@, suppressed@ or delayed@simulator.groundmail.dev (plus addressing like bounce+test1@ works); the result has test: true and webhooks fire as for real mail.",
734
752
  inputSchema: {
735
753
  type: "object",
736
754
  properties: {
737
755
  from: { type: "string", description: "Sender address (must match a verified domain or sandbox sender)" },
738
- to: { type: "string", description: "Recipient email address" },
756
+ to: {
757
+ type: "string",
758
+ description: "Recipient email address. A \u2026@simulator.groundmail.dev address simulates an outcome and never delivers"
759
+ },
739
760
  subject: { type: "string", description: "Subject line. Optional when using a published template" },
740
761
  html: { type: "string", description: "HTML body. Do not combine with template_id or template_alias" },
741
762
  text: { type: "string", description: "Plain-text body. Do not combine with template_id or template_alias" },
@@ -761,10 +782,13 @@ var MCP_TOOLS = [
761
782
  },
762
783
  {
763
784
  name: "list_emails",
764
- description: "List recent emails sent from this account.",
785
+ description: "List recent emails sent from this account. Test emails (test keys, simulator addresses) have test: true.",
765
786
  inputSchema: {
766
787
  type: "object",
767
- properties: { ...paginationProps }
788
+ properties: {
789
+ ...paginationProps,
790
+ test: { type: "boolean", description: "true: only test emails; false: only live ones. Omit for both" }
791
+ }
768
792
  },
769
793
  outputSchema: pagedOutput("emails", emailItem, "Emails on this page, newest first"),
770
794
  annotations: readOnly("List emails")
@@ -1123,6 +1147,18 @@ var MCP_TOOLS = [
1123
1147
  idempotentHint: true,
1124
1148
  openWorldHint: true
1125
1149
  }
1150
+ },
1151
+ {
1152
+ name: "get_import_report",
1153
+ description: "Beta. The stored report of an import from SendGrid, Postmark or Mailgun: what was imported, skipped and failed, the DNS changes per domain, what still needs doing, the code change and a prompt for it. Pass the import id, or omit it for the latest import. Previews are not stored.",
1154
+ inputSchema: {
1155
+ type: "object",
1156
+ properties: {
1157
+ id: { type: "string", description: "Import id (the `id` from import_from_provider). Omit for the latest import." }
1158
+ }
1159
+ },
1160
+ outputSchema: migrationOutput,
1161
+ annotations: readOnly("Get an import report")
1126
1162
  }
1127
1163
  ];
1128
1164
  function resolveApiKey() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groundmail-mcp",
3
- "version": "0.7.1",
3
+ "version": "0.9.0",
4
4
  "mcpName": "io.github.Groundmail/groundmail",
5
5
  "description": "Groundmail MCP server: send transactional email, manage domains, templates, webhooks and suppressions from Claude, Cursor, ChatGPT and other MCP clients",
6
6
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@modelcontextprotocol/sdk": "^1.30.0",
44
- "groundmail": "0.15.1"
44
+ "groundmail": "0.17.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "tsup": "^8.5.0",