@datapad-nl/vouch-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 +21 -0
- package/README.md +85 -0
- package/dist/index.js +115 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Datapad
|
|
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,85 @@
|
|
|
1
|
+
# @datapad-nl/vouch-mcp
|
|
2
|
+
|
|
3
|
+
An [MCP](https://modelcontextprotocol.io) server for **[Vouch](https://vouch.fast)** email
|
|
4
|
+
verification. It gives your AI assistant (Claude, Cursor, Cline, …) a `verify_email` tool that checks
|
|
5
|
+
whether an email address is really deliverable — syntax, MX records, a live SMTP probe, and catch-all
|
|
6
|
+
detection — and returns a verdict, a 0–100 confidence score, and quality flags.
|
|
7
|
+
|
|
8
|
+
## Prerequisites
|
|
9
|
+
|
|
10
|
+
- A Vouch API key (`vch_live_…`) — get one from the [dashboard](https://vouch.fast/dashboard).
|
|
11
|
+
- Node.js ≥ 18 (provides `npx`).
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
Add the server to your MCP client's config. There is nothing to install ahead of time — `npx` fetches
|
|
16
|
+
the package on first run.
|
|
17
|
+
|
|
18
|
+
**Claude Desktop, Claude Code, Cline, Windsurf, and most clients** (`.mcp.json` /
|
|
19
|
+
`claude_desktop_config.json`):
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"vouch": {
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": ["-y", "@datapad-nl/vouch-mcp"],
|
|
27
|
+
"env": { "VOUCH_API_KEY": "vch_live_your_key_here" }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Claude Code (CLI):**
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
claude mcp add vouch --env VOUCH_API_KEY=vch_live_your_key_here -- npx -y @datapad-nl/vouch-mcp
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Cursor:** Settings → MCP → *Add new server*, then use the same `command`, `args`, and `env` as above.
|
|
40
|
+
|
|
41
|
+
## The tool
|
|
42
|
+
|
|
43
|
+
**`verify_email`** — input `{ "email": "jane@example.com" }`. Returns a one-line summary plus the full
|
|
44
|
+
JSON verdict:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"email": "jane@example.com",
|
|
49
|
+
"user": "jane",
|
|
50
|
+
"domain": "example.com",
|
|
51
|
+
"status": "deliverable",
|
|
52
|
+
"reason": "mailbox_exists",
|
|
53
|
+
"score": 95,
|
|
54
|
+
"checks": { "syntax": true, "domainHasMx": true, "smtpConnected": true, "mailboxExists": true, "catchAll": false },
|
|
55
|
+
"flags": { "disposable": false, "roleAccount": false, "freeProvider": false },
|
|
56
|
+
"didYouMean": null,
|
|
57
|
+
"mxHost": "aspmx.l.google.com",
|
|
58
|
+
"meta": { "durationMs": 412, "checkedAt": "2026-06-11T13:28:23.957Z" }
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
- **status** — `deliverable` · `undeliverable` · `risky` · `unknown`
|
|
63
|
+
- **score** — 0–100 confidence
|
|
64
|
+
- **flags** — `disposable`, `roleAccount`, `freeProvider`
|
|
65
|
+
- **didYouMean** — a corrected address when a likely typo is detected (e.g. `jane@gmial.com` →
|
|
66
|
+
`jane@gmail.com`)
|
|
67
|
+
|
|
68
|
+
Ask your assistant something like *"Is jane@exmaple.com a real address?"* and it will call `verify_email`
|
|
69
|
+
and report back the verdict and any typo suggestion.
|
|
70
|
+
|
|
71
|
+
## Configuration
|
|
72
|
+
|
|
73
|
+
| Env var | Required | Default | Description |
|
|
74
|
+
| ---------------- | -------- | --------------------------- | ------------------------------------ |
|
|
75
|
+
| `VOUCH_API_KEY` | yes | — | Your `vch_live_…` key. |
|
|
76
|
+
| `VOUCH_API_URL` | no | `https://vouch.fast` | Override the API base URL. |
|
|
77
|
+
|
|
78
|
+
## Privacy
|
|
79
|
+
|
|
80
|
+
The server runs locally on your machine. Your API key and the address you verify are sent only to the
|
|
81
|
+
Vouch API over HTTPS — nothing is transmitted or stored by this package itself.
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
MIT
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Vouch MCP server (stdio transport).
|
|
4
|
+
*
|
|
5
|
+
* Exposes one tool — `verify_email` — that calls the hosted Vouch API
|
|
6
|
+
* (GET /v1/verify) with the customer's API key and returns the deliverability
|
|
7
|
+
* verdict. The key stays on the customer's machine; it is sent only as a Bearer
|
|
8
|
+
* token to the Vouch API over HTTPS.
|
|
9
|
+
*
|
|
10
|
+
* Environment:
|
|
11
|
+
* VOUCH_API_KEY (required) your vch_live_… key — https://vouch.fast/dashboard
|
|
12
|
+
* VOUCH_API_URL (optional) API base URL, default https://vouch.fast
|
|
13
|
+
*/
|
|
14
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
const VERSION = "0.1.0";
|
|
18
|
+
const DEFAULT_API_URL = "https://vouch.fast";
|
|
19
|
+
// SMTP probes can take several seconds; allow margin over the API's ~8s budget.
|
|
20
|
+
const REQUEST_TIMEOUT_MS = 20_000;
|
|
21
|
+
function apiBase() {
|
|
22
|
+
const raw = process.env.VOUCH_API_URL?.trim() || DEFAULT_API_URL;
|
|
23
|
+
return raw.replace(/\/+$/, "");
|
|
24
|
+
}
|
|
25
|
+
function errorResult(message) {
|
|
26
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
27
|
+
}
|
|
28
|
+
function formatSummary(r) {
|
|
29
|
+
const flags = (r.flags ?? {});
|
|
30
|
+
const tags = Object.keys(flags).filter((k) => flags[k]);
|
|
31
|
+
const flagStr = tags.length ? ` [${tags.join(", ")}]` : "";
|
|
32
|
+
const score = typeof r.score === "number" ? `${r.score}/100` : "n/a";
|
|
33
|
+
const reason = r.reason ? ` (${String(r.reason)})` : "";
|
|
34
|
+
const dym = r.didYouMean ? ` — did you mean ${String(r.didYouMean)}?` : "";
|
|
35
|
+
return `${String(r.email ?? "email")} → ${String(r.status ?? "unknown")}${reason}, score ${score}${flagStr}${dym}`;
|
|
36
|
+
}
|
|
37
|
+
async function verifyEmail(email) {
|
|
38
|
+
const key = process.env.VOUCH_API_KEY?.trim();
|
|
39
|
+
if (!key) {
|
|
40
|
+
return errorResult("VOUCH_API_KEY is not set. Add your Vouch API key (vch_live_…) to this server's " +
|
|
41
|
+
"environment. Get one from the dashboard at https://vouch.fast/dashboard.");
|
|
42
|
+
}
|
|
43
|
+
const url = `${apiBase()}/v1/verify?email=${encodeURIComponent(email)}`;
|
|
44
|
+
const controller = new AbortController();
|
|
45
|
+
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
46
|
+
let res;
|
|
47
|
+
try {
|
|
48
|
+
res = await fetch(url, {
|
|
49
|
+
headers: {
|
|
50
|
+
Authorization: `Bearer ${key}`,
|
|
51
|
+
Accept: "application/json",
|
|
52
|
+
"User-Agent": `vouch-mcp/${VERSION}`,
|
|
53
|
+
},
|
|
54
|
+
signal: controller.signal,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
const aborted = e instanceof Error && e.name === "AbortError";
|
|
59
|
+
return errorResult(aborted
|
|
60
|
+
? `Verification timed out after ${REQUEST_TIMEOUT_MS / 1000}s.`
|
|
61
|
+
: `Could not reach the Vouch API: ${e instanceof Error ? e.message : String(e)}.`);
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
clearTimeout(timer);
|
|
65
|
+
}
|
|
66
|
+
const raw = await res.text();
|
|
67
|
+
let body = null;
|
|
68
|
+
try {
|
|
69
|
+
body = raw ? JSON.parse(raw) : null;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
/* non-JSON body — handled below */
|
|
73
|
+
}
|
|
74
|
+
const obj = (body && typeof body === "object" ? body : {});
|
|
75
|
+
if (!res.ok) {
|
|
76
|
+
const detail = obj.message || obj.error || raw || `HTTP ${res.status}`;
|
|
77
|
+
const hint = res.status === 401
|
|
78
|
+
? " Check that VOUCH_API_KEY is correct and active."
|
|
79
|
+
: res.status === 402
|
|
80
|
+
? " You're out of verification credits — top up at https://vouch.fast/dashboard."
|
|
81
|
+
: res.status === 429
|
|
82
|
+
? ` Rate limited${obj.retryAfter ? `; retry after ${String(obj.retryAfter)}s` : ""}.`
|
|
83
|
+
: "";
|
|
84
|
+
return errorResult(`Vouch API error (${res.status}): ${String(detail)}.${hint}`);
|
|
85
|
+
}
|
|
86
|
+
if (!body || typeof body !== "object") {
|
|
87
|
+
return errorResult(`Unexpected response from the Vouch API: ${raw.slice(0, 200)}`);
|
|
88
|
+
}
|
|
89
|
+
const text = `${formatSummary(obj)}\n\n\`\`\`json\n${JSON.stringify(obj, null, 2)}\n\`\`\``;
|
|
90
|
+
return { content: [{ type: "text", text }] };
|
|
91
|
+
}
|
|
92
|
+
async function main() {
|
|
93
|
+
const server = new McpServer({ name: "vouch", version: VERSION });
|
|
94
|
+
server.registerTool("verify_email", {
|
|
95
|
+
title: "Verify email address",
|
|
96
|
+
description: "Check whether an email address is deliverable using Vouch. Runs syntax validation, MX lookup, " +
|
|
97
|
+
"a live SMTP probe, and catch-all detection, then returns a verdict (deliverable, undeliverable, " +
|
|
98
|
+
"risky, or unknown), a 0–100 confidence score, quality flags (disposable, role account, free " +
|
|
99
|
+
"provider), and a typo suggestion when relevant. Use before sending email or accepting a signup.",
|
|
100
|
+
inputSchema: {
|
|
101
|
+
email: z
|
|
102
|
+
.string()
|
|
103
|
+
.min(1)
|
|
104
|
+
.describe("The email address to verify, e.g. jane@example.com"),
|
|
105
|
+
},
|
|
106
|
+
}, async ({ email }) => verifyEmail(email.trim()));
|
|
107
|
+
const transport = new StdioServerTransport();
|
|
108
|
+
await server.connect(transport);
|
|
109
|
+
// Never write to stdout — it carries the JSON-RPC protocol. stderr is safe.
|
|
110
|
+
console.error(`[vouch-mcp] v${VERSION} ready (API ${apiBase()})`);
|
|
111
|
+
}
|
|
112
|
+
main().catch((e) => {
|
|
113
|
+
console.error("[vouch-mcp] fatal:", e);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@datapad-nl/vouch-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Vouch — verify email deliverability (syntax, MX, live SMTP, catch-all) with your Vouch API key.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"model-context-protocol",
|
|
8
|
+
"email",
|
|
9
|
+
"email-verification",
|
|
10
|
+
"deliverability",
|
|
11
|
+
"vouch",
|
|
12
|
+
"smtp"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://vouch.fast",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/Datapad-nl/Vouch.git",
|
|
18
|
+
"directory": "mcp"
|
|
19
|
+
},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"author": "Datapad",
|
|
22
|
+
"type": "module",
|
|
23
|
+
"bin": {
|
|
24
|
+
"vouch-mcp": "dist/index.js"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc",
|
|
35
|
+
"dev": "tsx src/index.ts",
|
|
36
|
+
"prepublishOnly": "npm run build"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
40
|
+
"zod": "^3.25.1"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^20",
|
|
44
|
+
"tsx": "^4.21.1",
|
|
45
|
+
"typescript": "^5"
|
|
46
|
+
}
|
|
47
|
+
}
|