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.
- package/LICENSE +190 -0
- package/README.md +257 -0
- package/data/embeddings.json +245241 -0
- package/dist/config/environment.d.ts +152 -0
- package/dist/config/environment.d.ts.map +1 -0
- package/dist/config/environment.js +217 -0
- package/dist/config/environment.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +119 -0
- package/dist/index.js.map +1 -0
- package/dist/services/rate-limiter.d.ts +90 -0
- package/dist/services/rate-limiter.d.ts.map +1 -0
- package/dist/services/rate-limiter.js +267 -0
- package/dist/services/rate-limiter.js.map +1 -0
- package/dist/services/tool-registry.d.ts +219 -0
- package/dist/services/tool-registry.d.ts.map +1 -0
- package/dist/services/tool-registry.js +459 -0
- package/dist/services/tool-registry.js.map +1 -0
- package/dist/tools/docs/embeddings-loader.d.ts +69 -0
- package/dist/tools/docs/embeddings-loader.d.ts.map +1 -0
- package/dist/tools/docs/embeddings-loader.js +218 -0
- package/dist/tools/docs/embeddings-loader.js.map +1 -0
- package/dist/tools/docs/errors.d.ts +75 -0
- package/dist/tools/docs/errors.d.ts.map +1 -0
- package/dist/tools/docs/errors.js +145 -0
- package/dist/tools/docs/errors.js.map +1 -0
- package/dist/tools/docs/index.d.ts +11 -0
- package/dist/tools/docs/index.d.ts.map +1 -0
- package/dist/tools/docs/index.js +14 -0
- package/dist/tools/docs/index.js.map +1 -0
- package/dist/tools/docs/metrics.d.ts +94 -0
- package/dist/tools/docs/metrics.d.ts.map +1 -0
- package/dist/tools/docs/metrics.js +174 -0
- package/dist/tools/docs/metrics.js.map +1 -0
- package/dist/tools/docs/search-docs-tool.d.ts +54 -0
- package/dist/tools/docs/search-docs-tool.d.ts.map +1 -0
- package/dist/tools/docs/search-docs-tool.js +231 -0
- package/dist/tools/docs/search-docs-tool.js.map +1 -0
- package/dist/tools/docs/types.d.ts +70 -0
- package/dist/tools/docs/types.d.ts.map +1 -0
- package/dist/tools/docs/types.js +7 -0
- package/dist/tools/docs/types.js.map +1 -0
- package/dist/tools/docs/vector-search.d.ts +80 -0
- package/dist/tools/docs/vector-search.d.ts.map +1 -0
- package/dist/tools/docs/vector-search.js +297 -0
- package/dist/tools/docs/vector-search.js.map +1 -0
- package/dist/tools/index.d.ts +27 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +3413 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/utils/mcp-errors.d.ts +109 -0
- package/dist/utils/mcp-errors.d.ts.map +1 -0
- package/dist/utils/mcp-errors.js +306 -0
- package/dist/utils/mcp-errors.js.map +1 -0
- 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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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|