zapsmtp-mcp 0.0.0-stage → 0.1.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 (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +311 -2
  3. package/dist/bin.d.ts +2 -0
  4. package/dist/bin.js +16 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/catalog.d.ts +30 -0
  7. package/dist/catalog.js +80 -0
  8. package/dist/catalog.js.map +1 -0
  9. package/dist/docs.d.ts +13 -0
  10. package/dist/docs.js +22 -0
  11. package/dist/docs.js.map +1 -0
  12. package/dist/generated/api.d.ts +2 -0
  13. package/dist/generated/api.js +5721 -0
  14. package/dist/generated/api.js.map +1 -0
  15. package/dist/generated/model.d.ts +89 -0
  16. package/dist/generated/model.js +37 -0
  17. package/dist/generated/model.js.map +1 -0
  18. package/dist/http.d.ts +25 -0
  19. package/dist/http.js +122 -0
  20. package/dist/http.js.map +1 -0
  21. package/dist/index.d.ts +8 -0
  22. package/dist/index.js +9 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/main.d.ts +28 -0
  25. package/dist/main.js +123 -0
  26. package/dist/main.js.map +1 -0
  27. package/dist/schema.d.ts +7 -0
  28. package/dist/schema.js +56 -0
  29. package/dist/schema.js.map +1 -0
  30. package/dist/server.d.ts +28 -0
  31. package/dist/server.js +82 -0
  32. package/dist/server.js.map +1 -0
  33. package/dist/tools.d.ts +46 -0
  34. package/dist/tools.js +342 -0
  35. package/dist/tools.js.map +1 -0
  36. package/dist/version.d.ts +1 -0
  37. package/dist/version.js +2 -0
  38. package/dist/version.js.map +1 -0
  39. package/docs/actions.md +13 -0
  40. package/docs/ai-tools.md +136 -0
  41. package/docs/analytics.md +1881 -0
  42. package/docs/click-actions.md +320 -0
  43. package/docs/conventions.md +131 -0
  44. package/docs/dashboard.md +69 -0
  45. package/docs/deliverability.md +1483 -0
  46. package/docs/domain-setup.md +1494 -0
  47. package/docs/domains.md +19 -0
  48. package/docs/emails.md +20 -0
  49. package/docs/inbound-guide.md +2188 -0
  50. package/docs/inbound.md +24 -0
  51. package/docs/index.json +240 -0
  52. package/docs/index.md +224 -0
  53. package/docs/keys.md +15 -0
  54. package/docs/llms.txt +176 -0
  55. package/docs/logs.md +11 -0
  56. package/docs/migration.md +1779 -0
  57. package/docs/platform.md +10 -0
  58. package/docs/receiving.md +19 -0
  59. package/docs/recipes.md +3594 -0
  60. package/docs/sdks.md +311 -0
  61. package/docs/sending.md +972 -0
  62. package/docs/smtp.md +183 -0
  63. package/docs/stats.md +12 -0
  64. package/docs/suppressions.md +14 -0
  65. package/docs/teams.md +36 -0
  66. package/docs/template-editor.md +62 -0
  67. package/docs/template-library.md +17 -0
  68. package/docs/templates.md +20 -0
  69. package/docs/templating.md +1613 -0
  70. package/docs/testing.md +153 -0
  71. package/docs/variables.md +11 -0
  72. package/docs/webhook-events.md +246 -0
  73. package/docs/webhooks.md +19 -0
  74. package/package.json +59 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ZapSMTP
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,312 @@
1
- # Temporary Holding Version
1
+ # ZapSMTP MCP server
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The official [Model Context Protocol](https://modelcontextprotocol.io) server for
4
+ [ZapSMTP](https://zapsmtp.com): let Claude, Cursor, VS Code, Codex and any other MCP client send,
5
+ receive and track email, and manage templates, domains, webhooks and everything else the API does.
6
+
7
+ - **The whole API**: one tool per API operation (112), generated from the API reference, so a new
8
+ endpoint becomes a tool with the next release. Clear descriptions and JSON Schemas with every
9
+ parameter, required field and allowed value.
10
+ - **Safe to hand to an agent**: tool annotations (read-only, destructive, idempotent, open-world) for
11
+ clients that ask before acting, `--read-only`, toolsets, a recipient domain allowlist, and sends that
12
+ never repeat when retried. The API key never reaches the model.
13
+ - **Made for agents**: `send_test_email` tries any delivery outcome on simulator addresses that never
14
+ leave ZapSMTP; `verify_webhook_signature` checks webhook requests; lists come back one page at a time
15
+ with a cursor for the next; errors carry the API's code, message and request id.
16
+ - **stdio or Streamable HTTP**: run it next to your editor, or serve a team over HTTP where every client
17
+ brings its own API key.
18
+ - **The docs as resources**: `llms.txt` and every guide, bundled in the package (nothing is fetched at
19
+ runtime).
20
+
21
+ Node.js 18.3 or newer. Built on the official [Node.js SDK](https://www.npmjs.com/package/zapsmtp).
22
+
23
+ ## Quick start
24
+
25
+ Create an API key in the [dashboard](https://zapsmtp.com) (a `zap_test_…` key runs everything without
26
+ delivering anything), then add the server to your client.
27
+
28
+ ### Claude Code
29
+
30
+ ```bash
31
+ claude mcp add zapsmtp -e ZAP_API_KEY=zap_... -- npx -y zapsmtp-mcp
32
+ ```
33
+
34
+ With a default sender and only the tools you need:
35
+
36
+ ```bash
37
+ claude mcp add zapsmtp -e ZAP_API_KEY=zap_... -e ZAP_SENDER="Acme <hello@acme.com>" \
38
+ -- npx -y zapsmtp-mcp --toolsets emails,templates,simulator
39
+ ```
40
+
41
+ ### Claude Desktop
42
+
43
+ Settings → Developer → Edit Config (`claude_desktop_config.json`):
44
+
45
+ ```json
46
+ {
47
+ "mcpServers": {
48
+ "zapsmtp": {
49
+ "command": "npx",
50
+ "args": ["-y", "zapsmtp-mcp"],
51
+ "env": { "ZAP_API_KEY": "zap_..." }
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ ### Cursor
58
+
59
+ `~/.cursor/mcp.json` (every project) or `.cursor/mcp.json` (one project):
60
+
61
+ ```json
62
+ {
63
+ "mcpServers": {
64
+ "zapsmtp": {
65
+ "command": "npx",
66
+ "args": ["-y", "zapsmtp-mcp"],
67
+ "env": { "ZAP_API_KEY": "zap_..." }
68
+ }
69
+ }
70
+ }
71
+ ```
72
+
73
+ ### VS Code (GitHub Copilot agent mode)
74
+
75
+ `.vscode/mcp.json`; VS Code asks for the key once and stores it securely:
76
+
77
+ ```json
78
+ {
79
+ "inputs": [
80
+ { "type": "promptString", "id": "zapsmtp-key", "description": "ZapSMTP API key", "password": true }
81
+ ],
82
+ "servers": {
83
+ "zapsmtp": {
84
+ "type": "stdio",
85
+ "command": "npx",
86
+ "args": ["-y", "zapsmtp-mcp"],
87
+ "env": { "ZAP_API_KEY": "${input:zapsmtp-key}" }
88
+ }
89
+ }
90
+ }
91
+ ```
92
+
93
+ ### OpenAI Codex
94
+
95
+ ```bash
96
+ codex mcp add zapsmtp --env ZAP_API_KEY=zap_... -- npx -y zapsmtp-mcp
97
+ ```
98
+
99
+ or in `~/.codex/config.toml`:
100
+
101
+ ```toml
102
+ [mcp_servers.zapsmtp]
103
+ command = "npx"
104
+ args = ["-y", "zapsmtp-mcp"]
105
+ env = { ZAP_API_KEY = "zap_..." }
106
+ ```
107
+
108
+ ### Windsurf
109
+
110
+ `~/.codeium/windsurf/mcp_config.json`:
111
+
112
+ ```json
113
+ {
114
+ "mcpServers": {
115
+ "zapsmtp": {
116
+ "command": "npx",
117
+ "args": ["-y", "zapsmtp-mcp"],
118
+ "env": { "ZAP_API_KEY": "zap_..." }
119
+ }
120
+ }
121
+ }
122
+ ```
123
+
124
+ ### Zed
125
+
126
+ `settings.json`:
127
+
128
+ ```json
129
+ {
130
+ "context_servers": {
131
+ "zapsmtp": {
132
+ "source": "custom",
133
+ "command": "npx",
134
+ "args": ["-y", "zapsmtp-mcp"],
135
+ "env": { "ZAP_API_KEY": "zap_..." }
136
+ }
137
+ }
138
+ }
139
+ ```
140
+
141
+ ### Gemini CLI
142
+
143
+ `~/.gemini/settings.json` (Gemini CLI expands `$ZAP_API_KEY` from your environment):
144
+
145
+ ```json
146
+ {
147
+ "mcpServers": {
148
+ "zapsmtp": {
149
+ "command": "npx",
150
+ "args": ["-y", "zapsmtp-mcp"],
151
+ "env": { "ZAP_API_KEY": "$ZAP_API_KEY" }
152
+ }
153
+ }
154
+ }
155
+ ```
156
+
157
+ ### Any other client
158
+
159
+ Run `npx -y zapsmtp-mcp` over stdio with `ZAP_API_KEY` in its environment, or connect to the HTTP
160
+ server below.
161
+
162
+ ## Streamable HTTP
163
+
164
+ ```bash
165
+ npx -y zapsmtp-mcp --http # http://127.0.0.1:3000/mcp
166
+ npx -y zapsmtp-mcp --http --port 8080 --host 0.0.0.0
167
+ ```
168
+
169
+ The HTTP server holds no API key. Every client sends its own as `Authorization: Bearer <key>`, and each
170
+ request gets its own SDK client and MCP server (the server is stateless), so one client's key is never
171
+ used for another's calls. A request without a key gets `401`.
172
+
173
+ ```bash
174
+ claude mcp add --transport http zapsmtp http://127.0.0.1:3000/mcp --header "Authorization: Bearer zap_..."
175
+ ```
176
+
177
+ ```json
178
+ {
179
+ "mcpServers": {
180
+ "zapsmtp": { "url": "http://127.0.0.1:3000/mcp", "headers": { "Authorization": "Bearer zap_..." } }
181
+ }
182
+ }
183
+ ```
184
+
185
+ - It listens on `127.0.0.1` unless `--host` says otherwise, and while on loopback it refuses requests
186
+ whose `Host` or `Origin` is not local (DNS rebinding).
187
+ - Beyond your machine, put it behind HTTPS (a reverse proxy): the key travels in a header.
188
+ - `GET /health` answers `{"status": "ok"}` for load balancers. Request bodies are limited to 64 MiB.
189
+
190
+ ## Options
191
+
192
+ | Flag | Environment | Default | |
193
+ |---|---|---|---|
194
+ | `--key <key>` | `ZAP_API_KEY` | | API key (stdio). Not used with `--http`. |
195
+ | `--http` | | off | Serve Streamable HTTP at `/mcp` instead of stdio |
196
+ | `--port <port>` | `ZAP_MCP_PORT` | `3000` | HTTP port |
197
+ | `--host <host>` | `ZAP_MCP_HOST` | `127.0.0.1` | HTTP address |
198
+ | `--toolsets <a,b>` | `ZAP_TOOLSETS` | the defaults below | Toolsets to expose, or `all` |
199
+ | `--read-only` | `ZAP_READ_ONLY=1` | off | Only tools that change nothing |
200
+ | `--sender <address>` | `ZAP_SENDER` | | From for sends that omit it; without one, sends require `from` |
201
+ | `--reply-to <address>` | `ZAP_REPLY_TO` | | Reply-To for sends that omit it |
202
+ | `--allowed-recipient-domains <a,b>` | `ZAP_ALLOWED_RECIPIENT_DOMAINS` | | Refuse sends to any other domain |
203
+ | `--base-url <url>` | `ZAP_BASE_URL` | `https://api.zapsmtp.com/v1` | API base URL |
204
+ | `--list-tools` | | | Print the tools these options expose, and exit |
205
+ | `-h`, `--help` / `-v`, `--version` | | | |
206
+
207
+ Flags win over the environment.
208
+
209
+ ## Toolsets
210
+
211
+ The default toolsets give 76 tools; `--read-only` leaves 41 of them. Clients that slow down with many
212
+ tools do best with just the toolsets they need: `--toolsets emails,simulator` is 14 tools.
213
+
214
+ | Toolset | Default | Tools | |
215
+ |---|---|---|---|
216
+ | `emails` | yes | 12 | `emails_send`, `emails_send_batch`, `emails_list`, `emails_get`, `emails_update`, `emails_cancel`, `emails_get_content`, `emails_spam_check`, `emails_spam_check_sent`, `emails_attachments_list`, `emails_attachments_get`, `emails_share` |
217
+ | `receiving` | yes | 8 | `emails_receiving_list`, `emails_receiving_get`, `emails_receiving_delete`, `emails_receiving_attachments_list`, `emails_receiving_attachments_get`, `emails_receiving_redeliver`, `emails_receiving_report_spam`, `emails_receiving_reply` |
218
+ | `threads` | yes | 3 | `threads_list`, `threads_get`, `threads_update` |
219
+ | `templates` | yes | 12 | `templates_list`, `templates_create`, `templates_get`, `templates_update`, `templates_delete`, `templates_render`, `templates_render_source`, `templates_publish`, `templates_duplicate`, `templates_versions_list`, `templates_versions_get`, `templates_versions_restore` |
220
+ | `variables` | yes | 3 | `variables_list`, `variables_set_global`, `variables_delete_global` |
221
+ | `domains` | yes | 11 | `domains_list`, `domains_create`, `domains_get`, `domains_update`, `domains_verify`, `domains_delete`, `domains_get_dmarc`, `domains_get_reputation`, `domains_check_reputation`, `domains_get_brand`, `domains_update_brand` |
222
+ | `webhooks` | yes | 12 | `webhooks_list`, `webhooks_create`, `webhooks_get`, `webhooks_update`, `webhooks_delete`, `webhooks_test`, `webhooks_list_deliveries`, `webhooks_rotate_secret`, `webhooks_events_replay`, `webhooks_events_list`, `webhooks_events_get`, `verify_webhook_signature` |
223
+ | `suppressions` | yes | 6 | `suppressions_list`, `suppressions_create`, `suppressions_delete`, `suppressions_get`, `suppressions_create_batch`, `suppressions_delete_batch` |
224
+ | `logs` | yes | 2 | `logs_list`, `logs_get` |
225
+ | `stats` | yes | 4 | `stats_get`, `stats_timeseries`, `stats_breakdown`, `stats_metrics` |
226
+ | `usage` | yes | 1 | `usage_get` |
227
+ | `simulator` | yes | 2 | `simulator_get`, `send_test_email` |
228
+ | `inbound` | | 16 | inbound domains, routes and forward destinations |
229
+ | `actions` | | 5 | click actions |
230
+ | `template_modules` | | 5 | reusable template modules |
231
+ | `template_assets` | | 3 | images hosted for templates |
232
+ | `template_timers` | | 1 | countdown timer images |
233
+ | `api_keys` | | 4 | create, update and revoke API keys |
234
+ | `smtp_credentials` | | 3 | SMTP relay credentials |
235
+ | `dedicated_ips` | | 1 | dedicated sending IPs |
236
+
237
+ `zapsmtp-mcp --list-tools --toolsets all` prints every tool. Tool names follow the
238
+ [Node.js SDK](https://www.npmjs.com/package/zapsmtp): `zap.templates.versions.get` is
239
+ `templates_versions_get`.
240
+
241
+ ## What the tools do
242
+
243
+ - **Arguments** are the API's parameters by their API names (`reply_to`, `scheduled_at`), path
244
+ parameters included (`templates_versions_get` takes `id` and `vid`). Unknown or missing arguments are
245
+ refused before anything is sent.
246
+ - **Results** are the API's JSON. A list returns one page: `{data, has_more, next_cursor}`; pass
247
+ `next_cursor` back as `cursor` for the next page with the same filters. An operation without a body
248
+ returns `{"ok": true}`.
249
+ - **Errors** are tool errors (`isError`) with `{"error": {status, code, type, message, request_id}}`,
250
+ so the model can correct itself; quote the `request_id` to support.
251
+ - **Sends** (`emails_send`, `emails_send_batch`, `emails_receiving_reply`) take an `idempotency_key`; the
252
+ server makes one when it is omitted, so the SDK's automatic retries never send twice.
253
+ - **`send_test_email`** sends to the simulator address of a scenario (`delivered`, `bounced`, `full`,
254
+ `blocked`, `delayed`, `complained`, `suppressed`, or any SMTP reply as `bounce+<code>…`) and returns
255
+ the email id with the event to expect.
256
+ - **`verify_webhook_signature`** checks a webhook request's `Zap-Signature` against its raw body and
257
+ the endpoint's secret, locally, and returns its events (several for a batch webhook).
258
+
259
+ Annotations: tools for `GET` requests, renders and spam checks are `readOnlyHint`. Deletes, cancelling a
260
+ scheduled email, rotating a webhook secret, removing suppressions and restoring a template version are
261
+ `destructiveHint`. Sends, test webhooks and replays are `openWorldHint`. Updates, deletes and
262
+ verifications are `idempotentHint`.
263
+
264
+ ## Resources
265
+
266
+ When the package was built with the docs site, `resources/list` offers
267
+ `https://zapsmtp.com/llms.txt` (an index of the docs) and every guide as Markdown, for example
268
+ `https://zapsmtp.com/docs/sending.md`. They are read from the package; nothing is fetched.
269
+
270
+ ## Safety
271
+
272
+ - **The key stays out of the conversation.** It is read from the environment or a flag and sent only to
273
+ the API. Tool results and errors are scrubbed of it, and the server writes nothing about it to its
274
+ logs. Prefer the environment (or VS Code's `promptString` input) over `--key`, which shows in process
275
+ lists.
276
+ - **Scope the key.** Give the agent a `zap_test_…` key while you try things, and a key restricted to
277
+ sending, one domain or one stream (`api_keys_create`) for production use.
278
+ - **Limit what the agent can do**: `--read-only`, `--toolsets`, and
279
+ `--allowed-recipient-domains acme.com,example.org`, which refuses sends to any other domain (and its
280
+ subdomains) before any request is made. Under the allowlist, `emails_receiving_reply` must name its
281
+ recipients in `to` and cannot use `reply_all`, since the original sender's domain is unknown until
282
+ the API answers. `send_test_email` always sends to the simulator.
283
+ - **Review before approving**: destructive tools are annotated, so clients that ask before running a tool
284
+ (Claude Code, Claude Desktop, VS Code, Cursor) show which calls change or delete things.
285
+ - **HTTP**: loopback by default with `Host`/`Origin` checks; use HTTPS beyond your machine.
286
+
287
+ ## Embedding
288
+
289
+ ```ts
290
+ import { API, buildTools, createServer, makeClient } from 'zapsmtp-mcp';
291
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
292
+
293
+ const tools = buildTools(API, { toolsets: ['emails', 'simulator'], sender: 'hello@acme.com' });
294
+ const server = createServer({ client: makeClient({ apiKey: process.env.ZAP_API_KEY! }), tools });
295
+ await server.connect(new StdioServerTransport());
296
+ ```
297
+
298
+ ## Development
299
+
300
+ ```bash
301
+ cd sdks/node && npm ci && npm run build # the SDK this package uses
302
+ cd ../mcp && npm ci
303
+ npm run generate # src/generated/ by sdks/codegen (emit/mcp.mjs); the build fails when it is stale
304
+ npm test # every tool against the conformance server, HTTP auth, safety options
305
+ npm run coverage # 100% of the hand-written code
306
+ npm run build # the codegen check, dist/, and docs/ from landing/zapsmtp-site/dist when it is built
307
+ ../live/run.sh mcp # against the dev API
308
+ ```
309
+
310
+ `src/generated/` is generated by `sdks/codegen` (`emit/mcp.mjs`; the code calling the SDK comes from
311
+ `codegen/templates/tools-model.ts`, shared with the CLI); `src/catalog.ts` holds the hand-written choices (toolsets,
312
+ annotations, descriptions).
package/dist/bin.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/bin.js ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ // Entry point of the zapsmtp-mcp command.
3
+ import { main } from './main.js';
4
+ main(process.argv.slice(2), process.env, process).then((r) => {
5
+ if (typeof r === 'number') {
6
+ process.exitCode = r;
7
+ return;
8
+ }
9
+ const stop = () => { void r.close().then(() => process.exit(0)); };
10
+ process.once('SIGINT', stop);
11
+ process.once('SIGTERM', stop);
12
+ }, (err) => {
13
+ process.stderr.write(`zapsmtp-mcp: ${err instanceof Error ? err.message : String(err)}\n`);
14
+ process.exitCode = 1;
15
+ });
16
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,0CAA0C;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;IAC3D,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC,EAAE,CAAC,GAAY,EAAE,EAAE;IAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3F,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { type Operation } from './generated/model.js';
2
+ export interface Toolset {
3
+ name: string;
4
+ description: string;
5
+ default: boolean;
6
+ }
7
+ /** Every toolset, in the order they are listed. A resource without one here gets its own (snake_case name). */
8
+ export declare const TOOLSETS: Toolset[];
9
+ export declare const DEFAULT_TOOLSETS: string[];
10
+ /** The SDK method path of an operation, e.g. "emails.receiving.list". */
11
+ export declare const sdkName: (op: Operation) => string;
12
+ /** emails.receiving.attachments.list -> emails_receiving_attachments_list */
13
+ export declare const toolName: (op: Operation) => string;
14
+ /** Received emails get a toolset of their own; every other operation belongs to its top-level resource. */
15
+ export declare const toolsetOf: (op: Operation) => string;
16
+ export interface Annotations {
17
+ title: string;
18
+ readOnlyHint: boolean;
19
+ destructiveHint?: boolean;
20
+ idempotentHint?: boolean;
21
+ openWorldHint: boolean;
22
+ }
23
+ export declare function annotations(op: Operation): Annotations;
24
+ /** Operations whose recipients --allowed-recipient-domains checks, and the parameters that hold them. */
25
+ export declare const RECIPIENT_PARAMS: Record<string, string[]>;
26
+ /** Operations that take the default sender and Reply-To. */
27
+ export declare const SENDS: Set<string>;
28
+ /** The operation's documentation, cut at a sentence end when it is long. */
29
+ export declare function describe(op: Operation): string;
30
+ export declare function trim(s: string, max: number): string;
@@ -0,0 +1,80 @@
1
+ // The hand-written layer over the generated operations: tool names, toolsets,
2
+ // annotations and descriptions. Everything here is a judgement call the API
3
+ // model cannot make; the parameters themselves always come from the model.
4
+ import { snake } from './generated/model.js';
5
+ /** Every toolset, in the order they are listed. A resource without one here gets its own (snake_case name). */
6
+ export const TOOLSETS = [
7
+ { name: 'emails', description: 'Send (one or a batch), list, get, reschedule, cancel, spam-check and share sent emails; their attachments', default: true },
8
+ { name: 'receiving', description: 'Received (inbound) emails: list, get, reply, report spam, redeliver, attachments, delete', default: true },
9
+ { name: 'threads', description: 'Conversations of sent and received emails', default: true },
10
+ { name: 'templates', description: 'Templates: create, update, render, publish, duplicate, versions', default: true },
11
+ { name: 'variables', description: 'Template variables and global variables', default: true },
12
+ { name: 'domains', description: 'Sending domains: DNS records, verification, tracking, DMARC reports, reputation, brand (BIMI)', default: true },
13
+ { name: 'webhooks', description: 'Webhook endpoints, test deliveries, delivery history, event replay, secret rotation, signature verification', default: true },
14
+ { name: 'suppressions', description: 'The suppression list: add, remove, look up', default: true },
15
+ { name: 'logs', description: 'API request logs', default: true },
16
+ { name: 'stats', description: 'Sending statistics, time series, breakdowns and metrics', default: true },
17
+ { name: 'usage', description: 'This month\'s usage and plan', default: true },
18
+ { name: 'simulator', description: 'Simulator addresses, and send_test_email to try any delivery outcome safely', default: true },
19
+ { name: 'inbound', description: 'Inbound domains, routes and forward destinations', default: false },
20
+ { name: 'actions', description: 'Click actions (named buttons and links)', default: false },
21
+ { name: 'template_modules', description: 'Reusable template modules', default: false },
22
+ { name: 'template_assets', description: 'Images hosted for templates', default: false },
23
+ { name: 'template_timers', description: 'Countdown timer images', default: false },
24
+ { name: 'api_keys', description: 'API keys: create, update, revoke', default: false },
25
+ { name: 'smtp_credentials', description: 'SMTP relay credentials', default: false },
26
+ { name: 'dedicated_ips', description: 'Dedicated sending IPs and their warm-up', default: false },
27
+ ];
28
+ export const DEFAULT_TOOLSETS = TOOLSETS.filter((t) => t.default).map((t) => t.name);
29
+ /** The SDK method path of an operation, e.g. "emails.receiving.list". */
30
+ export const sdkName = (op) => [...op.resource, op.method].join('.');
31
+ /** emails.receiving.attachments.list -> emails_receiving_attachments_list */
32
+ export const toolName = (op) => [...op.resource, op.method].map(snake).join('_');
33
+ /** Received emails get a toolset of their own; every other operation belongs to its top-level resource. */
34
+ export const toolsetOf = (op) => op.resource[0] === 'emails' && op.resource[1] === 'receiving' ? 'receiving' : snake(op.resource[0]);
35
+ /** POST operations that change nothing: they compute an answer. */
36
+ const READ_ONLY_POSTS = new Set(['templates.render', 'templates.renderSource', 'emails.spamCheck', 'emails.spamCheckSent']);
37
+ /** Operations that destroy or revoke something besides DELETE requests. */
38
+ const DESTRUCTIVE = new Set(['emails.cancel', 'webhooks.rotateSecret', 'suppressions.deleteBatch', 'templates.versions.restore']);
39
+ /** POST operations that end in the same state when repeated. */
40
+ const IDEMPOTENT_POSTS = new Set([
41
+ 'emails.cancel', 'domains.verify', 'inbound.domains.verify', 'domains.checkReputation', 'templates.publish',
42
+ 'emails.receiving.reportSpam', 'suppressions.createBatch', 'suppressions.deleteBatch', 'templates.versions.restore',
43
+ ]);
44
+ /** Operations that send email or call a URL outside ZapSMTP. */
45
+ const OPEN_WORLD = new Set([
46
+ 'emails.send', 'emails.sendBatch', 'emails.receiving.reply', 'inbound.forwardDestinations.create',
47
+ 'inbound.forwardDestinations.resendConfirmation', 'webhooks.test', 'webhooks.events.replay', 'emails.receiving.redeliver',
48
+ ]);
49
+ export function annotations(op) {
50
+ const name = sdkName(op);
51
+ const readOnly = op.httpMethod === 'GET' || READ_ONLY_POSTS.has(name);
52
+ const a = { title: op.title, readOnlyHint: readOnly, openWorldHint: OPEN_WORLD.has(name) };
53
+ if (!readOnly) {
54
+ a.destructiveHint = op.httpMethod === 'DELETE' || DESTRUCTIVE.has(name);
55
+ a.idempotentHint = op.httpMethod === 'PUT' || op.httpMethod === 'DELETE' || op.httpMethod === 'PATCH' || IDEMPOTENT_POSTS.has(name);
56
+ }
57
+ return a;
58
+ }
59
+ /** Operations whose recipients --allowed-recipient-domains checks, and the parameters that hold them. */
60
+ export const RECIPIENT_PARAMS = {
61
+ 'emails.send': ['to', 'cc', 'bcc'],
62
+ 'emails.sendBatch': ['to', 'cc', 'bcc'],
63
+ 'emails.receiving.reply': ['to', 'cc', 'bcc'],
64
+ 'inbound.forwardDestinations.create': ['email'],
65
+ };
66
+ /** Operations that take the default sender and Reply-To. */
67
+ export const SENDS = new Set(['emails.send', 'emails.sendBatch']);
68
+ const MAX_DESCRIPTION = 900;
69
+ /** The operation's documentation, cut at a sentence end when it is long. */
70
+ export function describe(op) {
71
+ return trim(op.doc, MAX_DESCRIPTION);
72
+ }
73
+ export function trim(s, max) {
74
+ if (s.length <= max)
75
+ return s;
76
+ const cut = s.slice(0, max);
77
+ const end = Math.max(cut.lastIndexOf('. '), cut.lastIndexOf('.\n'));
78
+ return end > max / 2 ? cut.slice(0, end + 1) : cut.slice(0, cut.lastIndexOf(' ')) + ' …';
79
+ }
80
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
package/dist/docs.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ export interface DocPage {
2
+ uri: string;
3
+ name: string;
4
+ title: string;
5
+ description: string;
6
+ /** the file in the docs directory */
7
+ file: string;
8
+ }
9
+ /** Where the build puts the docs: <package>/docs. */
10
+ export declare const DOCS_DIR: string;
11
+ /** The bundled pages; none when the package was built without them. */
12
+ export declare function loadDocs(dir?: string): DocPage[];
13
+ export declare function readDoc(dir: string, page: DocPage): string;
package/dist/docs.js ADDED
@@ -0,0 +1,22 @@
1
+ // The ZapSMTP docs as MCP resources: llms.txt and the guides in Markdown,
2
+ // bundled into the package at build time (scripts/bundle-docs.mjs). Nothing
3
+ // is fetched at runtime.
4
+ import { readFileSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+ /** Where the build puts the docs: <package>/docs. */
8
+ export const DOCS_DIR = fileURLToPath(new URL('../docs/', import.meta.url));
9
+ /** The bundled pages; none when the package was built without them. */
10
+ export function loadDocs(dir = DOCS_DIR) {
11
+ try {
12
+ const pages = JSON.parse(readFileSync(join(dir, 'index.json'), 'utf8'));
13
+ return Array.isArray(pages) ? pages : [];
14
+ }
15
+ catch {
16
+ return [];
17
+ }
18
+ }
19
+ export function readDoc(dir, page) {
20
+ return readFileSync(join(dir, page.file), 'utf8');
21
+ }
22
+ //# sourceMappingURL=docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,4EAA4E;AAC5E,yBAAyB;AACzB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAWzC,qDAAqD;AACrD,MAAM,CAAC,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE5E,uEAAuE;AACvE,MAAM,UAAU,QAAQ,CAAC,MAAc,QAAQ;IAC7C,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CAAc,CAAC;QACrF,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,IAAa;IAChD,OAAO,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Api } from './model.js';
2
+ export declare const API: Api;