notifycx-mcp 1.1.0 → 1.2.1
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 +11 -5
- package/dist/index.d.ts +1 -2
- package/dist/index.js +125 -11
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@ Use this in Cursor, Claude Code, or other MCP hosts when a coding agent should c
|
|
|
6
6
|
|
|
7
7
|
## Install (Cursor)
|
|
8
8
|
|
|
9
|
+
**Already have a key:**
|
|
10
|
+
|
|
9
11
|
```json
|
|
10
12
|
{
|
|
11
13
|
"mcpServers": {
|
|
@@ -20,23 +22,27 @@ Use this in Cursor, Claude Code, or other MCP hosts when a coding agent should c
|
|
|
20
22
|
}
|
|
21
23
|
```
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
**No key yet:** omit `NOTIFY_API_KEY`, call `bootstrap_start` → user pastes email OTP → `bootstrap_confirm` → put the returned `api_key` into MCP env. See [agent bootstrap docs](https://notify.cx/docs/agent-bootstrap-no-dashboard).
|
|
26
|
+
|
|
27
|
+
Never paste API key secrets into chat logs.
|
|
24
28
|
|
|
25
29
|
## Tools
|
|
26
30
|
|
|
27
31
|
| Tool | When to use |
|
|
28
32
|
|------|-------------|
|
|
33
|
+
| `bootstrap_start` / `bootstrap_confirm` | Sign up or recover without the dashboard (no API key required) |
|
|
29
34
|
| `send_email` | Production transactional send (verified `from`) |
|
|
30
35
|
| `send_test_email` | Non-delivering API rehearsal |
|
|
31
|
-
| `add_domain` | Add domain +
|
|
36
|
+
| `add_domain` | Add domain + structured `dnsRecords` (type/name/value) for the user to publish at their host |
|
|
32
37
|
| `check_domain` | Poll verification after DNS is configured |
|
|
33
|
-
| `list_domains` / `get_domain` | Domain
|
|
38
|
+
| `list_domains` / `get_domain` | Domain status + `dnsRecords` |
|
|
34
39
|
| `list_webhooks` / `create_webhook` / `update_webhook` / `delete_webhook` / `get_webhook` / `test_webhook` | Webhook setup (Pro+) |
|
|
35
40
|
| `list_email_logs` | Recent delivery logs |
|
|
36
41
|
| `get_usage` | Quota / account_verified |
|
|
37
|
-
| `list_api_keys`
|
|
42
|
+
| `list_api_keys` / `create_api_key` / `regenerate_api_key` / `delete_api_key` | Manage keys |
|
|
43
|
+
| `create_billing_checkout` | Stripe Checkout URL for Pro/Scale |
|
|
38
44
|
|
|
39
|
-
Typical setup path: `add_domain` →
|
|
45
|
+
Typical setup path: bootstrap → `add_domain` → user publishes `dnsRecords` → `check_domain` → `send_email`.
|
|
40
46
|
|
|
41
47
|
## Pricing
|
|
42
48
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { }
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
#!/usr/bin/env node
|
|
2
3
|
|
|
3
4
|
// src/index.ts
|
|
4
5
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
6
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
-
import Notify, { NotifyError } from "notifycx";
|
|
7
|
+
import Notify, { NotifyError, NOTIFYCX_VERSION } from "notifycx";
|
|
7
8
|
import { z } from "zod";
|
|
9
|
+
function baseUrl() {
|
|
10
|
+
return process.env.NOTIFY_BASE_URL;
|
|
11
|
+
}
|
|
12
|
+
function optionalApiKey() {
|
|
13
|
+
return process.env.NOTIFY_API_KEY;
|
|
14
|
+
}
|
|
8
15
|
function requireApiKey() {
|
|
9
|
-
const apiKey =
|
|
16
|
+
const apiKey = optionalApiKey();
|
|
10
17
|
if (!apiKey) {
|
|
11
18
|
throw new Error(
|
|
12
|
-
"Missing NOTIFY_API_KEY.
|
|
19
|
+
"Missing NOTIFY_API_KEY. Run bootstrap_start + bootstrap_confirm first, then set NOTIFY_API_KEY in MCP env to the returned api_key (never paste secrets into chat)."
|
|
13
20
|
);
|
|
14
21
|
}
|
|
15
22
|
return apiKey;
|
|
@@ -17,7 +24,7 @@ function requireApiKey() {
|
|
|
17
24
|
function client() {
|
|
18
25
|
return new Notify({
|
|
19
26
|
apiKey: requireApiKey(),
|
|
20
|
-
baseUrl:
|
|
27
|
+
baseUrl: baseUrl(),
|
|
21
28
|
client: "mcp"
|
|
22
29
|
});
|
|
23
30
|
}
|
|
@@ -77,8 +84,57 @@ var webhookWriteShape = {
|
|
|
77
84
|
};
|
|
78
85
|
var server = new McpServer({
|
|
79
86
|
name: "notifycx-mcp",
|
|
80
|
-
version
|
|
87
|
+
// Keep MCP package.json version aligned with notifycx (NOTIFYCX_VERSION).
|
|
88
|
+
version: NOTIFYCX_VERSION
|
|
81
89
|
});
|
|
90
|
+
server.tool(
|
|
91
|
+
"bootstrap_start",
|
|
92
|
+
"Start Notify agent signup or key recovery without the dashboard. Sends a 6-digit email OTP. No NOTIFY_API_KEY required. Ask the user to paste the code, then call bootstrap_confirm. Requires acceptTerms: true (https://notify.cx/terms).",
|
|
93
|
+
{
|
|
94
|
+
email: z.string().email().describe("User email for the Notify account"),
|
|
95
|
+
intent: z.enum(["signup", "recover"]).optional().describe("signup (default) or recover existing account"),
|
|
96
|
+
acceptTerms: z.boolean().describe("Must be true \u2014 user accepts Terms and AUP")
|
|
97
|
+
},
|
|
98
|
+
async (args) => {
|
|
99
|
+
try {
|
|
100
|
+
return ok(
|
|
101
|
+
await Notify.bootstrapStart({
|
|
102
|
+
email: args.email,
|
|
103
|
+
intent: args.intent,
|
|
104
|
+
acceptTerms: args.acceptTerms,
|
|
105
|
+
baseUrl: baseUrl()
|
|
106
|
+
})
|
|
107
|
+
);
|
|
108
|
+
} catch (err) {
|
|
109
|
+
return fail(err);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
server.tool(
|
|
114
|
+
"bootstrap_confirm",
|
|
115
|
+
"Confirm the email OTP from bootstrap_start. Returns api_key once \u2014 instruct the user to put it in MCP env NOTIFY_API_KEY (do not leave the secret in chat). Then use add_domain / send_email. No NOTIFY_API_KEY required for this call.",
|
|
116
|
+
{
|
|
117
|
+
email: z.string().email(),
|
|
118
|
+
code: z.string().regex(/^\d{6}$/).describe("6-digit code from email"),
|
|
119
|
+
intent: z.enum(["signup", "recover"]).optional(),
|
|
120
|
+
clientHint: z.string().max(64).optional().describe("e.g. cursor, chatgpt")
|
|
121
|
+
},
|
|
122
|
+
async (args) => {
|
|
123
|
+
try {
|
|
124
|
+
return ok(
|
|
125
|
+
await Notify.bootstrapConfirm({
|
|
126
|
+
email: args.email,
|
|
127
|
+
code: args.code,
|
|
128
|
+
intent: args.intent,
|
|
129
|
+
clientHint: args.clientHint,
|
|
130
|
+
baseUrl: baseUrl()
|
|
131
|
+
})
|
|
132
|
+
);
|
|
133
|
+
} catch (err) {
|
|
134
|
+
return fail(err);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
);
|
|
82
138
|
server.tool(
|
|
83
139
|
"send_email",
|
|
84
140
|
"Send transactional email via Notify (password reset, receipt, magic link, invoice, etc.) with a verified from domain. Use when the user wants production delivery. Prefer html for the body. For non-delivering API rehearsal before domain verification, use send_test_email instead.",
|
|
@@ -105,7 +161,7 @@ server.tool(
|
|
|
105
161
|
);
|
|
106
162
|
server.tool(
|
|
107
163
|
"list_domains",
|
|
108
|
-
"List Notify sending domains and verification status (SPF/DKIM).
|
|
164
|
+
"List Notify sending domains and verification status (SPF/DKIM). Includes structured dnsRecords (type/name/value) for the user to publish at their DNS host.",
|
|
109
165
|
{},
|
|
110
166
|
async () => {
|
|
111
167
|
try {
|
|
@@ -117,7 +173,7 @@ server.tool(
|
|
|
117
173
|
);
|
|
118
174
|
server.tool(
|
|
119
175
|
"get_domain",
|
|
120
|
-
"Get one Notify sending domain by hostname, including DNS
|
|
176
|
+
"Get one Notify sending domain by hostname, including dnsRecords (type/name/value) and raw DNS tokens for pending verification. Show dnsRecords to the user so they can add them at their hosting provider.",
|
|
121
177
|
{
|
|
122
178
|
domain: z.string().min(1).describe("Domain hostname, e.g. example.com")
|
|
123
179
|
},
|
|
@@ -131,7 +187,7 @@ server.tool(
|
|
|
131
187
|
);
|
|
132
188
|
server.tool(
|
|
133
189
|
"add_domain",
|
|
134
|
-
"Add a sending domain and start SPF/DKIM verification. Returns
|
|
190
|
+
"Add a sending domain and start SPF/DKIM verification. Returns dnsRecords (type/name/value) the user must add at their DNS host \u2014 Notify does not publish DNS. After DNS is configured, call check_domain. Then use send_email with a from address on that domain.",
|
|
135
191
|
{
|
|
136
192
|
domain: z.string().min(1).describe("Domain hostname to verify, e.g. example.com"),
|
|
137
193
|
dnsProvider: z.enum([
|
|
@@ -142,7 +198,7 @@ server.tool(
|
|
|
142
198
|
"godaddy",
|
|
143
199
|
"route53",
|
|
144
200
|
"other"
|
|
145
|
-
]).optional().describe("Optional DNS provider hint for
|
|
201
|
+
]).optional().describe("Optional DNS provider hint for host/name formatting")
|
|
146
202
|
},
|
|
147
203
|
async (args) => {
|
|
148
204
|
try {
|
|
@@ -154,7 +210,7 @@ server.tool(
|
|
|
154
210
|
);
|
|
155
211
|
server.tool(
|
|
156
212
|
"check_domain",
|
|
157
|
-
"Poll SES for domain SPF/DKIM verification status after DNS records were added. Call after add_domain. When both succeed, production send_email with that from domain is unlocked.",
|
|
213
|
+
"Poll SES for domain SPF/DKIM verification status after DNS records were added. Call after add_domain. When both succeed, production send_email with that from domain is unlocked and the plan email limit lifts.",
|
|
158
214
|
{
|
|
159
215
|
domain: z.string().min(1).describe("Domain hostname to check")
|
|
160
216
|
},
|
|
@@ -196,7 +252,7 @@ server.tool(
|
|
|
196
252
|
);
|
|
197
253
|
server.tool(
|
|
198
254
|
"list_api_keys",
|
|
199
|
-
"List API key metadata for the account (id, name, prefix only \u2014 never the full secret).
|
|
255
|
+
"List API key metadata for the account (id, name, prefix only \u2014 never the full secret).",
|
|
200
256
|
{},
|
|
201
257
|
async () => {
|
|
202
258
|
try {
|
|
@@ -206,6 +262,64 @@ server.tool(
|
|
|
206
262
|
}
|
|
207
263
|
}
|
|
208
264
|
);
|
|
265
|
+
server.tool(
|
|
266
|
+
"create_api_key",
|
|
267
|
+
"Create an API key (full_access required). Free plan allows one key. Prefer sending_access + domainId for app keys on Pro+.",
|
|
268
|
+
{
|
|
269
|
+
name: z.string().min(1),
|
|
270
|
+
permission: z.enum(["full_access", "sending_access"]).optional(),
|
|
271
|
+
domainId: z.string().uuid().optional()
|
|
272
|
+
},
|
|
273
|
+
async (args) => {
|
|
274
|
+
try {
|
|
275
|
+
return ok(await client().createApiKey(args));
|
|
276
|
+
} catch (err) {
|
|
277
|
+
return fail(err);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
);
|
|
281
|
+
server.tool(
|
|
282
|
+
"regenerate_api_key",
|
|
283
|
+
"Rotate an API key secret by keyId. Returns the new api_key once \u2014 update NOTIFY_API_KEY / app secrets.",
|
|
284
|
+
{
|
|
285
|
+
keyId: z.string().uuid()
|
|
286
|
+
},
|
|
287
|
+
async (args) => {
|
|
288
|
+
try {
|
|
289
|
+
return ok(await client().regenerateApiKey(args.keyId));
|
|
290
|
+
} catch (err) {
|
|
291
|
+
return fail(err);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
);
|
|
295
|
+
server.tool(
|
|
296
|
+
"delete_api_key",
|
|
297
|
+
"Deactivate an API key by keyId. Cannot delete the last full_access key.",
|
|
298
|
+
{
|
|
299
|
+
keyId: z.string().uuid()
|
|
300
|
+
},
|
|
301
|
+
async (args) => {
|
|
302
|
+
try {
|
|
303
|
+
return ok(await client().deleteApiKey(args.keyId));
|
|
304
|
+
} catch (err) {
|
|
305
|
+
return fail(err);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
);
|
|
309
|
+
server.tool(
|
|
310
|
+
"create_billing_checkout",
|
|
311
|
+
"Get a Stripe Checkout URL for Pro or Scale (full_access key). User opens the URL in a browser to pay \u2014 not the Notify dashboard.",
|
|
312
|
+
{
|
|
313
|
+
plan: z.enum(["pro", "scale"]).optional()
|
|
314
|
+
},
|
|
315
|
+
async (args) => {
|
|
316
|
+
try {
|
|
317
|
+
return ok(await client().createBillingCheckout({ plan: args.plan }));
|
|
318
|
+
} catch (err) {
|
|
319
|
+
return fail(err);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
);
|
|
209
323
|
server.tool(
|
|
210
324
|
"list_webhooks",
|
|
211
325
|
"List Notify webhook subscriptions (URL, events, domain scope).",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "notifycx-mcp",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Official MCP server for Notify — transactional email tools for coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"homepage": "https://notify.cx/mcp",
|
|
28
28
|
"repository": {
|
|
29
29
|
"type": "git",
|
|
30
|
-
"url": "https://github.com/
|
|
30
|
+
"url": "https://github.com/notifycx/notifycx.git",
|
|
31
31
|
"directory": "mcp"
|
|
32
32
|
},
|
|
33
33
|
"author": "notify.cx",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
40
|
-
"notifycx": "^1.1
|
|
40
|
+
"notifycx": "^1.2.1",
|
|
41
41
|
"zod": "^3.24.2"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|