@aiwerk/mcp-server-resend 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 (55) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +21 -0
  3. package/README.md +154 -0
  4. package/dist/src/errors.d.ts +16 -0
  5. package/dist/src/errors.d.ts.map +1 -0
  6. package/dist/src/errors.js +21 -0
  7. package/dist/src/lib/destructive-gate.d.ts +27 -0
  8. package/dist/src/lib/destructive-gate.d.ts.map +1 -0
  9. package/dist/src/lib/destructive-gate.js +72 -0
  10. package/dist/src/lib/idempotency.d.ts +2 -0
  11. package/dist/src/lib/idempotency.d.ts.map +1 -0
  12. package/dist/src/lib/idempotency.js +12 -0
  13. package/dist/src/lib/resend-client.d.ts +13 -0
  14. package/dist/src/lib/resend-client.d.ts.map +1 -0
  15. package/dist/src/lib/resend-client.js +128 -0
  16. package/dist/src/server.d.ts +12 -0
  17. package/dist/src/server.d.ts.map +1 -0
  18. package/dist/src/server.js +400 -0
  19. package/dist/src/tools/apikeys.d.ts +37 -0
  20. package/dist/src/tools/apikeys.d.ts.map +1 -0
  21. package/dist/src/tools/apikeys.js +72 -0
  22. package/dist/src/tools/broadcasts.d.ts +85 -0
  23. package/dist/src/tools/broadcasts.d.ts.map +1 -0
  24. package/dist/src/tools/broadcasts.js +118 -0
  25. package/dist/src/tools/contact-properties.d.ts +47 -0
  26. package/dist/src/tools/contact-properties.d.ts.map +1 -0
  27. package/dist/src/tools/contact-properties.js +80 -0
  28. package/dist/src/tools/contacts.d.ts +137 -0
  29. package/dist/src/tools/contacts.d.ts.map +1 -0
  30. package/dist/src/tools/contacts.js +139 -0
  31. package/dist/src/tools/domains.d.ts +95 -0
  32. package/dist/src/tools/domains.d.ts.map +1 -0
  33. package/dist/src/tools/domains.js +118 -0
  34. package/dist/src/tools/emails.d.ts +214 -0
  35. package/dist/src/tools/emails.d.ts.map +1 -0
  36. package/dist/src/tools/emails.js +142 -0
  37. package/dist/src/tools/logs.d.ts +18 -0
  38. package/dist/src/tools/logs.d.ts.map +1 -0
  39. package/dist/src/tools/logs.js +18 -0
  40. package/dist/src/tools/segments.d.ts +49 -0
  41. package/dist/src/tools/segments.d.ts.map +1 -0
  42. package/dist/src/tools/segments.js +79 -0
  43. package/dist/src/tools/templates.d.ts +113 -0
  44. package/dist/src/tools/templates.d.ts.map +1 -0
  45. package/dist/src/tools/templates.js +113 -0
  46. package/dist/src/tools/topics.d.ts +53 -0
  47. package/dist/src/tools/topics.d.ts.map +1 -0
  48. package/dist/src/tools/topics.js +81 -0
  49. package/dist/src/tools/webhooks.d.ts +49 -0
  50. package/dist/src/tools/webhooks.d.ts.map +1 -0
  51. package/dist/src/tools/webhooks.js +87 -0
  52. package/dist/src/version.d.ts +2 -0
  53. package/dist/src/version.d.ts.map +1 -0
  54. package/dist/src/version.js +2 -0
  55. package/package.json +42 -0
