mcp-resend 1.0.0-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.
Files changed (56) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +257 -0
  3. package/data/embeddings.json +245241 -0
  4. package/dist/config/environment.d.ts +152 -0
  5. package/dist/config/environment.d.ts.map +1 -0
  6. package/dist/config/environment.js +217 -0
  7. package/dist/config/environment.js.map +1 -0
  8. package/dist/index.d.ts +13 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +119 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/services/rate-limiter.d.ts +90 -0
  13. package/dist/services/rate-limiter.d.ts.map +1 -0
  14. package/dist/services/rate-limiter.js +267 -0
  15. package/dist/services/rate-limiter.js.map +1 -0
  16. package/dist/services/tool-registry.d.ts +219 -0
  17. package/dist/services/tool-registry.d.ts.map +1 -0
  18. package/dist/services/tool-registry.js +459 -0
  19. package/dist/services/tool-registry.js.map +1 -0
  20. package/dist/tools/docs/embeddings-loader.d.ts +69 -0
  21. package/dist/tools/docs/embeddings-loader.d.ts.map +1 -0
  22. package/dist/tools/docs/embeddings-loader.js +218 -0
  23. package/dist/tools/docs/embeddings-loader.js.map +1 -0
  24. package/dist/tools/docs/errors.d.ts +75 -0
  25. package/dist/tools/docs/errors.d.ts.map +1 -0
  26. package/dist/tools/docs/errors.js +145 -0
  27. package/dist/tools/docs/errors.js.map +1 -0
  28. package/dist/tools/docs/index.d.ts +11 -0
  29. package/dist/tools/docs/index.d.ts.map +1 -0
  30. package/dist/tools/docs/index.js +14 -0
  31. package/dist/tools/docs/index.js.map +1 -0
  32. package/dist/tools/docs/metrics.d.ts +94 -0
  33. package/dist/tools/docs/metrics.d.ts.map +1 -0
  34. package/dist/tools/docs/metrics.js +174 -0
  35. package/dist/tools/docs/metrics.js.map +1 -0
  36. package/dist/tools/docs/search-docs-tool.d.ts +54 -0
  37. package/dist/tools/docs/search-docs-tool.d.ts.map +1 -0
  38. package/dist/tools/docs/search-docs-tool.js +231 -0
  39. package/dist/tools/docs/search-docs-tool.js.map +1 -0
  40. package/dist/tools/docs/types.d.ts +70 -0
  41. package/dist/tools/docs/types.d.ts.map +1 -0
  42. package/dist/tools/docs/types.js +7 -0
  43. package/dist/tools/docs/types.js.map +1 -0
  44. package/dist/tools/docs/vector-search.d.ts +80 -0
  45. package/dist/tools/docs/vector-search.d.ts.map +1 -0
  46. package/dist/tools/docs/vector-search.js +297 -0
  47. package/dist/tools/docs/vector-search.js.map +1 -0
  48. package/dist/tools/index.d.ts +27 -0
  49. package/dist/tools/index.d.ts.map +1 -0
  50. package/dist/tools/index.js +3413 -0
  51. package/dist/tools/index.js.map +1 -0
  52. package/dist/utils/mcp-errors.d.ts +109 -0
  53. package/dist/utils/mcp-errors.d.ts.map +1 -0
  54. package/dist/utils/mcp-errors.js +306 -0
  55. package/dist/utils/mcp-errors.js.map +1 -0
  56. package/package.json +77 -0
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Environment Configuration
3
+ *
4
+ * Validates and provides access to environment variables with Zod schemas.
5
+ * Supports API key validation, scopes, tiers, and debug settings.
6
+ *
7
+ * @module config/environment
8
+ */
9
+ import { z } from "zod";
10
+ /**
11
+ * Tool tiers for dynamic loading.
12
+ */
13
+ export type ToolTier = "core" | "secondary" | "tertiary" | "all";
14
+ /**
15
+ * Tool scopes for permission-based access.
16
+ */
17
+ export type ToolScope = "read" | "write" | "admin";
18
+ /**
19
+ * Environment configuration schema.
20
+ *
21
+ * Validates:
22
+ * - RESEND_API_KEY: Optional, must start with "re_" if provided
23
+ * - RESEND_MCP_SCOPES: Optional comma-separated list of scopes
24
+ * - RESEND_MCP_DEFAULT_TIER: Optional tier setting (core|secondary|tertiary|all)
25
+ * - RESEND_RATE_LIMIT_MS: Optional rate limit interval
26
+ * - RESEND_DEBUG: Optional debug flag
27
+ *
28
+ * NOTE: If RESEND_API_KEY is not provided, only documentation search is available.
29
+ */
30
+ declare const envSchema: z.ZodObject<{
31
+ /**
32
+ * Resend API key. Optional, but required for API operations.
33
+ * If not provided, only documentation search tool is available.
34
+ * Get your key from: https://resend.com/api-keys
35
+ */
36
+ RESEND_API_KEY: z.ZodEffects<z.ZodOptional<z.ZodString>, string | undefined, string | undefined>;
37
+ /**
38
+ * Comma-separated list of enabled scopes.
39
+ * Valid values: read, write, admin
40
+ * Example: "read,write"
41
+ */
42
+ RESEND_MCP_SCOPES: z.ZodPipeline<z.ZodEffects<z.ZodOptional<z.ZodString>, string[] | undefined, string | undefined>, z.ZodOptional<z.ZodArray<z.ZodEnum<["read", "write", "admin"]>, "many">>>;
43
+ /**
44
+ * Default tool tier to load on startup.
45
+ * - core: Essential tools only (send_email, list_domains)
46
+ * - secondary: Core + additional tools (templates, contacts)
47
+ * - tertiary: All available tools
48
+ * - all: Alias for tertiary
49
+ */
50
+ RESEND_MCP_DEFAULT_TIER: z.ZodEffects<z.ZodDefault<z.ZodEnum<["core", "secondary", "tertiary", "all"]>>, "core" | "secondary" | "tertiary", "core" | "secondary" | "tertiary" | "all" | undefined>;
51
+ /**
52
+ * Rate limit interval in milliseconds.
53
+ * Default: 500ms (2 requests/second)
54
+ */
55
+ RESEND_RATE_LIMIT_MS: z.ZodEffects<z.ZodOptional<z.ZodString>, number, string | undefined>;
56
+ /**
57
+ * Enable debug logging.
58
+ * Set to "true", "1", or "yes" to enable.
59
+ */
60
+ RESEND_DEBUG: z.ZodEffects<z.ZodOptional<z.ZodString>, boolean, string | undefined>;
61
+ }, "strip", z.ZodTypeAny, {
62
+ RESEND_MCP_DEFAULT_TIER: "core" | "secondary" | "tertiary";
63
+ RESEND_RATE_LIMIT_MS: number;
64
+ RESEND_DEBUG: boolean;
65
+ RESEND_API_KEY?: string | undefined;
66
+ RESEND_MCP_SCOPES?: ("read" | "write" | "admin")[] | undefined;
67
+ }, {
68
+ RESEND_API_KEY?: string | undefined;
69
+ RESEND_MCP_SCOPES?: string | undefined;
70
+ RESEND_MCP_DEFAULT_TIER?: "core" | "secondary" | "tertiary" | "all" | undefined;
71
+ RESEND_RATE_LIMIT_MS?: string | undefined;
72
+ RESEND_DEBUG?: string | undefined;
73
+ }>;
74
+ /**
75
+ * Inferred type from the environment schema.
76
+ */
77
+ export type EnvConfig = z.infer<typeof envSchema>;
78
+ /**
79
+ * Parsed configuration object.
80
+ * Provides typed access to validated environment variables.
81
+ */
82
+ export interface Config {
83
+ /** Resend API key (undefined if not provided - docs search only mode) */
84
+ apiKey: string | undefined;
85
+ /** Enabled scopes (undefined means all scopes) */
86
+ scopes: ToolScope[] | undefined;
87
+ /** Default tool tier */
88
+ defaultTier: Exclude<ToolTier, "all">;
89
+ /** Rate limit interval in milliseconds */
90
+ rateLimitMs: number;
91
+ /** Debug mode enabled */
92
+ debug: boolean;
93
+ /** Whether API operations are available (API key is set) */
94
+ hasApiKey: boolean;
95
+ }
96
+ /**
97
+ * Load and validate configuration from environment variables.
98
+ * Caches the result for subsequent calls.
99
+ *
100
+ * @throws Error if required environment variables are missing or invalid
101
+ * @returns Validated configuration object
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * const config = loadConfig();
106
+ * console.error(`Using API key: ${config.apiKey.slice(0, 6)}...`);
107
+ * ```
108
+ */
109
+ export declare function loadConfig(): Config;
110
+ /**
111
+ * Get the current configuration.
112
+ * Returns cached config or loads it if not yet loaded.
113
+ *
114
+ * @throws Error if configuration is invalid
115
+ * @returns Validated configuration object
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const config = getConfig();
120
+ * if (config.debug) {
121
+ * console.error("Debug mode enabled");
122
+ * }
123
+ * ```
124
+ */
125
+ export declare function getConfig(): Config;
126
+ /**
127
+ * Check if configuration has been loaded.
128
+ *
129
+ * @returns True if configuration is loaded
130
+ */
131
+ export declare function isConfigLoaded(): boolean;
132
+ /**
133
+ * Reset the configuration cache.
134
+ * Forces reload on next getConfig() or loadConfig() call.
135
+ * Useful for testing or reconfiguration.
136
+ */
137
+ export declare function resetConfig(): void;
138
+ /**
139
+ * Validate that a specific scope is enabled.
140
+ *
141
+ * @param scope - Scope to check
142
+ * @returns True if scope is enabled (or if no scopes are configured)
143
+ */
144
+ export declare function isScopeEnabled(scope: ToolScope): boolean;
145
+ /**
146
+ * Get enabled scopes, or all scopes if none configured.
147
+ *
148
+ * @returns Array of enabled scopes
149
+ */
150
+ export declare function getEnabledScopes(): ToolScope[];
151
+ export {};
152
+ //# sourceMappingURL=environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/config/environment.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,KAAK,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnD;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,SAAS;IACb;;;;OAIG;;IAQH;;;;OAIG;;IAkBH;;;;;;OAMG;;IAMH;;;OAGG;;IAUH;;;OAGG;;;;;;;;;;;;;;EAQH,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAElD;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,yEAAyE;IACzE,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,kDAAkD;IAClD,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAAC;IAChC,wBAAwB;IACxB,WAAW,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACtC,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAC;CACpB;AAOD;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAwDnC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAKlC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAGlC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAOxD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,SAAS,EAAE,CAG9C"}
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Environment Configuration
3
+ *
4
+ * Validates and provides access to environment variables with Zod schemas.
5
+ * Supports API key validation, scopes, tiers, and debug settings.
6
+ *
7
+ * @module config/environment
8
+ */
9
+ import { z } from "zod";
10
+ // NOTE: Use console.error for logging - stdout is reserved for MCP protocol
11
+ const log = (message) => console.error(`[config] ${message}`);
12
+ /**
13
+ * Environment configuration schema.
14
+ *
15
+ * Validates:
16
+ * - RESEND_API_KEY: Optional, must start with "re_" if provided
17
+ * - RESEND_MCP_SCOPES: Optional comma-separated list of scopes
18
+ * - RESEND_MCP_DEFAULT_TIER: Optional tier setting (core|secondary|tertiary|all)
19
+ * - RESEND_RATE_LIMIT_MS: Optional rate limit interval
20
+ * - RESEND_DEBUG: Optional debug flag
21
+ *
22
+ * NOTE: If RESEND_API_KEY is not provided, only documentation search is available.
23
+ */
24
+ const envSchema = z.object({
25
+ /**
26
+ * Resend API key. Optional, but required for API operations.
27
+ * If not provided, only documentation search tool is available.
28
+ * Get your key from: https://resend.com/api-keys
29
+ */
30
+ RESEND_API_KEY: z
31
+ .string()
32
+ .optional()
33
+ .refine((key) => !key || key.startsWith("re_"), {
34
+ message: "RESEND_API_KEY must start with 're_'",
35
+ }),
36
+ /**
37
+ * Comma-separated list of enabled scopes.
38
+ * Valid values: read, write, admin
39
+ * Example: "read,write"
40
+ */
41
+ RESEND_MCP_SCOPES: z
42
+ .string()
43
+ .optional()
44
+ .transform((val) => {
45
+ if (!val)
46
+ return undefined;
47
+ const scopes = val
48
+ .split(",")
49
+ .map((s) => s.trim().toLowerCase())
50
+ .filter((s) => s.length > 0);
51
+ return scopes.length > 0 ? scopes : undefined;
52
+ })
53
+ .pipe(z
54
+ .array(z.enum(["read", "write", "admin"]))
55
+ .optional()),
56
+ /**
57
+ * Default tool tier to load on startup.
58
+ * - core: Essential tools only (send_email, list_domains)
59
+ * - secondary: Core + additional tools (templates, contacts)
60
+ * - tertiary: All available tools
61
+ * - all: Alias for tertiary
62
+ */
63
+ RESEND_MCP_DEFAULT_TIER: z
64
+ .enum(["core", "secondary", "tertiary", "all"])
65
+ .default("core")
66
+ .transform((tier) => (tier === "all" ? "tertiary" : tier)),
67
+ /**
68
+ * Rate limit interval in milliseconds.
69
+ * Default: 500ms (2 requests/second)
70
+ */
71
+ RESEND_RATE_LIMIT_MS: z
72
+ .string()
73
+ .optional()
74
+ .transform((val) => {
75
+ if (!val)
76
+ return 500;
77
+ const parsed = parseInt(val, 10);
78
+ return isNaN(parsed) ? 500 : Math.max(0, parsed);
79
+ }),
80
+ /**
81
+ * Enable debug logging.
82
+ * Set to "true", "1", or "yes" to enable.
83
+ */
84
+ RESEND_DEBUG: z
85
+ .string()
86
+ .optional()
87
+ .transform((val) => {
88
+ if (!val)
89
+ return false;
90
+ return ["true", "1", "yes"].includes(val.toLowerCase());
91
+ }),
92
+ });
93
+ /**
94
+ * Module-level configuration cache.
95
+ */
96
+ let cachedConfig = null;
97
+ /**
98
+ * Load and validate configuration from environment variables.
99
+ * Caches the result for subsequent calls.
100
+ *
101
+ * @throws Error if required environment variables are missing or invalid
102
+ * @returns Validated configuration object
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * const config = loadConfig();
107
+ * console.error(`Using API key: ${config.apiKey.slice(0, 6)}...`);
108
+ * ```
109
+ */
110
+ export function loadConfig() {
111
+ if (cachedConfig) {
112
+ return cachedConfig;
113
+ }
114
+ const result = envSchema.safeParse(process.env);
115
+ if (!result.success) {
116
+ const errors = result.error.errors
117
+ .map((e) => ` - ${e.path.join(".")}: ${e.message}`)
118
+ .join("\n");
119
+ log("Configuration validation failed:");
120
+ log(errors);
121
+ // Provide helpful hints for common issues
122
+ if (result.error.errors.some((e) => e.path.includes("RESEND_API_KEY"))) {
123
+ log("");
124
+ log("Hint: Set your Resend API key:");
125
+ log(' export RESEND_API_KEY="re_your_api_key_here"');
126
+ log(" Get your key from: https://resend.com/api-keys");
127
+ }
128
+ throw new Error(`Environment configuration invalid:\n${errors}`);
129
+ }
130
+ const env = result.data;
131
+ const hasApiKey = Boolean(env.RESEND_API_KEY);
132
+ const config = {
133
+ apiKey: env.RESEND_API_KEY,
134
+ scopes: env.RESEND_MCP_SCOPES,
135
+ defaultTier: env.RESEND_MCP_DEFAULT_TIER,
136
+ rateLimitMs: env.RESEND_RATE_LIMIT_MS,
137
+ debug: env.RESEND_DEBUG,
138
+ hasApiKey,
139
+ };
140
+ cachedConfig = config;
141
+ if (config.debug) {
142
+ log("Configuration loaded:");
143
+ log(` API Key: ${hasApiKey ? config.apiKey.slice(0, 6) + "..." : "(not set - docs only mode)"}`);
144
+ log(` Scopes: ${config.scopes?.join(", ") || "all"}`);
145
+ log(` Default Tier: ${config.defaultTier}`);
146
+ log(` Rate Limit: ${config.rateLimitMs}ms`);
147
+ log(` Debug: ${config.debug}`);
148
+ }
149
+ if (!hasApiKey) {
150
+ log("Running in documentation-only mode (no API key provided)");
151
+ log("Only search_resend_documentation tool is available");
152
+ log("Set RESEND_API_KEY to enable all tools");
153
+ }
154
+ return config;
155
+ }
156
+ /**
157
+ * Get the current configuration.
158
+ * Returns cached config or loads it if not yet loaded.
159
+ *
160
+ * @throws Error if configuration is invalid
161
+ * @returns Validated configuration object
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * const config = getConfig();
166
+ * if (config.debug) {
167
+ * console.error("Debug mode enabled");
168
+ * }
169
+ * ```
170
+ */
171
+ export function getConfig() {
172
+ if (!cachedConfig) {
173
+ return loadConfig();
174
+ }
175
+ return cachedConfig;
176
+ }
177
+ /**
178
+ * Check if configuration has been loaded.
179
+ *
180
+ * @returns True if configuration is loaded
181
+ */
182
+ export function isConfigLoaded() {
183
+ return cachedConfig !== null;
184
+ }
185
+ /**
186
+ * Reset the configuration cache.
187
+ * Forces reload on next getConfig() or loadConfig() call.
188
+ * Useful for testing or reconfiguration.
189
+ */
190
+ export function resetConfig() {
191
+ cachedConfig = null;
192
+ log("Configuration cache cleared");
193
+ }
194
+ /**
195
+ * Validate that a specific scope is enabled.
196
+ *
197
+ * @param scope - Scope to check
198
+ * @returns True if scope is enabled (or if no scopes are configured)
199
+ */
200
+ export function isScopeEnabled(scope) {
201
+ const config = getConfig();
202
+ // If no scopes configured, all scopes are enabled
203
+ if (!config.scopes) {
204
+ return true;
205
+ }
206
+ return config.scopes.includes(scope);
207
+ }
208
+ /**
209
+ * Get enabled scopes, or all scopes if none configured.
210
+ *
211
+ * @returns Array of enabled scopes
212
+ */
213
+ export function getEnabledScopes() {
214
+ const config = getConfig();
215
+ return config.scopes || ["read", "write", "admin"];
216
+ }
217
+ //# sourceMappingURL=environment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/config/environment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Resend MCP Server
4
+ *
5
+ * MCP server for the Resend email API. Enables AI assistants to send emails,
6
+ * manage domains, contacts, and templates via the Model Context Protocol.
7
+ *
8
+ * @module resend-mcp-server
9
+ * @version 1.0.0
10
+ * @license Apache-2.0
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
package/dist/index.js ADDED
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Resend MCP Server
4
+ *
5
+ * MCP server for the Resend email API. Enables AI assistants to send emails,
6
+ * manage domains, contacts, and templates via the Model Context Protocol.
7
+ *
8
+ * @module resend-mcp-server
9
+ * @version 1.0.0
10
+ * @license Apache-2.0
11
+ */
12
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
13
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
14
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
15
+ import { Resend } from "resend";
16
+ import { loadConfig } from "./config/environment.js";
17
+ import { configureRateLimiter } from "./services/rate-limiter.js";
18
+ import { initializeRegistry, loadTier, getEnabledTools, getToolExecutor, getRegistryStats, } from "./services/tool-registry.js";
19
+ import { createToolDefinitions } from "./tools/index.js";
20
+ import { createToolResponse, createValidationError } from "./utils/mcp-errors.js";
21
+ // NOTE: Use console.error for logging - stdout is reserved for MCP protocol
22
+ const log = (message) => console.error(`[resend-mcp] ${message}`);
23
+ // ============================================================================
24
+ // Server Setup
25
+ // ============================================================================
26
+ /**
27
+ * Create and configure the MCP server
28
+ */
29
+ function createServer(config) {
30
+ // Initialize Resend client only if API key is provided
31
+ const resend = config.hasApiKey ? new Resend(config.apiKey) : null;
32
+ // Configure rate limiter
33
+ configureRateLimiter({
34
+ intervalMs: config.rateLimitMs,
35
+ debug: config.debug,
36
+ });
37
+ const server = new Server({
38
+ name: "resend-mcp-server",
39
+ version: "1.0.0",
40
+ }, {
41
+ capabilities: {
42
+ tools: {
43
+ listChanged: true,
44
+ },
45
+ },
46
+ });
47
+ // Create tool definitions - pass resend client or null for docs-only mode
48
+ const allTools = createToolDefinitions(resend);
49
+ // Initialize the tool registry
50
+ initializeRegistry(server, allTools);
51
+ // Register tools/list handler - returns only enabled tools
52
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
53
+ const tools = getEnabledTools();
54
+ log(`Returning ${tools.length} enabled tools`);
55
+ return { tools };
56
+ });
57
+ // Register tools/call handler - executes enabled tools
58
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
59
+ const { name, arguments: args } = request.params;
60
+ log(`Tool called: ${name}`);
61
+ // Get executor for enabled tool
62
+ const executor = getToolExecutor(name);
63
+ if (!executor) {
64
+ // Check if tool exists but is disabled
65
+ const stats = getRegistryStats();
66
+ const isRegistered = stats.totalRegistered > 0;
67
+ if (isRegistered && !stats.enabledTools.includes(name)) {
68
+ return createToolResponse(createValidationError(`Tool '${name}' is not enabled in the current tier`, {
69
+ enabledTools: stats.enabledTools,
70
+ hint: "Use a higher tier to enable more tools",
71
+ }));
72
+ }
73
+ return createToolResponse(createValidationError(`Unknown tool: ${name}`, {
74
+ availableTools: stats.enabledTools,
75
+ }));
76
+ }
77
+ // Execute the tool
78
+ return executor(args);
79
+ });
80
+ return server;
81
+ }
82
+ // ============================================================================
83
+ // Main Entry Point
84
+ // ============================================================================
85
+ /**
86
+ * Main entry point
87
+ */
88
+ async function main() {
89
+ log("Starting Resend MCP Server v1.0.0");
90
+ // Load and validate configuration
91
+ let config;
92
+ try {
93
+ config = loadConfig();
94
+ log(`Configuration loaded (tier: ${config.defaultTier}, rate limit: ${config.rateLimitMs}ms)`);
95
+ }
96
+ catch (error) {
97
+ const message = error instanceof Error ? error.message : String(error);
98
+ log(`Configuration error: ${message}`);
99
+ process.exit(1);
100
+ }
101
+ // Create server
102
+ const server = createServer(config);
103
+ // Load tools for the configured tier
104
+ await loadTier(config.defaultTier);
105
+ // Log registry stats
106
+ const stats = getRegistryStats();
107
+ log(`Tools loaded: ${stats.totalEnabled}/${stats.totalRegistered} (tier: ${config.defaultTier})`);
108
+ log(`Enabled tools: ${stats.enabledTools.join(", ")}`);
109
+ // Connect via stdio transport
110
+ const transport = new StdioServerTransport();
111
+ await server.connect(transport);
112
+ log("Server connected and ready");
113
+ }
114
+ // Run the server
115
+ main().catch((error) => {
116
+ log(`Fatal error: ${error.message}`);
117
+ process.exit(1);
118
+ });
119
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Rate Limiter for Resend API
3
+ *
4
+ * Provides rate limiting with queue-based processing and exponential backoff retry
5
+ * to ensure compliance with Resend API rate limits.
6
+ *
7
+ * @module services/rate-limiter
8
+ */
9
+ /**
10
+ * Default minimum interval between API calls in milliseconds.
11
+ * Resend free tier allows 2 requests/second, so 500ms provides safety margin.
12
+ */
13
+ export declare const RATE_LIMIT_INTERVAL_MS = 500;
14
+ /**
15
+ * Default maximum number of retries for rate-limited requests.
16
+ */
17
+ export declare const DEFAULT_MAX_RETRIES = 3;
18
+ /**
19
+ * Configure the rate limiter settings.
20
+ *
21
+ * @param options - Configuration options
22
+ */
23
+ export declare function configureRateLimiter(options: {
24
+ intervalMs?: number;
25
+ debug?: boolean;
26
+ }): void;
27
+ /**
28
+ * Get the current rate limiter configuration.
29
+ *
30
+ * @returns Current configuration
31
+ */
32
+ export declare function getRateLimiterConfig(): {
33
+ intervalMs: number;
34
+ queueLength: number;
35
+ isProcessing: boolean;
36
+ };
37
+ /**
38
+ * Execute a function with rate limiting.
39
+ * Queues the function and processes it when the rate limit allows.
40
+ *
41
+ * @param fn - Async function to execute
42
+ * @returns Promise resolving to the function result
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const result = await withRateLimit(() => resendClient.emails.send(params));
47
+ * ```
48
+ */
49
+ export declare function withRateLimit<T>(fn: () => Promise<T>): Promise<T>;
50
+ /**
51
+ * Execute a function with automatic retry on rate limit errors.
52
+ * Uses exponential backoff with jitter.
53
+ *
54
+ * @param fn - Async function to execute
55
+ * @param maxRetries - Maximum number of retry attempts (default: 3)
56
+ * @returns Promise resolving to the function result
57
+ * @throws Error if all retries are exhausted
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const result = await withRetry(
62
+ * () => resendClient.emails.send(params),
63
+ * 3
64
+ * );
65
+ * ```
66
+ */
67
+ export declare function withRetry<T>(fn: () => Promise<T>, maxRetries?: number): Promise<T>;
68
+ /**
69
+ * Execute a function with both rate limiting and retry logic.
70
+ * This is the recommended function for most Resend API calls.
71
+ *
72
+ * @param fn - Async function to execute
73
+ * @param maxRetries - Maximum number of retry attempts (default: 3)
74
+ * @returns Promise resolving to the function result
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * const result = await withRateLimitAndRetry(
79
+ * () => resendClient.emails.send(params),
80
+ * 3
81
+ * );
82
+ * ```
83
+ */
84
+ export declare function withRateLimitAndRetry<T>(fn: () => Promise<T>, maxRetries?: number): Promise<T>;
85
+ /**
86
+ * Reset the rate limiter state.
87
+ * Useful for testing or reconfiguration.
88
+ */
89
+ export declare function resetRateLimiter(): void;
90
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/services/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH;;;GAGG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C;;GAEG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAkCrC;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,IAAI,CAQP;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB,CAMA;AAkDD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAQjE;AAiFD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,UAAU,GAAE,MAA4B,GACvC,OAAO,CAAC,CAAC,CAAC,CAiCZ;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,EAC3C,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,UAAU,GAAE,MAA4B,GACvC,OAAO,CAAC,CAAC,CAAC,CAEZ;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAOvC"}