groundmail-mcp 0.14.5 → 0.15.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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +131 -6
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -55,7 +55,7 @@ When you connect, you choose the access: **Full**, **Send only** or **Read only*
55
55
  >
56
56
  > "How is my deliverability over the last 7 days?"
57
57
 
58
- Tools cover emails (send, list, look up), domains (add, apply DNS through Cloudflare, Vercel or GoDaddy, verify), templates, webhooks, suppressions, address validation, deliverability, DMARC monitoring, imports from other providers and tenants (one per customer you send for: create, update, pause, resume, stats; `tenant` on sends, domains and suppressions). Each tool carries read-only and destructive annotations and an output schema. Full list: [docs.groundmail.dev/ai/mcp](https://docs.groundmail.dev/ai/mcp).
58
+ Tools cover emails (send, list, look up), domains (add, apply DNS through Cloudflare, Vercel or GoDaddy, verify), templates, webhooks, suppressions, address validation, deliverability, DMARC monitoring, email testing (a test address per run, then wait for the email and read its code and links), imports from other providers and tenants (one per customer you send for: create, update, pause, resume, stats; `tenant` on sends, domains and suppressions). Each tool carries read-only and destructive annotations and an output schema. Full list: [docs.groundmail.dev/ai/mcp](https://docs.groundmail.dev/ai/mcp).
59
59
 
60
60
  ## Transports
61
61
 
package/dist/index.js CHANGED
@@ -559,6 +559,58 @@ var tenantStatsOutput = object(
559
559
  },
560
560
  ["tenant", "stats"]
561
561
  );
562
+ var testInboxOutput = object(
563
+ {
564
+ test_inbox: described(
565
+ object(
566
+ {
567
+ object: string("Always test_inbox"),
568
+ domain: string("The team's test domain. Mail to any address at it is caught and never delivered"),
569
+ address: string("A fresh unique address on the test domain. Use a new one for each test"),
570
+ addon: anyObject("Email testing add-on: active (boolean) and status"),
571
+ usage: anyObject("This month: received, rejected, included (100 free, 5,000 with the add-on), overage, resets_at"),
572
+ retention_days: number("Days caught emails are kept")
573
+ },
574
+ ["domain", "address"]
575
+ ),
576
+ "The team's test inbox"
577
+ )
578
+ },
579
+ ["test_inbox"]
580
+ );
581
+ var testEmailFields = {
582
+ object: string("Always test_inbox_email"),
583
+ id: string("Test email id (tie_\u2026)"),
584
+ source: string("inbound (received at the test domain, from any provider) or test_key (sent with a gm_test_ key)"),
585
+ email_id: nullableString("With test_key: the sent email id (msg_\u2026)"),
586
+ from: string("Sender"),
587
+ to: stringArray("Recipients"),
588
+ cc: stringArray("Cc addresses"),
589
+ subject: string("Subject line"),
590
+ code: nullableString("The one-time code found in the email (4 to 8 digits), or null"),
591
+ links: stringArray("http(s) links in the email, in order"),
592
+ received_at: string("When it arrived (ISO 8601)"),
593
+ expires_at: string("When it is deleted (ISO 8601)")
594
+ };
595
+ var testEmailItem = object(testEmailFields, ["id", "subject"]);
596
+ var testEmailOutput = object(
597
+ {
598
+ email: described(
599
+ object(
600
+ {
601
+ ...testEmailFields,
602
+ text_body: nullableString("Plain-text body"),
603
+ html_body: nullableString("HTML body"),
604
+ headers: arrayOf(anyObject("A header: name and value"), "Message headers in order"),
605
+ raw_source: nullableString("Raw message source, when available")
606
+ },
607
+ ["id", "subject"]
608
+ ),
609
+ "The test email"
610
+ )
611
+ },
612
+ ["email"]
613
+ );
562
614
 
563
615
  // src/tools.ts
564
616
  function textResult(value, isError = false) {
@@ -979,6 +1031,32 @@ async function callMcpTool(client, name, args) {
979
1031
  }
980
1032
  return textResult(await client.migrations.get(id));
981
1033
  }
1034
+ case "get_test_inbox_address": {
1035
+ return textResult({ test_inbox: await client.testInbox.info() });
1036
+ }
1037
+ case "list_test_emails": {
1038
+ return textResult(
1039
+ await client.testInbox.list({
1040
+ limit: optNumber(args, "limit"),
1041
+ cursor: optString(args, "cursor"),
1042
+ to: optString(args, "to"),
1043
+ since: optString(args, "since")
1044
+ })
1045
+ );
1046
+ }
1047
+ case "get_test_email": {
1048
+ const id = optString(args, "id");
1049
+ if (!id) return textResult("Missing required argument: id", true);
1050
+ return textResult({ email: await client.testInbox.get(id) });
1051
+ }
1052
+ case "wait_for_test_email": {
1053
+ const to = optString(args, "to");
1054
+ if (!to) return textResult("Missing required argument: to", true);
1055
+ const seconds = Math.min(60, Math.max(0, optNumber(args, "timeout") ?? 30));
1056
+ return textResult({
1057
+ email: await client.testInbox.waitFor({ to, timeout: seconds * 1e3, since: optString(args, "since") })
1058
+ });
1059
+ }
982
1060
  default:
983
1061
  return textResult(`Unknown tool: ${name}`, true);
984
1062
  }