@@ -0,0 +1,113 @@
1
+ import { z } from 'zod';
2
+ import { type ConfirmationRequired } from '../lib/destructive-gate.js';
3
+ type TemplateVariable = {
4
+ key: string;
5
+ type: 'string' | 'number' | 'boolean' | 'object' | 'list';
6
+ fallback_value?: string | number | boolean | Record<string, unknown> | unknown[];
7
+ };
8
+ export declare const templateCreateInputSchema: {
9
+ name: z.ZodString;
10
+ html: z.ZodString;
11
+ alias: z.ZodOptional<z.ZodString>;
12
+ from: z.ZodOptional<z.ZodString>;
13
+ subject: z.ZodOptional<z.ZodString>;
14
+ reply_to: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
15
+ text: z.ZodOptional<z.ZodString>;
16
+ variables: z.ZodOptional<z.ZodArray<z.ZodObject<{
17
+ key: z.ZodString;
18
+ type: z.ZodEnum<["string", "number", "boolean", "object", "list"]>;
19
+ fallback_value: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodArray<z.ZodUnknown, "many">]>>;
20
+ }, "strip", z.ZodTypeAny, {
21
+ type: "string" | "number" | "boolean" | "object" | "list";
22
+ key: string;
23
+ fallback_value?: string | number | boolean | unknown[] | Record<string, unknown> | undefined;
24
+ }, {
25
+ type: "string" | "number" | "boolean" | "object" | "list";
26
+ key: string;
27
+ fallback_value?: string | number | boolean | unknown[] | Record<string, unknown> | undefined;
28
+ }>, "many">>;
29
+ };
30
+ export declare function templateCreate(args: {
31
+ name: string;
32
+ html: string;
33
+ alias?: string;
34
+ from?: string;
35
+ subject?: string;
36
+ reply_to?: string[];
37
+ text?: string;
38
+ variables?: TemplateVariable[];
39
+ }): Promise<unknown>;
40
+ export declare const templateListInputSchema: {
41
+ limit: z.ZodOptional<z.ZodNumber>;
42
+ after: z.ZodOptional<z.ZodString>;
43
+ before: z.ZodOptional<z.ZodString>;
44
+ };
45
+ export declare function templateList(args: {
46
+ limit?: number;
47
+ after?: string;
48
+ before?: string;
49
+ }): Promise<unknown>;
50
+ export declare const templateGetInputSchema: {
51
+ id: z.ZodString;
52
+ };
53
+ export declare function templateGet(args: {
54
+ id: string;
55
+ }): Promise<unknown>;
56
+ export declare const templateUpdateInputSchema: {
57
+ id: z.ZodString;
58
+ name: z.ZodOptional<z.ZodString>;
59
+ alias: z.ZodOptional<z.ZodString>;
60
+ from: z.ZodOptional<z.ZodString>;
61
+ subject: z.ZodOptional<z.ZodString>;
62
+ reply_to: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
63
+ html: z.ZodOptional<z.ZodString>;
64
+ text: z.ZodOptional<z.ZodString>;
65
+ variables: z.ZodOptional<z.ZodArray<z.ZodObject<{
66
+ key: z.ZodString;
67
+ type: z.ZodEnum<["string", "number", "boolean", "object", "list"]>;
68
+ fallback_value: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodArray<z.ZodUnknown, "many">]>>;
69
+ }, "strip", z.ZodTypeAny, {
70
+ type: "string" | "number" | "boolean" | "object" | "list";
71
+ key: string;
72
+ fallback_value?: string | number | boolean | unknown[] | Record<string, unknown> | undefined;
73
+ }, {
74
+ type: "string" | "number" | "boolean" | "object" | "list";
75
+ key: string;
76
+ fallback_value?: string | number | boolean | unknown[] | Record<string, unknown> | undefined;
77
+ }>, "many">>;
78
+ };
79
+ export declare function templateUpdate(args: {
80
+ id: string;
81
+ name?: string;
82
+ alias?: string;
83
+ from?: string;
84
+ subject?: string;
85
+ reply_to?: string[];
86
+ html?: string;
87
+ text?: string;
88
+ variables?: TemplateVariable[];
89
+ }): Promise<unknown>;
90
+ export declare const templateDeleteInputSchema: {
91
+ id: z.ZodOptional<z.ZodString>;
92
+ ids: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
93
+ confirm_token: z.ZodOptional<z.ZodString>;
94
+ };
95
+ export declare function templateDelete(args: {
96
+ id?: string;
97
+ ids?: string[];
98
+ confirm_token?: string;
99
+ }): Promise<unknown | ConfirmationRequired>;
100
+ export declare const templateDuplicateInputSchema: {
101
+ id: z.ZodString;
102
+ };
103
+ export declare function templateDuplicate(args: {
104
+ id: string;
105
+ }): Promise<unknown>;
106
+ export declare const templatePublishInputSchema: {
107
+ id: z.ZodString;
108
+ };
109
+ export declare function templatePublish(args: {
110
+ id: string;
111
+ }): Promise<unknown>;
112
+ export {};
113
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../src/tools/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAA2C,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAgBhH,KAAK,gBAAgB,GAAG;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1D,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,CAAC;CAClF,CAAC;AAIF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;CAUrC,CAAC;AAEF,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACtF,oBAEA;AAID,eAAO,MAAM,uBAAuB;;;;CAAmB,CAAC;AAExD,wBAAsB,YAAY,CAAC,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,oBAE3F;AAID,eAAO,MAAM,sBAAsB;;CAElC,CAAC;AAEF,wBAAsB,WAAW,CAAC,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,oBAErD;AAID,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;CAWrC,CAAC;AAEF,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACpE,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAChC,oBAGA;AAID,eAAO,MAAM,yBAAyB;;;;CAIrC,CAAC;AAEF,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACrD,GAAG,OAAO,CAAC,OAAO,GAAG,oBAAoB,CAAC,CAoC1C;AAID,eAAO,MAAM,4BAA4B;;CAExC,CAAC;AAEF,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,oBAE3D;AAID,eAAO,MAAM,0BAA0B;;CAEtC,CAAC;AAEF,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,oBAEzD"}
@@ -0,0 +1,113 @@
1
+ import { z } from 'zod';
2
+ import { resendPost, resendGet, resendPatch, resendDelete } from '../lib/resend-client.js';
3
+ import { requireConfirmation, validateAndConsume } from '../lib/destructive-gate.js';
4
+ const paginationSchema = {
5
+ limit: z.number().int().min(1).max(100).optional().describe('Max items to return (max 100).'),
6
+ after: z.string().optional().describe('Cursor — return items after this value.'),
7
+ before: z.string().optional().describe('Cursor — return items before this value.'),
8
+ };
9
+ const templateVariableSchema = z.object({
10
+ key: z.string().describe('Variable key.'),
11
+ type: z.enum(['string', 'number', 'boolean', 'object', 'list'])
12
+ .describe('Variable data type.'),
13
+ fallback_value: z.union([z.string(), z.number(), z.boolean(), z.record(z.unknown()), z.array(z.unknown())]).optional()
14
+ .describe('Fallback value when the variable is not supplied at send time. Must match the type.'),
15
+ });
16
+ // --- resend_template_create ---
17
+ export const templateCreateInputSchema = {
18
+ name: z.string().describe('Template name.'),
19
+ html: z.string().describe('HTML content of the template.'),
20
+ alias: z.string().optional().describe('Short alias for the template (used in resend_email_send template field).'),
21
+ from: z.string().optional().describe('Default sender address for emails using this template.'),
22
+ subject: z.string().optional().describe('Default subject line.'),
23
+ reply_to: z.array(z.string()).optional().describe('Default reply-to address(es).'),
24
+ text: z.string().optional().describe('Plain text version of the template.'),
25
+ variables: z.array(templateVariableSchema).optional()
26
+ .describe('Template variable definitions. Each entry has key, type, and optional fallback_value.'),
27
+ };
28
+ export async function templateCreate(args) {
29
+ return resendPost('/templates', args);
30
+ }
31
+ // --- resend_template_list ---
32
+ export const templateListInputSchema = paginationSchema;
33
+ export async function templateList(args) {
34
+ return resendGet('/templates', args);
35
+ }
36
+ // --- resend_template_get ---
37
+ export const templateGetInputSchema = {
38
+ id: z.string().describe('Template ID.'),
39
+ };
40
+ export async function templateGet(args) {
41
+ return resendGet(`/templates/${args.id}`);
42
+ }
43
+ // --- resend_template_update ---
44
+ export const templateUpdateInputSchema = {
45
+ id: z.string().describe('Template ID to update.'),
46
+ name: z.string().optional().describe('New template name.'),
47
+ alias: z.string().optional().describe('New alias.'),
48
+ from: z.string().optional().describe('New default sender.'),
49
+ subject: z.string().optional().describe('New default subject.'),
50
+ reply_to: z.array(z.string()).optional().describe('New reply-to address(es).'),
51
+ html: z.string().optional().describe('New HTML content.'),
52
+ text: z.string().optional().describe('New plain text content.'),
53
+ variables: z.array(templateVariableSchema).optional()
54
+ .describe('Updated template variable definitions.'),
55
+ };
56
+ export async function templateUpdate(args) {
57
+ const { id, ...body } = args;
58
+ return resendPatch(`/templates/${id}`, body);
59
+ }
60
+ // --- resend_template_delete (α-gated, bulk) ---
61
+ export const templateDeleteInputSchema = {
62
+ id: z.string().optional().describe('Template ID to delete. Provide id or ids.'),
63
+ ids: z.array(z.string()).optional().describe('Multiple template IDs to delete.'),
64
+ confirm_token: z.string().optional().describe('Confirmation token from a previous call.'),
65
+ };
66
+ export async function templateDelete(args) {
67
+ const { confirm_token, ...rest } = args;
68
+ const tool = 'resend_template_delete';
69
+ if (!rest.id && (!rest.ids || rest.ids.length === 0)) {
70
+ throw new Error('Provide id (single) or ids (bulk).');
71
+ }
72
+ const isBulk = !!rest.ids;
73
+ const ids = isBulk ? rest.ids : undefined;
74
+ const id = !isBulk ? rest.id : undefined;
75
+ if (!confirm_token) {
76
+ const count = isBulk ? ids.length : 1;
77
+ const preview = isBulk ? ids.slice(0, 3).join(', ') : rest.id;
78
+ return requireConfirmation({
79
+ tool, id, ids, payload: rest,
80
+ summary: `Delete ${count} template(s): ${preview}. Irreversible.`,
81
+ });
82
+ }
83
+ const result = validateAndConsume({ confirm_token, tool, id, ids, payload: rest });
84
+ if (!result.valid)
85
+ throw new Error(result.reason);
86
+ if (isBulk) {
87
+ const results = await Promise.allSettled(ids.map(tid => resendDelete(`/templates/${tid}`)));
88
+ const succeeded = [];
89
+ const failed = [];
90
+ results.forEach((r, idx) => {
91
+ if (r.status === 'fulfilled')
92
+ succeeded.push(ids[idx]);
93
+ else
94
+ failed.push({ id: ids[idx], error: String(r.reason) });
95
+ });
96
+ return { succeeded, failed, summary: `${succeeded.length}/${ids.length} succeeded` };
97
+ }
98
+ return resendDelete(`/templates/${rest.id}`);
99
+ }
100
+ // --- resend_template_duplicate ---
101
+ export const templateDuplicateInputSchema = {
102
+ id: z.string().describe('Template ID to duplicate.'),
103
+ };
104
+ export async function templateDuplicate(args) {
105
+ return resendPost(`/templates/${args.id}/duplicate`);
106
+ }
107
+ // --- resend_template_publish ---
108
+ export const templatePublishInputSchema = {
109
+ id: z.string().describe('Template ID to publish. Published templates can be referenced by alias in resend_email_send.'),
110
+ };
111
+ export async function templatePublish(args) {
112
+ return resendPost(`/templates/${args.id}/publish`);
113
+ }
@@ -0,0 +1,53 @@
1
+ import { z } from 'zod';
2
+ import { type ConfirmationRequired } from '../lib/destructive-gate.js';
3
+ export declare const topicCreateInputSchema: {
4
+ name: z.ZodString;
5
+ default_subscription: z.ZodEnum<["opt_in", "opt_out"]>;
6
+ description: z.ZodOptional<z.ZodString>;
7
+ visibility: z.ZodOptional<z.ZodEnum<["public", "private"]>>;
8
+ };
9
+ export declare function topicCreate(args: {
10
+ name: string;
11
+ default_subscription: 'opt_in' | 'opt_out';
12
+ description?: string;
13
+ visibility?: 'public' | 'private';
14
+ }): Promise<unknown>;
15
+ export declare const topicListInputSchema: {
16
+ limit: z.ZodOptional<z.ZodNumber>;
17
+ after: z.ZodOptional<z.ZodString>;
18
+ before: z.ZodOptional<z.ZodString>;
19
+ };
20
+ export declare function topicList(args: {
21
+ limit?: number;
22
+ after?: string;
23
+ before?: string;
24
+ }): Promise<unknown>;
25
+ export declare const topicGetInputSchema: {
26
+ id: z.ZodString;
27
+ };
28
+ export declare function topicGet(args: {
29
+ id: string;
30
+ }): Promise<unknown>;
31
+ export declare const topicUpdateInputSchema: {
32
+ id: z.ZodString;
33
+ name: z.ZodOptional<z.ZodString>;
34
+ description: z.ZodOptional<z.ZodString>;
35
+ visibility: z.ZodOptional<z.ZodEnum<["public", "private"]>>;
36
+ };
37
+ export declare function topicUpdate(args: {
38
+ id: string;
39
+ name?: string;
40
+ description?: string;
41
+ visibility?: 'public' | 'private';
42
+ }): Promise<unknown>;
43
+ export declare const topicDeleteInputSchema: {
44
+ id: z.ZodOptional<z.ZodString>;
45
+ ids: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
46
+ confirm_token: z.ZodOptional<z.ZodString>;
47
+ };
48
+ export declare function topicDelete(args: {
49
+ id?: string;
50
+ ids?: string[];
51
+ confirm_token?: string;
52
+ }): Promise<unknown | ConfirmationRequired>;
53
+ //# sourceMappingURL=topics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topics.d.ts","sourceRoot":"","sources":["../../../src/tools/topics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAA2C,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAUhH,eAAO,MAAM,sBAAsB;;;;;CAKlC,CAAC;AAEF,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,IAAI,EAAE,MAAM,CAAC;IAAC,oBAAoB,EAAE,QAAQ,GAAG,SAAS,CAAC;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CACzD,oBAEA;AAID,eAAO,MAAM,oBAAoB;;;;CAAmB,CAAC;AAErD,wBAAsB,SAAS,CAAC,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,oBAExF;AAID,eAAO,MAAM,mBAAmB;;CAE/B,CAAC;AAEF,wBAAsB,QAAQ,CAAC,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,oBAElD;AAID,eAAO,MAAM,sBAAsB;;;;;CAKlC,CAAC;AAEF,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CACpF,oBAGA;AAID,eAAO,MAAM,sBAAsB;;;;CAIlC,CAAC;AAEF,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACrD,GAAG,OAAO,CAAC,OAAO,GAAG,oBAAoB,CAAC,CAoC1C"}
@@ -0,0 +1,81 @@
1
+ import { z } from 'zod';
2
+ import { resendPost, resendGet, resendPatch, resendDelete } from '../lib/resend-client.js';
3
+ import { requireConfirmation, validateAndConsume } from '../lib/destructive-gate.js';
4
+ const paginationSchema = {
5
+ limit: z.number().int().min(1).max(100).optional().describe('Max items to return (max 100).'),
6
+ after: z.string().optional().describe('Cursor — return items after this value.'),
7
+ before: z.string().optional().describe('Cursor — return items before this value.'),
8
+ };
9
+ // --- resend_topic_create ---
10
+ export const topicCreateInputSchema = {
11
+ name: z.string().describe('Topic name (e.g. "Weekly Newsletter").'),
12
+ default_subscription: z.enum(['opt_in', 'opt_out']).describe('Default subscription for contacts not explicitly opted in/out. opt_in means new contacts are subscribed by default.'),
13
+ description: z.string().optional().describe('Human-readable description of the topic.'),
14
+ visibility: z.enum(['public', 'private']).optional().describe('Visibility of the topic (default: private).'),
15
+ };
16
+ export async function topicCreate(args) {
17
+ return resendPost('/topics', args);
18
+ }
19
+ // --- resend_topic_list ---
20
+ export const topicListInputSchema = paginationSchema;
21
+ export async function topicList(args) {
22
+ return resendGet('/topics', args);
23
+ }
24
+ // --- resend_topic_get ---
25
+ export const topicGetInputSchema = {
26
+ id: z.string().describe('Topic ID.'),
27
+ };
28
+ export async function topicGet(args) {
29
+ return resendGet(`/topics/${args.id}`);
30
+ }
31
+ // --- resend_topic_update ---
32
+ export const topicUpdateInputSchema = {
33
+ id: z.string().describe('Topic ID to update.'),
34
+ name: z.string().optional().describe('New topic name.'),
35
+ description: z.string().optional().describe('New description.'),
36
+ visibility: z.enum(['public', 'private']).optional().describe('New visibility.'),
37
+ };
38
+ export async function topicUpdate(args) {
39
+ const { id, ...body } = args;
40
+ return resendPatch(`/topics/${id}`, body);
41
+ }
42
+ // --- resend_topic_delete (α-gated, bulk) ---
43
+ export const topicDeleteInputSchema = {
44
+ id: z.string().optional().describe('Topic ID to delete. Provide id or ids.'),
45
+ ids: z.array(z.string()).optional().describe('Multiple topic IDs to delete.'),
46
+ confirm_token: z.string().optional().describe('Confirmation token from a previous call.'),
47
+ };
48
+ export async function topicDelete(args) {
49
+ const { confirm_token, ...rest } = args;
50
+ const tool = 'resend_topic_delete';
51
+ if (!rest.id && (!rest.ids || rest.ids.length === 0)) {
52
+ throw new Error('Provide id (single) or ids (bulk).');
53
+ }
54
+ const isBulk = !!rest.ids;
55
+ const ids = isBulk ? rest.ids : undefined;
56
+ const id = !isBulk ? rest.id : undefined;
57
+ if (!confirm_token) {
58
+ const count = isBulk ? ids.length : 1;
59
+ const preview = isBulk ? ids.slice(0, 3).join(', ') : rest.id;
60
+ return requireConfirmation({
61
+ tool, id, ids, payload: rest,
62
+ summary: `Delete ${count} topic(s): ${preview}. Irreversible — contact subscription data for this topic is lost.`,
63
+ });
64
+ }
65
+ const result = validateAndConsume({ confirm_token, tool, id, ids, payload: rest });
66
+ if (!result.valid)
67
+ throw new Error(result.reason);
68
+ if (isBulk) {
69
+ const results = await Promise.allSettled(ids.map(tid => resendDelete(`/topics/${tid}`)));
70
+ const succeeded = [];
71
+ const failed = [];
72
+ results.forEach((r, idx) => {
73
+ if (r.status === 'fulfilled')
74
+ succeeded.push(ids[idx]);
75
+ else
76
+ failed.push({ id: ids[idx], error: String(r.reason) });
77
+ });
78
+ return { succeeded, failed, summary: `${succeeded.length}/${ids.length} succeeded` };
79
+ }
80
+ return resendDelete(`/topics/${rest.id}`);
81
+ }
@@ -0,0 +1,49 @@
1
+ import { z } from 'zod';
2
+ import { type ConfirmationRequired } from '../lib/destructive-gate.js';
3
+ export declare const webhookCreateInputSchema: {
4
+ endpoint: z.ZodString;
5
+ events: z.ZodArray<z.ZodString, "many">;
6
+ };
7
+ export declare function webhookCreate(args: {
8
+ endpoint: string;
9
+ events: string[];
10
+ }): Promise<unknown>;
11
+ export declare const webhookListInputSchema: {
12
+ limit: z.ZodOptional<z.ZodNumber>;
13
+ after: z.ZodOptional<z.ZodString>;
14
+ before: z.ZodOptional<z.ZodString>;
15
+ };
16
+ export declare function webhookList(args: {
17
+ limit?: number;
18
+ after?: string;
19
+ before?: string;
20
+ }): Promise<unknown>;
21
+ export declare const webhookGetInputSchema: {
22
+ webhook_id: z.ZodString;
23
+ };
24
+ export declare function webhookGet(args: {
25
+ webhook_id: string;
26
+ }): Promise<unknown>;
27
+ export declare const webhookUpdateInputSchema: {
28
+ webhook_id: z.ZodString;
29
+ endpoint: z.ZodOptional<z.ZodString>;
30
+ events: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
31
+ status: z.ZodOptional<z.ZodEnum<["enabled", "disabled"]>>;
32
+ };
33
+ export declare function webhookUpdate(args: {
34
+ webhook_id: string;
35
+ endpoint?: string;
36
+ events?: string[];
37
+ status?: 'enabled' | 'disabled';
38
+ }): Promise<unknown>;
39
+ export declare const webhookDeleteInputSchema: {
40
+ webhook_id: z.ZodOptional<z.ZodString>;
41
+ webhook_ids: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
42
+ confirm_token: z.ZodOptional<z.ZodString>;
43
+ };
44
+ export declare function webhookDelete(args: {
45
+ webhook_id?: string;
46
+ webhook_ids?: string[];
47
+ confirm_token?: string;
48
+ }): Promise<unknown | ConfirmationRequired>;
49
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../../src/tools/webhooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAA2C,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAgBhH,eAAO,MAAM,wBAAwB;;;CAIpC,CAAC;AAEF,wBAAsB,aAAa,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,oBAE/E;AAID,eAAO,MAAM,sBAAsB;;;;CAAmB,CAAC;AAEvD,wBAAsB,WAAW,CAAC,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,oBAE1F;AAID,eAAO,MAAM,qBAAqB;;CAEjC,CAAC;AAEF,wBAAsB,UAAU,CAAC,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,oBAE5D;AAID,eAAO,MAAM,wBAAwB;;;;;CAOpC,CAAC;AAEF,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;CAC3F,oBAGA;AAID,eAAO,MAAM,wBAAwB;;;;CAIpC,CAAC;AAEF,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACrE,GAAG,OAAO,CAAC,OAAO,GAAG,oBAAoB,CAAC,CAoC1C"}
@@ -0,0 +1,87 @@
1
+ import { z } from 'zod';
2
+ import { resendPost, resendGet, resendPatch, resendDelete } from '../lib/resend-client.js';
3
+ import { requireConfirmation, validateAndConsume } from '../lib/destructive-gate.js';
4
+ const WEBHOOK_EVENTS = [
5
+ 'email.sent', 'email.delivered', 'email.delivery_delayed',
6
+ 'email.complained', 'email.bounced', 'email.opened', 'email.clicked',
7
+ 'contact.created', 'contact.deleted', 'contact.updated',
8
+ ];
9
+ const paginationSchema = {
10
+ limit: z.number().int().min(1).max(100).optional().describe('Max items to return (max 100).'),
11
+ after: z.string().optional().describe('Cursor — return items after this value.'),
12
+ before: z.string().optional().describe('Cursor — return items before this value.'),
13
+ };
14
+ // --- resend_webhook_create ---
15
+ export const webhookCreateInputSchema = {
16
+ endpoint: z.string().url().describe('HTTPS URL that will receive webhook POST requests.'),
17
+ events: z.array(z.string()).min(1)
18
+ .describe(`Event types to subscribe to. Known values: ${WEBHOOK_EVENTS.join(', ')}.`),
19
+ };
20
+ export async function webhookCreate(args) {
21
+ return resendPost('/webhooks', args);
22
+ }
23
+ // --- resend_webhook_list ---
24
+ export const webhookListInputSchema = paginationSchema;
25
+ export async function webhookList(args) {
26
+ return resendGet('/webhooks', args);
27
+ }
28
+ // --- resend_webhook_get ---
29
+ export const webhookGetInputSchema = {
30
+ webhook_id: z.string().describe('Webhook ID.'),
31
+ };
32
+ export async function webhookGet(args) {
33
+ return resendGet(`/webhooks/${args.webhook_id}`);
34
+ }
35
+ // --- resend_webhook_update ---
36
+ export const webhookUpdateInputSchema = {
37
+ webhook_id: z.string().describe('Webhook ID to update.'),
38
+ endpoint: z.string().url().optional().describe('New endpoint URL.'),
39
+ events: z.array(z.string()).min(1).optional()
40
+ .describe('New set of event types to subscribe to.'),
41
+ status: z.enum(['enabled', 'disabled']).optional()
42
+ .describe('Enable or disable the webhook without deleting it.'),
43
+ };
44
+ export async function webhookUpdate(args) {
45
+ const { webhook_id, ...body } = args;
46
+ return resendPatch(`/webhooks/${webhook_id}`, body);
47
+ }
48
+ // --- resend_webhook_delete (α-gated, bulk) ---
49
+ export const webhookDeleteInputSchema = {
50
+ webhook_id: z.string().optional().describe('Webhook ID to delete. Provide webhook_id or webhook_ids.'),
51
+ webhook_ids: z.array(z.string()).optional().describe('Multiple webhook IDs to delete.'),
52
+ confirm_token: z.string().optional().describe('Confirmation token from a previous call.'),
53
+ };
54
+ export async function webhookDelete(args) {
55
+ const { confirm_token, ...rest } = args;
56
+ const tool = 'resend_webhook_delete';
57
+ if (!rest.webhook_id && (!rest.webhook_ids || rest.webhook_ids.length === 0)) {
58
+ throw new Error('Provide webhook_id (single) or webhook_ids (bulk).');
59
+ }
60
+ const isBulk = !!rest.webhook_ids;
61
+ const ids = isBulk ? rest.webhook_ids : undefined;
62
+ const id = !isBulk ? rest.webhook_id : undefined;
63
+ if (!confirm_token) {
64
+ const count = isBulk ? ids.length : 1;
65
+ const preview = isBulk ? ids.slice(0, 3).join(', ') : rest.webhook_id;
66
+ return requireConfirmation({
67
+ tool, id, ids, payload: rest,
68
+ summary: `Delete ${count} webhook(s): ${preview}. Stops event delivery — irreversible.`,
69
+ });
70
+ }
71
+ const result = validateAndConsume({ confirm_token, tool, id, ids, payload: rest });
72
+ if (!result.valid)
73
+ throw new Error(result.reason);
74
+ if (isBulk) {
75
+ const results = await Promise.allSettled(ids.map(wid => resendDelete(`/webhooks/${wid}`)));
76
+ const succeeded = [];
77
+ const failed = [];
78
+ results.forEach((r, idx) => {
79
+ if (r.status === 'fulfilled')
80
+ succeeded.push(ids[idx]);
81
+ else
82
+ failed.push({ id: ids[idx], error: String(r.reason) });
83
+ });
84
+ return { succeeded, failed, summary: `${succeeded.length}/${ids.length} succeeded` };
85
+ }
86
+ return resendDelete(`/webhooks/${rest.webhook_id}`);
87
+ }
@@ -0,0 +1,2 @@
1
+ export declare const VERSION = "0.1.0";
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,OAAO,UAAU,CAAC"}
@@ -0,0 +1,2 @@
1
+ // Generated by scripts/gen-version.mjs — do not edit by hand.
2
+ export const VERSION = "0.1.0";
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@aiwerk/mcp-server-resend",
3
+ "version": "0.1.0",
4
+ "description": "Resend API MCP server — transactional and marketing email, domains, contacts, broadcasts, and more",
5
+ "type": "module",
6
+ "main": "dist/src/server.js",
7
+ "bin": {
8
+ "mcp-server-resend": "dist/src/server.js"
9
+ },
10
+ "files": ["dist", "README.md", "CHANGELOG.md", "LICENSE"],
11
+ "scripts": {
12
+ "gen-version": "node scripts/gen-version.mjs",
13
+ "prebuild": "npm run gen-version",
14
+ "build": "tsc -p tsconfig.json",
15
+ "start": "node dist/src/server.js",
16
+ "predev": "npm run gen-version",
17
+ "dev": "tsc --watch",
18
+ "pretest": "npm run gen-version && bash -c 'pkill -9 -f \"[n]ode.*vitest\" 2>/dev/null; pkill -9 -f \"[e]sbuild.*--service\" 2>/dev/null; true'",
19
+ "test": "vitest run",
20
+ "posttest": "bash -c 'pkill -9 -f \"[n]ode.*vitest\" 2>/dev/null; pkill -9 -f \"[e]sbuild.*--service\" 2>/dev/null; true'",
21
+ "prepublishOnly": "bash scripts/prepublish-safety.sh && npm run build && npm test"
22
+ },
23
+ "engines": { "node": ">=18.0.0" },
24
+ "keywords": ["mcp", "mcp-server", "resend", "email", "transactional-email"],
25
+ "author": "AIWerk <kontakt@aiwerk.ch>",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/AIWerk/mcp-server-resend.git"
30
+ },
31
+ "homepage": "https://aiwerkmcp.com",
32
+ "bugs": { "url": "https://github.com/AIWerk/mcp-server-resend/issues" },
33
+ "dependencies": {
34
+ "@modelcontextprotocol/sdk": "^1.19.1",
35
+ "zod": "^3.25.76"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^22.0.0",
39
+ "typescript": "^5.5.0",
40
+ "vitest": "^3.2.1"
41
+ }
42
+ }