@emailens/mcp 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Emailens
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # @emailens/mcp
2
+
3
+ MCP (Model Context Protocol) server for email compatibility analysis. Enables Claude and other MCP-compatible AI assistants to preview, analyze, and score HTML emails across 12 email clients.
4
+
5
+ Built on top of [`@emailens/engine`](https://github.com/emailens/engine).
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g @emailens/mcp
11
+ # or
12
+ bunx @emailens/mcp
13
+ ```
14
+
15
+ ## Usage with Claude Desktop
16
+
17
+ Add to your Claude Desktop config (`claude_desktop_config.json`):
18
+
19
+ ```json
20
+ {
21
+ "mcpServers": {
22
+ "emailens": {
23
+ "command": "npx",
24
+ "args": ["-y", "@emailens/mcp"]
25
+ }
26
+ }
27
+ }
28
+ ```
29
+
30
+ Or if using Bun:
31
+
32
+ ```json
33
+ {
34
+ "mcpServers": {
35
+ "emailens": {
36
+ "command": "bunx",
37
+ "args": ["@emailens/mcp"]
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ ## Usage with Claude Code
44
+
45
+ Add to your Claude Code settings:
46
+
47
+ ```bash
48
+ claude mcp add emailens -- npx -y @emailens/mcp
49
+ ```
50
+
51
+ ## Tools
52
+
53
+ The server exposes three tools:
54
+
55
+ ### `preview_email`
56
+
57
+ Full email compatibility preview — transforms HTML per client, analyzes CSS, generates scores, and simulates dark mode.
58
+
59
+ **Parameters:**
60
+
61
+ | Name | Type | Required | Description |
62
+ |---|---|---|---|
63
+ | `html` | string | Yes | The email HTML source code |
64
+ | `clients` | string[] | No | Filter to specific client IDs (e.g. `["gmail_web", "outlook_windows"]`). Omit for all 12 clients. |
65
+ | `format` | enum | No | Input format: `"html"` (default), `"jsx"` (React Email), `"mjml"`, or `"maizzle"`. Controls which framework-specific fix snippets appear. |
66
+
67
+ **Returns:** JSON with `overallScore` (0–100), `compatibilityScores` (per-client), `cssWarnings` (with fix snippets), `clientCount`, and `darkModeWarnings`.
68
+
69
+ **Example prompt:**
70
+ > Analyze this email HTML and tell me what will break in Gmail and Outlook:
71
+ > ```html
72
+ > <div style="display: flex; gap: 16px; border-radius: 8px;">...</div>
73
+ > ```
74
+
75
+ ### `analyze_email`
76
+
77
+ Quick CSS compatibility analysis — returns warnings and per-client scores without full transforms. Faster than `preview_email` when you only need the compatibility report.
78
+
79
+ **Parameters:**
80
+
81
+ | Name | Type | Required | Description |
82
+ |---|---|---|---|
83
+ | `html` | string | Yes | The email HTML source code |
84
+ | `format` | enum | No | Input format: `"html"`, `"jsx"`, `"mjml"`, or `"maizzle"` |
85
+
86
+ **Returns:** JSON with `overallScore`, `scores` (per-client), `warningCount`, and `warnings` (with severity, message, and fix).
87
+
88
+ **Example prompt:**
89
+ > What's the compatibility score for this React Email template?
90
+
91
+ ### `list_clients`
92
+
93
+ Lists all 12 supported email client IDs and display names. Useful for discovering valid client IDs to pass to `preview_email`.
94
+
95
+ **Parameters:** None
96
+
97
+ **Returns:** JSON array of `{ id, name }` objects.
98
+
99
+ **Example prompt:**
100
+ > What email clients does Emailens support?
101
+
102
+ ## Supported Email Clients
103
+
104
+ | Client | ID | Dark Mode |
105
+ |---|---|---|
106
+ | Gmail | `gmail-web` | Yes |
107
+ | Gmail Android | `gmail-android` | Yes |
108
+ | Gmail iOS | `gmail-ios` | Yes |
109
+ | Outlook 365 | `outlook-web` | Yes |
110
+ | Outlook Windows | `outlook-windows` | No |
111
+ | Apple Mail | `apple-mail-macos` | Yes |
112
+ | Apple Mail iOS | `apple-mail-ios` | Yes |
113
+ | Yahoo Mail | `yahoo-mail` | Yes |
114
+ | Samsung Mail | `samsung-mail` | Yes |
115
+ | Thunderbird | `thunderbird` | No |
116
+ | HEY Mail | `hey-mail` | Yes |
117
+ | Superhuman | `superhuman` | Yes |
118
+
119
+ ## Framework-Aware Fixes
120
+
121
+ When you specify a `format`, the fix snippets in warnings are tailored to your framework:
122
+
123
+ - **`jsx`** — References React Email components (`Row`, `Column`, `Font`, `Container` from `@react-email/components`)
124
+ - **`mjml`** — References MJML elements (`mj-section`, `mj-column`, `mj-font`, `mj-style`)
125
+ - **`maizzle`** — References Tailwind CSS classes and Maizzle config (`googleFonts`, MSO conditionals)
126
+ - **`html`** (default) — Generic HTML with VML fallbacks for Outlook
127
+
128
+ ## How It Works
129
+
130
+ The MCP server is a thin wrapper around `@emailens/engine`. For each tool call, it:
131
+
132
+ 1. Validates inputs with Zod schemas
133
+ 2. Calls engine functions (`transformForAllClients`, `analyzeEmail`, `generateCompatibilityScore`, `simulateDarkMode`)
134
+ 3. Formats and returns JSON results via stdio transport
135
+
136
+ The engine uses [Cheerio](https://cheerio.js.org/) for HTML manipulation and [css-tree](https://github.com/csstree/csstree) for CSS parsing. No external API calls — all analysis runs locally.
137
+
138
+ ## Development
139
+
140
+ ```bash
141
+ # Install dependencies
142
+ bun install
143
+
144
+ # Build
145
+ bun run build
146
+
147
+ # Run locally
148
+ bun run src/index.ts
149
+
150
+ # Type check
151
+ bun run typecheck
152
+ ```
153
+
154
+ ## License
155
+
156
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,213 @@
1
+ #!/usr/bin/env node
2
+ #!/usr/bin/env node
3
+
4
+ // src/index.ts
5
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
+ import { z } from "zod";
8
+ import {
9
+ transformForAllClients,
10
+ analyzeEmail,
11
+ generateCompatibilityScore,
12
+ simulateDarkMode,
13
+ EMAIL_CLIENTS
14
+ } from "@emailens/engine";
15
+ function toFramework(format) {
16
+ if (format === "jsx" || format === "mjml" || format === "maizzle") return format;
17
+ return void 0;
18
+ }
19
+ var server = new McpServer({
20
+ name: "emailens",
21
+ version: "0.1.0"
22
+ });
23
+ server.registerTool(
24
+ "preview_email",
25
+ {
26
+ title: "Preview Email",
27
+ description: "Analyze an HTML email and see how it renders across 12 email clients (Gmail, Outlook, Apple Mail, Yahoo, Samsung, Thunderbird, HEY, Superhuman). Returns CSS transforms, compatibility warnings with fix snippets, dark mode simulation, and per-client scores.",
28
+ inputSchema: {
29
+ html: z.string().describe("The email HTML source code"),
30
+ clients: z.array(z.string()).optional().describe(
31
+ "Optional array of client IDs to filter (e.g. ['gmail-web', 'outlook-windows']). Omit for all clients."
32
+ ),
33
+ format: z.enum(["html", "jsx", "mjml", "maizzle"]).optional().describe(
34
+ "Input format of the email source: 'html' (default), 'jsx' (React Email), 'mjml', or 'maizzle'. Controls which framework-specific fix snippets appear in the warnings."
35
+ )
36
+ },
37
+ annotations: {
38
+ title: "Preview Email",
39
+ readOnlyHint: true,
40
+ destructiveHint: false,
41
+ idempotentHint: true,
42
+ openWorldHint: false
43
+ }
44
+ },
45
+ async ({ html, clients, format }) => {
46
+ const validClientIds = new Set(EMAIL_CLIENTS.map((c) => c.id));
47
+ let transforms = transformForAllClients(html);
48
+ if (clients) {
49
+ const filter = clients.filter((c) => validClientIds.has(c));
50
+ if (filter.length === 0) {
51
+ return {
52
+ content: [
53
+ {
54
+ type: "text",
55
+ text: JSON.stringify(
56
+ {
57
+ error: "No valid client IDs provided",
58
+ validClientIds: Array.from(validClientIds)
59
+ },
60
+ null,
61
+ 2
62
+ )
63
+ }
64
+ ],
65
+ isError: true
66
+ };
67
+ }
68
+ transforms = transforms.filter(
69
+ (t) => filter.includes(t.clientId)
70
+ );
71
+ }
72
+ const warnings = analyzeEmail(html, toFramework(format));
73
+ const scores = generateCompatibilityScore(warnings);
74
+ const darkMode = {};
75
+ for (const t of transforms) {
76
+ darkMode[t.clientId] = simulateDarkMode(t.html, t.clientId);
77
+ }
78
+ const scoreValues = Object.values(scores);
79
+ const overallScore = scoreValues.length > 0 ? Math.round(
80
+ scoreValues.reduce(
81
+ (a, b) => a + b.score,
82
+ 0
83
+ ) / scoreValues.length
84
+ ) : 0;
85
+ return {
86
+ content: [
87
+ {
88
+ type: "text",
89
+ text: JSON.stringify(
90
+ {
91
+ overallScore,
92
+ compatibilityScores: scores,
93
+ cssWarnings: warnings.map((w) => ({
94
+ client: w.client,
95
+ property: w.property,
96
+ severity: w.severity,
97
+ message: w.message,
98
+ suggestion: w.suggestion,
99
+ fix: w.fix
100
+ })),
101
+ clientCount: transforms.length,
102
+ darkModeWarnings: Object.entries(darkMode).reduce(
103
+ (acc, [clientId, dm]) => {
104
+ if (dm.warnings.length > 0) {
105
+ acc[clientId] = dm.warnings.length;
106
+ }
107
+ return acc;
108
+ },
109
+ {}
110
+ )
111
+ },
112
+ null,
113
+ 2
114
+ )
115
+ }
116
+ ]
117
+ };
118
+ }
119
+ );
120
+ server.registerTool(
121
+ "analyze_email",
122
+ {
123
+ title: "Analyze Email",
124
+ description: "Quick CSS compatibility analysis \u2014 returns warnings and per-client scores without full transforms. Faster than preview_email when you only need the compatibility report.",
125
+ inputSchema: {
126
+ html: z.string().describe("The email HTML source code"),
127
+ format: z.enum(["html", "jsx", "mjml", "maizzle"]).optional().describe(
128
+ "Input format: 'html' (default), 'jsx' (React Email), 'mjml', or 'maizzle'. Determines which framework-specific fix snippets are returned."
129
+ )
130
+ },
131
+ annotations: {
132
+ title: "Analyze Email",
133
+ readOnlyHint: true,
134
+ destructiveHint: false,
135
+ idempotentHint: true,
136
+ openWorldHint: false
137
+ }
138
+ },
139
+ async ({ html, format }) => {
140
+ const warnings = analyzeEmail(html, toFramework(format));
141
+ const scores = generateCompatibilityScore(warnings);
142
+ const scoreValues = Object.values(scores);
143
+ const overallScore = scoreValues.length > 0 ? Math.round(
144
+ scoreValues.reduce(
145
+ (a, b) => a + b.score,
146
+ 0
147
+ ) / scoreValues.length
148
+ ) : 0;
149
+ return {
150
+ content: [
151
+ {
152
+ type: "text",
153
+ text: JSON.stringify(
154
+ {
155
+ overallScore,
156
+ scores,
157
+ warningCount: warnings.length,
158
+ warnings: warnings.map((w) => ({
159
+ client: w.client,
160
+ property: w.property,
161
+ severity: w.severity,
162
+ message: w.message,
163
+ suggestion: w.suggestion,
164
+ fix: w.fix
165
+ }))
166
+ },
167
+ null,
168
+ 2
169
+ )
170
+ }
171
+ ]
172
+ };
173
+ }
174
+ );
175
+ server.registerTool(
176
+ "list_clients",
177
+ {
178
+ title: "List Email Clients",
179
+ description: "List all 12 supported email client IDs, display names, categories, rendering engines, and dark mode support.",
180
+ annotations: {
181
+ title: "List Email Clients",
182
+ readOnlyHint: true,
183
+ destructiveHint: false,
184
+ idempotentHint: true,
185
+ openWorldHint: false
186
+ }
187
+ },
188
+ async () => {
189
+ return {
190
+ content: [
191
+ {
192
+ type: "text",
193
+ text: JSON.stringify(
194
+ EMAIL_CLIENTS.map(
195
+ (c) => ({
196
+ id: c.id,
197
+ name: c.name,
198
+ category: c.category,
199
+ engine: c.engine,
200
+ darkModeSupport: c.darkModeSupport
201
+ })
202
+ ),
203
+ null,
204
+ 2
205
+ )
206
+ }
207
+ ]
208
+ };
209
+ }
210
+ );
211
+ var transport = new StdioServerTransport();
212
+ await server.connect(transport);
213
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\r\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\r\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\r\nimport { z } from \"zod\";\r\nimport {\r\n transformForAllClients,\r\n analyzeEmail,\r\n generateCompatibilityScore,\r\n simulateDarkMode,\r\n EMAIL_CLIENTS,\r\n type Framework,\r\n type CSSWarning,\r\n} from \"@emailens/engine\";\r\n\r\nfunction toFramework(format?: string): Framework | undefined {\r\n if (format === \"jsx\" || format === \"mjml\" || format === \"maizzle\") return format;\r\n return undefined;\r\n}\r\n\r\nconst server = new McpServer({\r\n name: \"emailens\",\r\n version: \"0.1.0\",\r\n});\r\n\r\n// ── Tool: preview_email ─────────────────────────────────────────\r\nserver.registerTool(\r\n \"preview_email\",\r\n {\r\n title: \"Preview Email\",\r\n description:\r\n \"Analyze an HTML email and see how it renders across 12 email clients (Gmail, Outlook, Apple Mail, Yahoo, Samsung, Thunderbird, HEY, Superhuman). Returns CSS transforms, compatibility warnings with fix snippets, dark mode simulation, and per-client scores.\",\r\n inputSchema: {\r\n html: z.string().describe(\"The email HTML source code\"),\r\n clients: z\r\n .array(z.string())\r\n .optional()\r\n .describe(\r\n \"Optional array of client IDs to filter (e.g. ['gmail-web', 'outlook-windows']). Omit for all clients.\"\r\n ),\r\n format: z\r\n .enum([\"html\", \"jsx\", \"mjml\", \"maizzle\"])\r\n .optional()\r\n .describe(\r\n \"Input format of the email source: 'html' (default), 'jsx' (React Email), 'mjml', or 'maizzle'. Controls which framework-specific fix snippets appear in the warnings.\"\r\n ),\r\n },\r\n annotations: {\r\n title: \"Preview Email\",\r\n readOnlyHint: true,\r\n destructiveHint: false,\r\n idempotentHint: true,\r\n openWorldHint: false,\r\n },\r\n },\r\n async ({ html, clients, format }) => {\r\n const validClientIds = new Set(EMAIL_CLIENTS.map((c: { id: string }) => c.id));\r\n\r\n let transforms = transformForAllClients(html);\r\n if (clients) {\r\n const filter = clients.filter((c: string) => validClientIds.has(c));\r\n if (filter.length === 0) {\r\n return {\r\n content: [\r\n {\r\n type: \"text\" as const,\r\n text: JSON.stringify(\r\n {\r\n error: \"No valid client IDs provided\",\r\n validClientIds: Array.from(validClientIds),\r\n },\r\n null,\r\n 2\r\n ),\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n transforms = transforms.filter((t: { clientId: string }) =>\r\n filter.includes(t.clientId)\r\n );\r\n }\r\n\r\n const warnings = analyzeEmail(html, toFramework(format));\r\n const scores = generateCompatibilityScore(warnings);\r\n\r\n const darkMode: Record<string, { html: string; warnings: CSSWarning[] }> =\r\n {};\r\n for (const t of transforms) {\r\n darkMode[t.clientId] = simulateDarkMode(t.html, t.clientId);\r\n }\r\n\r\n const scoreValues = Object.values(scores);\r\n const overallScore =\r\n scoreValues.length > 0\r\n ? Math.round(\r\n scoreValues.reduce(\r\n (a: number, b: { score: number }) => a + b.score,\r\n 0\r\n ) / scoreValues.length\r\n )\r\n : 0;\r\n\r\n return {\r\n content: [\r\n {\r\n type: \"text\" as const,\r\n text: JSON.stringify(\r\n {\r\n overallScore,\r\n compatibilityScores: scores,\r\n cssWarnings: warnings.map((w: CSSWarning) => ({\r\n client: w.client,\r\n property: w.property,\r\n severity: w.severity,\r\n message: w.message,\r\n suggestion: w.suggestion,\r\n fix: w.fix,\r\n })),\r\n clientCount: transforms.length,\r\n darkModeWarnings: Object.entries(darkMode).reduce(\r\n (\r\n acc: Record<string, number>,\r\n [clientId, dm]: [string, { warnings: CSSWarning[] }]\r\n ) => {\r\n if (dm.warnings.length > 0) {\r\n acc[clientId] = dm.warnings.length;\r\n }\r\n return acc;\r\n },\r\n {}\r\n ),\r\n },\r\n null,\r\n 2\r\n ),\r\n },\r\n ],\r\n };\r\n }\r\n);\r\n\r\n// ── Tool: analyze_email ─────────────────────────────────────────\r\nserver.registerTool(\r\n \"analyze_email\",\r\n {\r\n title: \"Analyze Email\",\r\n description:\r\n \"Quick CSS compatibility analysis — returns warnings and per-client scores without full transforms. Faster than preview_email when you only need the compatibility report.\",\r\n inputSchema: {\r\n html: z.string().describe(\"The email HTML source code\"),\r\n format: z\r\n .enum([\"html\", \"jsx\", \"mjml\", \"maizzle\"])\r\n .optional()\r\n .describe(\r\n \"Input format: 'html' (default), 'jsx' (React Email), 'mjml', or 'maizzle'. Determines which framework-specific fix snippets are returned.\"\r\n ),\r\n },\r\n annotations: {\r\n title: \"Analyze Email\",\r\n readOnlyHint: true,\r\n destructiveHint: false,\r\n idempotentHint: true,\r\n openWorldHint: false,\r\n },\r\n },\r\n async ({ html, format }) => {\r\n const warnings = analyzeEmail(html, toFramework(format));\r\n const scores = generateCompatibilityScore(warnings);\r\n\r\n const scoreValues = Object.values(scores);\r\n const overallScore =\r\n scoreValues.length > 0\r\n ? Math.round(\r\n scoreValues.reduce(\r\n (a: number, b: { score: number }) => a + b.score,\r\n 0\r\n ) / scoreValues.length\r\n )\r\n : 0;\r\n\r\n return {\r\n content: [\r\n {\r\n type: \"text\" as const,\r\n text: JSON.stringify(\r\n {\r\n overallScore,\r\n scores,\r\n warningCount: warnings.length,\r\n warnings: warnings.map((w: CSSWarning) => ({\r\n client: w.client,\r\n property: w.property,\r\n severity: w.severity,\r\n message: w.message,\r\n suggestion: w.suggestion,\r\n fix: w.fix,\r\n })),\r\n },\r\n null,\r\n 2\r\n ),\r\n },\r\n ],\r\n };\r\n }\r\n);\r\n\r\n// ── Tool: list_clients ──────────────────────────────────────────\r\nserver.registerTool(\r\n \"list_clients\",\r\n {\r\n title: \"List Email Clients\",\r\n description:\r\n \"List all 12 supported email client IDs, display names, categories, rendering engines, and dark mode support.\",\r\n annotations: {\r\n title: \"List Email Clients\",\r\n readOnlyHint: true,\r\n destructiveHint: false,\r\n idempotentHint: true,\r\n openWorldHint: false,\r\n },\r\n },\r\n async () => {\r\n return {\r\n content: [\r\n {\r\n type: \"text\" as const,\r\n text: JSON.stringify(\r\n EMAIL_CLIENTS.map(\r\n (c: {\r\n id: string;\r\n name: string;\r\n category: string;\r\n engine: string;\r\n darkModeSupport: boolean;\r\n }) => ({\r\n id: c.id,\r\n name: c.name,\r\n category: c.category,\r\n engine: c.engine,\r\n darkModeSupport: c.darkModeSupport,\r\n })\r\n ),\r\n null,\r\n 2\r\n ),\r\n },\r\n ],\r\n };\r\n }\r\n);\r\n\r\n// ── Start ────────────────────────────────────────────────────────\r\nconst transport = new StdioServerTransport();\r\nawait server.connect(transport);\r\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@emailens/mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for email compatibility analysis — preview, analyze, and list email clients via Claude or any MCP-compatible tool.",
5
+ "type": "module",
6
+ "bin": {
7
+ "emailens-mcp": "./dist/index.js"
8
+ },
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "main": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "files": [
18
+ "dist",
19
+ "LICENSE"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsup",
23
+ "dev": "tsup --watch",
24
+ "start": "bun run dist/index.js",
25
+ "typecheck": "tsc --noEmit",
26
+ "prepublishOnly": "bun run build"
27
+ },
28
+ "dependencies": {
29
+ "@emailens/engine": "^0.1.0",
30
+ "@modelcontextprotocol/sdk": "^1.12.0",
31
+ "zod": "^3.24.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^25.3.0",
35
+ "bun-types": "^1.3.9",
36
+ "tsup": "^8.4.0",
37
+ "typescript": "^5.9.3"
38
+ },
39
+ "keywords": [
40
+ "mcp",
41
+ "model-context-protocol",
42
+ "email",
43
+ "email-testing",
44
+ "compatibility",
45
+ "claude"
46
+ ],
47
+ "license": "MIT",
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/emailens/mcp.git"
51
+ },
52
+ "homepage": "https://github.com/emailens/mcp#readme",
53
+ "bugs": {
54
+ "url": "https://github.com/emailens/mcp/issues"
55
+ }
56
+ }