email-validator-mcp 1.0.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/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # Email Validator MCP
2
+
3
+ Validate email addresses without sending mail. Checks the format, looks up the MX record, and flags disposable domains. No key required.
4
+
5
+ This file is self contained. It reads public data only and never writes to the machine. All output is bounded and honest about what could not be fetched.
6
+
7
+ ## Tools
8
+
9
+
10
+ * `validate_email` Validate a single email address.
11
+ * `validate_batch` Validate multiple addresses.
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ npm install
17
+ npm run build
18
+ node dist/index.js
19
+ ```
20
+
21
+ MX records are resolved through the DNS of the sending machine. A missing MX record does not guarantee an inbox does not exist, the result is honest about that.
package/dist/api.js ADDED
@@ -0,0 +1,49 @@
1
+ import { promises as dns } from "node:dns";
2
+ export class EmailError extends Error {
3
+ }
4
+ const DISPOSABLE = new Set([
5
+ "mailinator.com", "10minutemail.com", "guerrillamail.com", "sharklasers.com",
6
+ "yopmail.com", "tempmail.com", "throwawaymail.com", "maildrop.cc", "temp-mail.org",
7
+ "getnada.com", "dispostable.com", "mohmal.com", "emailondeck.com", "burnermail.io",
8
+ "trashmail.com", "spam4.me", "fakeinbox.com", "mailnesia.com", "mintemail.com",
9
+ ]);
10
+ async function checkOne(email) {
11
+ const parts = email.split("@");
12
+ const result = {
13
+ email,
14
+ format: parts.length !== 2 || !parts[0] || !/^[^\s@]+$/.test(parts[0]) ? "invalid" : "valid",
15
+ mx_hosts: [],
16
+ disposable: DISPOSABLE.has((parts[1] ?? "").toLowerCase()),
17
+ deliverable: "unknown",
18
+ };
19
+ if (result.format === "invalid") {
20
+ result.deliverable = "not checked";
21
+ return result;
22
+ }
23
+ try {
24
+ const hosts = await dns.resolveMx(parts[1]);
25
+ result.mx_hosts = hosts.sort((a, b) => a.priority - b.priority).map((h) => h.exchange);
26
+ result.deliverable = result.mx_hosts.length > 0 ? "likely" : "no MX record";
27
+ }
28
+ catch {
29
+ result.deliverable = "no MX record or domain not found";
30
+ }
31
+ return result;
32
+ }
33
+ function fmt(r) {
34
+ const flags = [r.format === "invalid" ? "INVALID FORMAT" : null, r.disposable ? "DISPOSABLE" : null].filter(Boolean);
35
+ return `${r.email}\n Format: ${r.format}\n MX: ${r.mx_hosts.slice(0, 5).join(", ") || "none"}\n Deliverable: ${r.deliverable}${flags.length ? ` | ${flags.join(" | ")}` : ""}`;
36
+ }
37
+ export async function validateEmail(args) {
38
+ const email = (args.email ?? "").trim();
39
+ if (!email)
40
+ throw new EmailError("Provide an email address");
41
+ return fmt(await checkOne(email));
42
+ }
43
+ export async function validateBatch(args) {
44
+ const list = (args.emails ?? "").split(",").map((e) => e.trim()).filter(Boolean);
45
+ if (list.length === 0)
46
+ throw new EmailError("Provide at least one email address");
47
+ const results = await Promise.all(list.slice(0, 25).map(checkOne));
48
+ return results.map(fmt).join("\n\n");
49
+ }
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+ import { createServer } from "./server.js";
3
+ const main = async () => { const server = createServer(); await server.connect(new StdioServerTransport()); };
4
+ main().catch((error) => { console.error("Fatal error:", error); process.exit(1); });
package/dist/server.js ADDED
@@ -0,0 +1,38 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import { validateBatch } from "./api.js";
4
+ import { validateEmail } from "./api.js";
5
+ const text = (value) => ({ content: [{ type: "text", text: value }] });
6
+ const textError = (t) => ({ content: [{ type: "text", text: t }], isError: true });
7
+ const READ_ONLY = { readOnlyHint: true, openWorldHint: true };
8
+ const error = (e) => `Error: ${e instanceof Error ? e.message : String(e)}`;
9
+ export function createServer() {
10
+ const server = new McpServer({ name: "email-validator-mcp", version: "1.0.0" });
11
+ server.registerTool("validate_email", {
12
+ title: "Validate email",
13
+ description: "Check an email address format, MX record, and disposable status.",
14
+ inputSchema: z.object({ email: z.string().describe("Email address to validate.") }),
15
+ annotations: READ_ONLY,
16
+ }, async (args) => {
17
+ try {
18
+ return text(await validateEmail(args));
19
+ }
20
+ catch (e) {
21
+ return textError(error(e));
22
+ }
23
+ });
24
+ server.registerTool("validate_batch", {
25
+ title: "Validate batch",
26
+ description: "Check a list of comma separated email addresses.",
27
+ inputSchema: z.object({ emails: z.string().describe("Comma separated email addresses.") }),
28
+ annotations: READ_ONLY,
29
+ }, async (args) => {
30
+ try {
31
+ return text(await validateBatch(args));
32
+ }
33
+ catch (e) {
34
+ return textError(error(e));
35
+ }
36
+ });
37
+ return server;
38
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "type": "module",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "https://github.com/mrfentmen/email-validator-mcp.git"
7
+ },
8
+ "bin": {
9
+ "email-validator-mcp": "./dist/index.js"
10
+ },
11
+ "main": "./dist/index.js",
12
+ "files": [
13
+ "dist",
14
+ "server.json",
15
+ "README.md"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc -p tsconfig.json",
19
+ "start": "node dist/index.js",
20
+ "dev": "npm run build && node dist/index.js"
21
+ },
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "@modelcontextprotocol/sdk": "^1.0.4",
25
+ "zod": "^3.23.8",
26
+ "pdf-lib": "^1.17.1",
27
+ "exceljs": "^4.4.0",
28
+ "qrcode": "^1.5.4",
29
+ "sharp": "^0.33.4"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^22.0.0",
33
+ "typescript": "^5.6.0"
34
+ },
35
+ "name": "email-validator-mcp",
36
+ "description": "Validate email addresses by format, MX record, and disposable domain. No key required.",
37
+ "mcpName": "io.github.mrfentmen/email-validator-mcp",
38
+ "keywords": [
39
+ "mcp",
40
+ "email",
41
+ "validator",
42
+ "mx",
43
+ "disposable"
44
+ ],
45
+ "engines": {
46
+ "node": ">=20"
47
+ }
48
+ }
package/server.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.mrfentmen/email-validator-mcp",
4
+ "description": "Validate email addresses by format, MX record, and disposable domain. No key required.",
5
+ "repository": {
6
+ "url": "https://github.com/mrfentmen/email-validator-mcp",
7
+ "source": "github"
8
+ },
9
+ "version": "1.0.0",
10
+ "packages": [
11
+ {
12
+ "registryType": "npm",
13
+ "identifier": "email-validator-mcp",
14
+ "version": "1.0.0",
15
+ "transport": {
16
+ "type": "stdio"
17
+ }
18
+ }
19
+ ]
20
+ }