@emailens/mcp 0.3.2 → 0.3.3

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/dist/index.js CHANGED
@@ -16,6 +16,11 @@ import {
16
16
  structuralWarnings,
17
17
  EMAIL_CLIENTS
18
18
  } from "@emailens/engine";
19
+ var toPlainText = null;
20
+ try {
21
+ ({ toPlainText } = await import("@emailens/engine"));
22
+ } catch {
23
+ }
19
24
  function toFramework(format) {
20
25
  if (format === "jsx" || format === "mjml" || format === "maizzle") return format;
21
26
  return void 0;
@@ -86,6 +91,7 @@ server.registerTool(
86
91
  0
87
92
  ) / scoreValues.length
88
93
  ) : 0;
94
+ const plainText = toPlainText ? toPlainText(html) : void 0;
89
95
  return {
90
96
  content: [
91
97
  {
@@ -103,6 +109,7 @@ server.registerTool(
103
109
  fix: w.fix,
104
110
  fixType: w.fixType
105
111
  })),
112
+ ...plainText ? { plainText } : {},
106
113
  clientCount: transforms.length,
107
114
  darkModeWarnings: Object.entries(darkMode).reduce(
108
115
  (acc, [clientId, dm]) => {
package/dist/index.js.map CHANGED
@@ -1 +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 generateFixPrompt,\r\n estimateAiFixTokens,\r\n auditEmail,\r\n structuralWarnings,\r\n EMAIL_CLIENTS,\r\n type Framework,\r\n type CSSWarning,\r\n type AuditReport,\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.3.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 fixType: w.fixType,\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: audit_email ───────────────────────────────────────────\r\nserver.registerTool(\r\n \"audit_email\",\r\n {\r\n title: \"Audit Email\",\r\n description:\r\n \"Run ALL email checks in one call: CSS compatibility, spam scoring, link validation, accessibility audit, and image analysis. Returns a unified report. Use --skip to omit specific checks.\",\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'.\"\r\n ),\r\n skip: z\r\n .array(z.enum([\"spam\", \"links\", \"accessibility\", \"images\", \"compatibility\"]))\r\n .optional()\r\n .describe(\r\n \"Array of checks to skip (e.g. ['spam', 'images']).\"\r\n ),\r\n },\r\n annotations: {\r\n title: \"Audit 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, skip }) => {\r\n const report = auditEmail(html, {\r\n framework: toFramework(format),\r\n skip,\r\n });\r\n\r\n const scoreValues = Object.values(report.compatibility.scores);\r\n const overallCompatibility =\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 overallCompatibility,\r\n compatibility: {\r\n scores: report.compatibility.scores,\r\n warningCount: report.compatibility.warnings.length,\r\n warnings: report.compatibility.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 fixType: w.fixType,\r\n })),\r\n },\r\n spam: report.spam,\r\n links: report.links,\r\n accessibility: report.accessibility,\r\n images: report.images,\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 \"CSS compatibility analysis with quality reports — returns warnings, per-client scores, plus spam, link, accessibility, and image analysis. For compatibility-only results, use skip. For full transforms + dark mode, use preview_email.\",\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 report = auditEmail(html, { framework: toFramework(format) });\r\n\r\n const scoreValues = Object.values(report.compatibility.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: report.compatibility.scores,\r\n warningCount: report.compatibility.warnings.length,\r\n warnings: report.compatibility.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 fixType: w.fixType,\r\n })),\r\n spam: report.spam,\r\n links: report.links,\r\n accessibility: report.accessibility,\r\n images: report.images,\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: fix_email ─────────────────────────────────────────────\r\nserver.registerTool(\r\n \"fix_email\",\r\n {\r\n title: \"Fix Email\",\r\n description:\r\n \"Generate a structured fix prompt for email compatibility issues. Returns a markdown prompt with the original code, all detected issues (with fix type: CSS or structural), fix snippets, and format-specific instructions. The AI assistant can then apply these fixes directly. Use after preview_email or analyze_email to fix the issues found.\",\r\n inputSchema: {\r\n html: z.string().describe(\"The email HTML source code to fix\"),\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'. Controls the fix syntax in the prompt.\"\r\n ),\r\n scope: z\r\n .enum([\"all\", \"current\"])\r\n .optional()\r\n .describe(\r\n \"Fix scope: 'all' (default) fixes for all clients, 'current' fixes for a single client (requires selectedClientId).\"\r\n ),\r\n selectedClientId: z\r\n .string()\r\n .optional()\r\n .describe(\r\n \"Client ID to scope fixes to (e.g. 'outlook-windows'). Only used when scope is 'current'.\"\r\n ),\r\n },\r\n annotations: {\r\n title: \"Fix 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, scope, selectedClientId }) => {\r\n const framework = toFramework(format);\r\n const fixScope = scope === \"current\" ? \"current\" : \"all\";\r\n const inputFormat = format || \"html\";\r\n\r\n const warnings = analyzeEmail(html, framework);\r\n const scores = generateCompatibilityScore(warnings);\r\n\r\n if (warnings.length === 0) {\r\n return {\r\n content: [\r\n {\r\n type: \"text\" as const,\r\n text: JSON.stringify(\r\n { message: \"No compatibility issues found — nothing to fix.\", overallScore: 100 },\r\n null,\r\n 2\r\n ),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n // Estimate tokens\r\n const estimate = await estimateAiFixTokens({\r\n originalHtml: html,\r\n warnings,\r\n scores,\r\n scope: fixScope,\r\n selectedClientId,\r\n format: inputFormat,\r\n });\r\n\r\n // Generate the fix prompt\r\n const prompt = generateFixPrompt({\r\n originalHtml: html,\r\n warnings,\r\n scores,\r\n scope: fixScope,\r\n selectedClientId,\r\n format: inputFormat,\r\n });\r\n\r\n const structural = structuralWarnings(warnings);\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 totalWarnings: warnings.length,\r\n structuralWarnings: structural.length,\r\n cssWarnings: warnings.length - structural.length,\r\n tokenEstimate: {\r\n inputTokens: estimate.inputTokens,\r\n estimatedOutputTokens: estimate.estimatedOutputTokens,\r\n truncated: estimate.truncated,\r\n },\r\n note: \"Apply the fixes in the prompt below to the email code. Structural issues require HTML restructuring (tables, VML conditionals), not just CSS changes.\",\r\n },\r\n null,\r\n 2\r\n ),\r\n },\r\n {\r\n type: \"text\" as const,\r\n text: prompt,\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":[]}
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 generateFixPrompt,\r\n estimateAiFixTokens,\r\n auditEmail,\r\n structuralWarnings,\r\n EMAIL_CLIENTS,\r\n type Framework,\r\n type CSSWarning,\r\n type AuditReport,\r\n} from \"@emailens/engine\";\r\n\r\n// toPlainText available in engine >=0.8.6\r\nlet toPlainText: ((html: string) => string) | null = null;\r\ntry {\r\n ({ toPlainText } = await import(\"@emailens/engine\"));\r\n} catch {\r\n // older engine version\r\n}\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.3.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 // Generate plain text version for multipart emails\r\n const plainText = toPlainText ? toPlainText(html) : undefined;\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 fixType: w.fixType,\r\n })),\r\n ...(plainText ? { plainText } : {}),\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: audit_email ───────────────────────────────────────────\r\nserver.registerTool(\r\n \"audit_email\",\r\n {\r\n title: \"Audit Email\",\r\n description:\r\n \"Run ALL email checks in one call: CSS compatibility, spam scoring, link validation, accessibility audit, and image analysis. Returns a unified report. Use --skip to omit specific checks.\",\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'.\"\r\n ),\r\n skip: z\r\n .array(z.enum([\"spam\", \"links\", \"accessibility\", \"images\", \"compatibility\"]))\r\n .optional()\r\n .describe(\r\n \"Array of checks to skip (e.g. ['spam', 'images']).\"\r\n ),\r\n },\r\n annotations: {\r\n title: \"Audit 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, skip }) => {\r\n const report = auditEmail(html, {\r\n framework: toFramework(format),\r\n skip,\r\n });\r\n\r\n const scoreValues = Object.values(report.compatibility.scores);\r\n const overallCompatibility =\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 overallCompatibility,\r\n compatibility: {\r\n scores: report.compatibility.scores,\r\n warningCount: report.compatibility.warnings.length,\r\n warnings: report.compatibility.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 fixType: w.fixType,\r\n })),\r\n },\r\n spam: report.spam,\r\n links: report.links,\r\n accessibility: report.accessibility,\r\n images: report.images,\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 \"CSS compatibility analysis with quality reports — returns warnings, per-client scores, plus spam, link, accessibility, and image analysis. For compatibility-only results, use skip. For full transforms + dark mode, use preview_email.\",\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 report = auditEmail(html, { framework: toFramework(format) });\r\n\r\n const scoreValues = Object.values(report.compatibility.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: report.compatibility.scores,\r\n warningCount: report.compatibility.warnings.length,\r\n warnings: report.compatibility.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 fixType: w.fixType,\r\n })),\r\n spam: report.spam,\r\n links: report.links,\r\n accessibility: report.accessibility,\r\n images: report.images,\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: fix_email ─────────────────────────────────────────────\r\nserver.registerTool(\r\n \"fix_email\",\r\n {\r\n title: \"Fix Email\",\r\n description:\r\n \"Generate a structured fix prompt for email compatibility issues. Returns a markdown prompt with the original code, all detected issues (with fix type: CSS or structural), fix snippets, and format-specific instructions. The AI assistant can then apply these fixes directly. Use after preview_email or analyze_email to fix the issues found.\",\r\n inputSchema: {\r\n html: z.string().describe(\"The email HTML source code to fix\"),\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'. Controls the fix syntax in the prompt.\"\r\n ),\r\n scope: z\r\n .enum([\"all\", \"current\"])\r\n .optional()\r\n .describe(\r\n \"Fix scope: 'all' (default) fixes for all clients, 'current' fixes for a single client (requires selectedClientId).\"\r\n ),\r\n selectedClientId: z\r\n .string()\r\n .optional()\r\n .describe(\r\n \"Client ID to scope fixes to (e.g. 'outlook-windows'). Only used when scope is 'current'.\"\r\n ),\r\n },\r\n annotations: {\r\n title: \"Fix 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, scope, selectedClientId }) => {\r\n const framework = toFramework(format);\r\n const fixScope = scope === \"current\" ? \"current\" : \"all\";\r\n const inputFormat = format || \"html\";\r\n\r\n const warnings = analyzeEmail(html, framework);\r\n const scores = generateCompatibilityScore(warnings);\r\n\r\n if (warnings.length === 0) {\r\n return {\r\n content: [\r\n {\r\n type: \"text\" as const,\r\n text: JSON.stringify(\r\n { message: \"No compatibility issues found — nothing to fix.\", overallScore: 100 },\r\n null,\r\n 2\r\n ),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n // Estimate tokens\r\n const estimate = await estimateAiFixTokens({\r\n originalHtml: html,\r\n warnings,\r\n scores,\r\n scope: fixScope,\r\n selectedClientId,\r\n format: inputFormat,\r\n });\r\n\r\n // Generate the fix prompt\r\n const prompt = generateFixPrompt({\r\n originalHtml: html,\r\n warnings,\r\n scores,\r\n scope: fixScope,\r\n selectedClientId,\r\n format: inputFormat,\r\n });\r\n\r\n const structural = structuralWarnings(warnings);\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 totalWarnings: warnings.length,\r\n structuralWarnings: structural.length,\r\n cssWarnings: warnings.length - structural.length,\r\n tokenEstimate: {\r\n inputTokens: estimate.inputTokens,\r\n estimatedOutputTokens: estimate.estimatedOutputTokens,\r\n truncated: estimate.truncated,\r\n },\r\n note: \"Apply the fixes in the prompt below to the email code. Structural issues require HTML restructuring (tables, VML conditionals), not just CSS changes.\",\r\n },\r\n null,\r\n 2\r\n ),\r\n },\r\n {\r\n type: \"text\" as const,\r\n text: prompt,\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":";;;;AACA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;AACrC,SAAS,SAAS;AAClB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP,IAAI,cAAiD;AACrD,IAAI;AACF,GAAC,EAAE,YAAY,IAAI,MAAM,OAAO,kBAAkB;AACpD,QAAQ;AAER;AAEA,SAAS,YAAY,QAAwC;AAC3D,MAAI,WAAW,SAAS,WAAW,UAAU,WAAW,UAAW,QAAO;AAC1E,SAAO;AACT;AAEA,IAAM,SAAS,IAAI,UAAU;AAAA,EAC3B,MAAM;AAAA,EACN,SAAS;AACX,CAAC;AAGD,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM,EAAE,OAAO,EAAE,SAAS,4BAA4B;AAAA,MACtD,SAAS,EACN,MAAM,EAAE,OAAO,CAAC,EAChB,SAAS,EACT;AAAA,QACC;AAAA,MACF;AAAA,MACF,QAAQ,EACL,KAAK,CAAC,QAAQ,OAAO,QAAQ,SAAS,CAAC,EACvC,SAAS,EACT;AAAA,QACC;AAAA,MACF;AAAA,IACJ;AAAA,IACA,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,EACF;AAAA,EACA,OAAO,EAAE,MAAM,SAAS,OAAO,MAAM;AACnC,UAAM,iBAAiB,IAAI,IAAI,cAAc,IAAI,CAAC,MAAsB,EAAE,EAAE,CAAC;AAE7E,QAAI,aAAa,uBAAuB,IAAI;AAC5C,QAAI,SAAS;AACX,YAAM,SAAS,QAAQ,OAAO,CAAC,MAAc,eAAe,IAAI,CAAC,CAAC;AAClE,UAAI,OAAO,WAAW,GAAG;AACvB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK;AAAA,gBACT;AAAA,kBACE,OAAO;AAAA,kBACP,gBAAgB,MAAM,KAAK,cAAc;AAAA,gBAC3C;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AACA,mBAAa,WAAW;AAAA,QAAO,CAAC,MAC9B,OAAO,SAAS,EAAE,QAAQ;AAAA,MAC5B;AAAA,IACF;AAEA,UAAM,WAAW,aAAa,MAAM,YAAY,MAAM,CAAC;AACvD,UAAM,SAAS,2BAA2B,QAAQ;AAElD,UAAM,WACJ,CAAC;AACH,eAAW,KAAK,YAAY;AAC1B,eAAS,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,EAAE,QAAQ;AAAA,IAC5D;AAEA,UAAM,cAAc,OAAO,OAAO,MAAM;AACxC,UAAM,eACJ,YAAY,SAAS,IACjB,KAAK;AAAA,MACH,YAAY;AAAA,QACV,CAAC,GAAW,MAAyB,IAAI,EAAE;AAAA,QAC3C;AAAA,MACF,IAAI,YAAY;AAAA,IAClB,IACA;AAGN,UAAM,YAAY,cAAc,YAAY,IAAI,IAAI;AAEpD,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,KAAK;AAAA,YACT;AAAA,cACE;AAAA,cACA,qBAAqB;AAAA,cACrB,aAAa,SAAS,IAAI,CAAC,OAAmB;AAAA,gBAC5C,QAAQ,EAAE;AAAA,gBACV,UAAU,EAAE;AAAA,gBACZ,UAAU,EAAE;AAAA,gBACZ,SAAS,EAAE;AAAA,gBACX,YAAY,EAAE;AAAA,gBACd,KAAK,EAAE;AAAA,gBACP,SAAS,EAAE;AAAA,cACb,EAAE;AAAA,cACF,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,cACjC,aAAa,WAAW;AAAA,cACxB,kBAAkB,OAAO,QAAQ,QAAQ,EAAE;AAAA,gBACzC,CACE,KACA,CAAC,UAAU,EAAE,MACV;AACH,sBAAI,GAAG,SAAS,SAAS,GAAG;AAC1B,wBAAI,QAAQ,IAAI,GAAG,SAAS;AAAA,kBAC9B;AACA,yBAAO;AAAA,gBACT;AAAA,gBACA,CAAC;AAAA,cACH;AAAA,YACF;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM,EAAE,OAAO,EAAE,SAAS,4BAA4B;AAAA,MACtD,QAAQ,EACL,KAAK,CAAC,QAAQ,OAAO,QAAQ,SAAS,CAAC,EACvC,SAAS,EACT;AAAA,QACC;AAAA,MACF;AAAA,MACF,MAAM,EACH,MAAM,EAAE,KAAK,CAAC,QAAQ,SAAS,iBAAiB,UAAU,eAAe,CAAC,CAAC,EAC3E,SAAS,EACT;AAAA,QACC;AAAA,MACF;AAAA,IACJ;AAAA,IACA,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,EACF;AAAA,EACA,OAAO,EAAE,MAAM,QAAQ,KAAK,MAAM;AAChC,UAAM,SAAS,WAAW,MAAM;AAAA,MAC9B,WAAW,YAAY,MAAM;AAAA,MAC7B;AAAA,IACF,CAAC;AAED,UAAM,cAAc,OAAO,OAAO,OAAO,cAAc,MAAM;AAC7D,UAAM,uBACJ,YAAY,SAAS,IACjB,KAAK;AAAA,MACH,YAAY;AAAA,QACV,CAAC,GAAW,MAAyB,IAAI,EAAE;AAAA,QAC3C;AAAA,MACF,IAAI,YAAY;AAAA,IAClB,IACA;AAEN,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,KAAK;AAAA,YACT;AAAA,cACE;AAAA,cACA,eAAe;AAAA,gBACb,QAAQ,OAAO,cAAc;AAAA,gBAC7B,cAAc,OAAO,cAAc,SAAS;AAAA,gBAC5C,UAAU,OAAO,cAAc,SAAS,IAAI,CAAC,OAAmB;AAAA,kBAC9D,QAAQ,EAAE;AAAA,kBACV,UAAU,EAAE;AAAA,kBACZ,UAAU,EAAE;AAAA,kBACZ,SAAS,EAAE;AAAA,kBACX,YAAY,EAAE;AAAA,kBACd,KAAK,EAAE;AAAA,kBACP,SAAS,EAAE;AAAA,gBACb,EAAE;AAAA,cACJ;AAAA,cACA,MAAM,OAAO;AAAA,cACb,OAAO,OAAO;AAAA,cACd,eAAe,OAAO;AAAA,cACtB,QAAQ,OAAO;AAAA,YACjB;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM,EAAE,OAAO,EAAE,SAAS,4BAA4B;AAAA,MACtD,QAAQ,EACL,KAAK,CAAC,QAAQ,OAAO,QAAQ,SAAS,CAAC,EACvC,SAAS,EACT;AAAA,QACC;AAAA,MACF;AAAA,IACJ;AAAA,IACA,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,EACF;AAAA,EACA,OAAO,EAAE,MAAM,OAAO,MAAM;AAC1B,UAAM,SAAS,WAAW,MAAM,EAAE,WAAW,YAAY,MAAM,EAAE,CAAC;AAElE,UAAM,cAAc,OAAO,OAAO,OAAO,cAAc,MAAM;AAC7D,UAAM,eACJ,YAAY,SAAS,IACjB,KAAK;AAAA,MACH,YAAY;AAAA,QACV,CAAC,GAAW,MAAyB,IAAI,EAAE;AAAA,QAC3C;AAAA,MACF,IAAI,YAAY;AAAA,IAClB,IACA;AAEN,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,KAAK;AAAA,YACT;AAAA,cACE;AAAA,cACA,QAAQ,OAAO,cAAc;AAAA,cAC7B,cAAc,OAAO,cAAc,SAAS;AAAA,cAC5C,UAAU,OAAO,cAAc,SAAS,IAAI,CAAC,OAAmB;AAAA,gBAC9D,QAAQ,EAAE;AAAA,gBACV,UAAU,EAAE;AAAA,gBACZ,UAAU,EAAE;AAAA,gBACZ,SAAS,EAAE;AAAA,gBACX,YAAY,EAAE;AAAA,gBACd,KAAK,EAAE;AAAA,gBACP,SAAS,EAAE;AAAA,cACb,EAAE;AAAA,cACF,MAAM,OAAO;AAAA,cACb,OAAO,OAAO;AAAA,cACd,eAAe,OAAO;AAAA,cACtB,QAAQ,OAAO;AAAA,YACjB;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM,EAAE,OAAO,EAAE,SAAS,mCAAmC;AAAA,MAC7D,QAAQ,EACL,KAAK,CAAC,QAAQ,OAAO,QAAQ,SAAS,CAAC,EACvC,SAAS,EACT;AAAA,QACC;AAAA,MACF;AAAA,MACF,OAAO,EACJ,KAAK,CAAC,OAAO,SAAS,CAAC,EACvB,SAAS,EACT;AAAA,QACC;AAAA,MACF;AAAA,MACF,kBAAkB,EACf,OAAO,EACP,SAAS,EACT;AAAA,QACC;AAAA,MACF;AAAA,IACJ;AAAA,IACA,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,EACF;AAAA,EACA,OAAO,EAAE,MAAM,QAAQ,OAAO,iBAAiB,MAAM;AACnD,UAAM,YAAY,YAAY,MAAM;AACpC,UAAM,WAAW,UAAU,YAAY,YAAY;AACnD,UAAM,cAAc,UAAU;AAE9B,UAAM,WAAW,aAAa,MAAM,SAAS;AAC7C,UAAM,SAAS,2BAA2B,QAAQ;AAElD,QAAI,SAAS,WAAW,GAAG;AACzB,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,SAAS,wDAAmD,cAAc,IAAI;AAAA,cAChF;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,WAAW,MAAM,oBAAoB;AAAA,MACzC,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA,QAAQ;AAAA,IACV,CAAC;AAGD,UAAM,SAAS,kBAAkB;AAAA,MAC/B,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA,QAAQ;AAAA,IACV,CAAC;AAED,UAAM,aAAa,mBAAmB,QAAQ;AAE9C,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,KAAK;AAAA,YACT;AAAA,cACE,eAAe,SAAS;AAAA,cACxB,oBAAoB,WAAW;AAAA,cAC/B,aAAa,SAAS,SAAS,WAAW;AAAA,cAC1C,eAAe;AAAA,gBACb,aAAa,SAAS;AAAA,gBACtB,uBAAuB,SAAS;AAAA,gBAChC,WAAW,SAAS;AAAA,cACtB;AAAA,cACA,MAAM;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa;AAAA,MACX,OAAO;AAAA,MACP,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,IACjB;AAAA,EACF;AAAA,EACA,YAAY;AACV,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,KAAK;AAAA,YACT,cAAc;AAAA,cACZ,CAAC,OAMM;AAAA,gBACL,IAAI,EAAE;AAAA,gBACN,MAAM,EAAE;AAAA,gBACR,UAAU,EAAE;AAAA,gBACZ,QAAQ,EAAE;AAAA,gBACV,iBAAiB,EAAE;AAAA,cACrB;AAAA,YACF;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,IAAM,YAAY,IAAI,qBAAqB;AAC3C,MAAM,OAAO,QAAQ,SAAS;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emailens/mcp",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "MCP server for email compatibility analysis — preview, analyze, fix, and list email clients via Claude or any MCP-compatible tool.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -26,7 +26,7 @@
26
26
  "prepublishOnly": "bun run build"
27
27
  },
28
28
  "dependencies": {
29
- "@emailens/engine": "^0.6.0",
29
+ "@emailens/engine": "^0.8.6",
30
30
  "@modelcontextprotocol/sdk": "^1.12.0",
31
31
  "zod": "^3.24.0"
32
32
  },