@@ -1301,7 +1379,7 @@ var MCP_TOOLS = [
1301
1379
  annotations: {
1302
1380
  title: "Add suppression",
1303
1381
  readOnlyHint: false,
1304
- destructiveHint: false,
1382
+ destructiveHint: true,
1305
1383
  idempotentHint: true,
1306
1384
  openWorldHint: false
1307
1385
  }
@@ -1436,7 +1514,7 @@ var MCP_TOOLS = [
1436
1514
  annotations: {
1437
1515
  title: "Publish template",
1438
1516
  readOnlyHint: false,
1439
- destructiveHint: false,
1517
+ destructiveHint: true,
1440
1518
  idempotentHint: false,
1441
1519
  openWorldHint: false
1442
1520
  }
@@ -1529,7 +1607,7 @@ var MCP_TOOLS = [
1529
1607
  annotations: {
1530
1608
  title: "Update tenant",
1531
1609
  readOnlyHint: false,
1532
- destructiveHint: false,
1610
+ destructiveHint: true,
1533
1611
  idempotentHint: true,
1534
1612
  openWorldHint: false
1535
1613
  }
@@ -1549,7 +1627,7 @@ var MCP_TOOLS = [
1549
1627
  annotations: {
1550
1628
  title: "Pause tenant",
1551
1629
  readOnlyHint: false,
1552
- destructiveHint: false,
1630
+ destructiveHint: true,
1553
1631
  idempotentHint: true,
1554
1632
  openWorldHint: false
1555
1633
  }
@@ -1617,7 +1695,7 @@ var MCP_TOOLS = [
1617
1695
  annotations: {
1618
1696
  title: "Enable DMARC monitoring",
1619
1697
  readOnlyHint: false,
1620
- destructiveHint: false,
1698
+ destructiveHint: true,
1621
1699
  idempotentHint: true,
1622
1700
  openWorldHint: true
1623
1701
  }
@@ -1678,6 +1756,53 @@ var MCP_TOOLS = [
1678
1756
  },
1679
1757
  outputSchema: migrationOutput,
1680
1758
  annotations: readOnly("Get an import report")
1759
+ },
1760
+ {
1761
+ name: "get_test_inbox_address",
1762
+ description: "Get a fresh unique address on the team's test domain (<team>.test.groundmail.dev), plus this month's test email usage. Mail sent to it from any email provider (SendGrid, SES, Groundmail or anything else) is caught in the test inbox and never delivered. Use a new address per test, have the app send to it, then call wait_for_test_email.",
1763
+ inputSchema: { type: "object", properties: {} },
1764
+ outputSchema: testInboxOutput,
1765
+ annotations: readOnly("Get a test inbox address")
1766
+ },
1767
+ {
1768
+ name: "list_test_emails",
1769
+ description: "List emails caught in the test inbox (and emails sent with a gm_test_ key), newest first, with the extracted one-time code and links. Kept 14 days.",
1770
+ inputSchema: {
1771
+ type: "object",
1772
+ properties: {
1773
+ ...paginationProps,
1774
+ to: { type: "string", description: "Only emails to this exact address" },
1775
+ since: { type: "string", description: "Only emails received at or after this time (ISO 8601)" }
1776
+ }
1777
+ },
1778
+ outputSchema: pagedOutput("emails", testEmailItem, "Caught test emails, newest first"),
1779
+ annotations: readOnly("List test emails")
1780
+ },
1781
+ {
1782
+ name: "get_test_email",
1783
+ description: "Get one caught test email with its text and HTML bodies, headers, source, code and links.",
1784
+ inputSchema: {
1785
+ type: "object",
1786
+ properties: { id: { type: "string", description: "Test email id (tie_\u2026)" } },
1787
+ required: ["id"]
1788
+ },
1789
+ outputSchema: testEmailOutput,
1790
+ annotations: readOnly("Get test email")
1791
+ },
1792
+ {
1793
+ name: "wait_for_test_email",
1794
+ description: "Wait for an email to a test inbox address and return it, with the one-time code and links extracted. An email that already arrived is returned at once. Waits up to timeout seconds (default 30, at most 60); on timeout, check that the app sent to the exact address and call again.",
1795
+ inputSchema: {
1796
+ type: "object",
1797
+ properties: {
1798
+ to: { type: "string", description: "The exact test address the app sent to" },
1799
+ timeout: { type: "number", description: "Seconds to wait, at most 60 (default 30)" },
1800
+ since: { type: "string", description: "Only emails received at or after this time (ISO 8601)" }
1801
+ },
1802
+ required: ["to"]
1803
+ },
1804
+ outputSchema: testEmailOutput,
1805
+ annotations: readOnly("Wait for a test email")
1681
1806
  }
1682
1807
  ];
1683
1808
  function resolveApiKey() {
@@ -1692,7 +1817,7 @@ function resolveApiKey() {
1692
1817
  }
1693
1818
 
1694
1819
  // src/server.ts
1695
- var MCP_SERVER_VERSION = "0.14.5";
1820
+ var MCP_SERVER_VERSION = "0.15.0";
1696
1821
  var MCP_SERVER_INSTRUCTIONS = [
1697
1822
  "Groundmail sends transactional email from domains the user has verified.",
1698
1823
  'To test before a domain is verified, call send_email with from "noreply@mail.groundmail.dev" and to set to the Groundmail account email; sandbox sends to any other address are rejected.',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groundmail-mcp",
3
- "version": "0.14.5",
3
+ "version": "0.15.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.32.1",
44
- "groundmail": "0.25.1"
44
+ "groundmail": "0.26.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "tsup": "^8.5.0",