site-audit-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.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,456 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * seo-mcp — MCP server for AI agents
4
+ * Website performance, WHOIS lookup, DNS records, SSL info, and tech stack detection.
5
+ * All data sources are free, no API key required.
6
+ */
7
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
+ import { z } from "zod";
10
+ const server = new McpServer({
11
+ name: "seo-mcp",
12
+ version: "0.1.0",
13
+ });
14
+ // ── Helpers ──────────────────────────────────────────────────
15
+ function extractDomain(input) {
16
+ try {
17
+ const url = new URL(input.startsWith("http") ? input : "https://" + input);
18
+ return url.hostname;
19
+ }
20
+ catch {
21
+ return input.replace(/^https?:\/\//, "").split("/")[0];
22
+ }
23
+ }
24
+ async function fetchJSON(url, timeoutMs = 15000) {
25
+ const controller = new AbortController();
26
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
27
+ try {
28
+ const res = await fetch(url, {
29
+ signal: controller.signal,
30
+ headers: { "User-Agent": "seo-mcp/0.1.0" },
31
+ });
32
+ if (!res.ok)
33
+ throw new Error("HTTP " + res.status + ": " + res.statusText);
34
+ return await res.json();
35
+ }
36
+ finally {
37
+ clearTimeout(timer);
38
+ }
39
+ }
40
+ async function fetchHeaders(url, timeoutMs = 15000) {
41
+ const controller = new AbortController();
42
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
43
+ try {
44
+ const res = await fetch(url, {
45
+ signal: controller.signal,
46
+ headers: { "User-Agent": "seo-mcp/0.1.0" },
47
+ redirect: "follow",
48
+ });
49
+ const headers = {};
50
+ res.headers.forEach((v, k) => { headers[k] = v; });
51
+ return { status: res.status, headers };
52
+ }
53
+ finally {
54
+ clearTimeout(timer);
55
+ }
56
+ }
57
+ // ── Telemetry ────────────────────────────────────────────────
58
+ async function telemetryPing() {
59
+ try {
60
+ await fetch("https://radom.group/seo-ping", {
61
+ method: "POST",
62
+ headers: { "Content-Type": "application/json" },
63
+ body: JSON.stringify({ server: "seo-mcp", version: "0.1.0", ts: new Date().toISOString() }),
64
+ signal: AbortSignal.timeout(5000),
65
+ }).catch(() => { });
66
+ }
67
+ catch { }
68
+ }
69
+ // ── Tool 1: check_pagespeed ──────────────────────────────────
70
+ server.tool("check_pagespeed", "Run Google PageSpeed Insights on a URL. Returns performance score, Core Web Vitals (FCP, LCP, CLS, TBT), speed index, and improvement opportunities.", {
71
+ url: z.string().describe("Full URL to test (e.g. https://example.com)"),
72
+ strategy: z.enum(["mobile", "desktop"]).default("mobile").describe("Test strategy: mobile or desktop"),
73
+ }, async ({ url, strategy }) => {
74
+ const apiUrl = "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=" + encodeURIComponent(url) + "&strategy=" + strategy;
75
+ let data;
76
+ try {
77
+ data = await fetchJSON(apiUrl, 60000);
78
+ }
79
+ catch (e) {
80
+ return { content: [{ type: "text", text: "PageSpeed API error: " + e.message + "\nThe free API is rate-limited. Try again in a few minutes or use a different IP." }] };
81
+ }
82
+ const lhr = data.lighthouseResult;
83
+ const cats = lhr?.categories?.performance;
84
+ const audits = lhr?.audits || {};
85
+ const score = cats?.score != null ? Math.round(cats.score * 100) : "N/A";
86
+ const fcp = audits["first-contentful-paint"]?.displayValue || "N/A";
87
+ const lcp = audits["largest-contentful-paint"]?.displayValue || "N/A";
88
+ const cls = audits["cumulative-layout-shift"]?.displayValue || "N/A";
89
+ const tbt = audits["total-blocking-time"]?.displayValue || "N/A";
90
+ const si = audits["speed-index"]?.displayValue || "N/A";
91
+ const lines = [
92
+ "PageSpeed Insights — " + strategy.toUpperCase(),
93
+ "URL: " + url,
94
+ "===================================",
95
+ "Performance Score: " + score + "/100",
96
+ "",
97
+ "Core Web Vitals:",
98
+ " FCP (First Contentful Paint): " + fcp,
99
+ " LCP (Largest Contentful Paint): " + lcp,
100
+ " CLS (Cumulative Layout Shift): " + cls,
101
+ " TBT (Total Blocking Time): " + tbt,
102
+ " Speed Index: " + si,
103
+ ];
104
+ // Opportunities
105
+ const opportunities = [];
106
+ for (const [key, audit] of Object.entries(audits)) {
107
+ if (audit.details?.type === "opportunity" && audit.details?.overallSavingsMs > 0) {
108
+ opportunities.push(" - " + audit.title + " (save ~" + Math.round(audit.details.overallSavingsMs) + "ms)");
109
+ }
110
+ }
111
+ if (opportunities.length > 0) {
112
+ lines.push("", "Opportunities:");
113
+ lines.push(...opportunities.slice(0, 10));
114
+ }
115
+ return { content: [{ type: "text", text: lines.join("\n") }] };
116
+ });
117
+ // ── Tool 2: lookup_whois ─────────────────────────────────────
118
+ server.tool("lookup_whois", "WHOIS lookup via RDAP. Returns registrar, creation/expiration dates, nameservers, and status.", {
119
+ domain: z.string().describe("Domain name (e.g. example.com)"),
120
+ }, async ({ domain }) => {
121
+ const clean = extractDomain(domain);
122
+ const data = await fetchJSON("https://rdap.org/domain/" + clean);
123
+ const registrar = data.entities?.find((e) => e.roles?.includes("registrar"))?.vcardArray?.[1]?.find((v) => v[0] === "fn")?.[3] || "Unknown";
124
+ const events = data.events || [];
125
+ const registration = events.find((e) => e.eventAction === "registration")?.eventDate || "N/A";
126
+ const expiration = events.find((e) => e.eventAction === "expiration")?.eventDate || "N/A";
127
+ const lastChanged = events.find((e) => e.eventAction === "last changed")?.eventDate || "N/A";
128
+ const nameservers = (data.nameservers || []).map((ns) => ns.ldhName || ns.objectClassName).filter(Boolean);
129
+ const statuses = data.status || [];
130
+ const lines = [
131
+ "WHOIS (RDAP) — " + clean,
132
+ "===================================",
133
+ "Registrar: " + registrar,
134
+ "Registered: " + registration,
135
+ "Expires: " + expiration,
136
+ "Last Changed: " + lastChanged,
137
+ "Status: " + (statuses.join(", ") || "N/A"),
138
+ "Nameservers: " + (nameservers.join(", ") || "N/A"),
139
+ ];
140
+ // Try to get registrant info
141
+ const registrant = data.entities?.find((e) => e.roles?.includes("registrant"));
142
+ if (registrant?.vcardArray?.[1]) {
143
+ const fn = registrant.vcardArray[1].find((v) => v[0] === "fn")?.[3];
144
+ const org = registrant.vcardArray[1].find((v) => v[0] === "org")?.[3];
145
+ if (fn)
146
+ lines.push("Registrant: " + fn);
147
+ if (org)
148
+ lines.push("Organization: " + org);
149
+ }
150
+ return { content: [{ type: "text", text: lines.join("\n") }] };
151
+ });
152
+ // ── Tool 3: check_dns ────────────────────────────────────────
153
+ server.tool("check_dns", "DNS record lookup via Google DNS-over-HTTPS. Supports A, AAAA, MX, TXT, NS, CNAME, SOA records.", {
154
+ domain: z.string().describe("Domain name (e.g. example.com)"),
155
+ record_type: z.string().default("ALL").describe("DNS record type: A, AAAA, MX, TXT, NS, CNAME, SOA, or ALL"),
156
+ }, async ({ domain, record_type }) => {
157
+ const clean = extractDomain(domain);
158
+ const types = record_type.toUpperCase() === "ALL"
159
+ ? ["A", "AAAA", "MX", "TXT", "NS", "CNAME", "SOA"]
160
+ : [record_type.toUpperCase()];
161
+ const lines = [
162
+ "DNS Records — " + clean,
163
+ "===================================",
164
+ ];
165
+ for (const type of types) {
166
+ try {
167
+ const data = await fetchJSON("https://dns.google/resolve?name=" + encodeURIComponent(clean) + "&type=" + type);
168
+ if (data.Answer && data.Answer.length > 0) {
169
+ lines.push("\n" + type + " Records:");
170
+ for (const record of data.Answer) {
171
+ lines.push(" " + record.name + " -> " + record.data + " (TTL: " + record.TTL + "s)");
172
+ }
173
+ }
174
+ }
175
+ catch (e) {
176
+ lines.push("\n" + type + ": Error — " + e.message);
177
+ }
178
+ }
179
+ if (lines.length === 2) {
180
+ lines.push("\nNo records found.");
181
+ }
182
+ return { content: [{ type: "text", text: lines.join("\n") }] };
183
+ });
184
+ // ── Tool 4: check_ssl ────────────────────────────────────────
185
+ server.tool("check_ssl", "Check SSL certificate for a domain. Returns issuer, validity dates, days until expiry, SANs, and certificate transparency data from crt.sh.", {
186
+ domain: z.string().describe("Domain name (e.g. example.com)"),
187
+ }, async ({ domain }) => {
188
+ const clean = extractDomain(domain);
189
+ const lines = [
190
+ "SSL Certificate — " + clean,
191
+ "===================================",
192
+ ];
193
+ // crt.sh certificate transparency
194
+ try {
195
+ const certs = await fetchJSON("https://crt.sh/?q=" + encodeURIComponent(clean) + "&output=json", 20000);
196
+ if (Array.isArray(certs) && certs.length > 0) {
197
+ // Most recent cert
198
+ const latest = certs[0];
199
+ lines.push("Issuer: " + (latest.issuer_name || "N/A"));
200
+ lines.push("Not Before: " + (latest.not_before || "N/A"));
201
+ lines.push("Not After: " + (latest.not_after || "N/A"));
202
+ if (latest.not_after) {
203
+ const expiry = new Date(latest.not_after);
204
+ const now = new Date();
205
+ const daysLeft = Math.ceil((expiry.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
206
+ lines.push("Days Left: " + daysLeft);
207
+ if (daysLeft < 30)
208
+ lines.push("WARNING: Certificate expires in less than 30 days!");
209
+ }
210
+ // SANs from the latest cert
211
+ if (latest.name_value) {
212
+ const sans = latest.name_value.split("\n").filter(Boolean);
213
+ lines.push("SANs: " + sans.slice(0, 10).join(", ") + (sans.length > 10 ? " (+" + (sans.length - 10) + " more)" : ""));
214
+ }
215
+ lines.push("\nRecent Certificates (last 5):");
216
+ for (const cert of certs.slice(0, 5)) {
217
+ lines.push(" " + cert.not_before + " -> " + cert.not_after + " | " + cert.issuer_name);
218
+ }
219
+ }
220
+ else {
221
+ lines.push("No certificates found on crt.sh");
222
+ }
223
+ }
224
+ catch (e) {
225
+ lines.push("crt.sh lookup failed: " + e.message);
226
+ }
227
+ // Direct HTTPS connection check
228
+ try {
229
+ const res = await fetch("https://" + clean, {
230
+ method: "HEAD",
231
+ signal: AbortSignal.timeout(10000),
232
+ headers: { "User-Agent": "seo-mcp/0.1.0" },
233
+ });
234
+ lines.push("\nLive HTTPS Check:");
235
+ lines.push(" Status: " + res.status + " " + res.statusText);
236
+ lines.push(" Connection: OK");
237
+ }
238
+ catch (e) {
239
+ lines.push("\nLive HTTPS Check:");
240
+ lines.push(" Connection: FAILED — " + e.message);
241
+ }
242
+ return { content: [{ type: "text", text: lines.join("\n") }] };
243
+ });
244
+ // ── Tool 5: analyze_headers ──────────────────────────────────
245
+ server.tool("analyze_headers", "Fetch a URL and analyze HTTP response headers. Returns server info, security headers, caching headers, and tech stack hints.", {
246
+ url: z.string().describe("Full URL to analyze (e.g. https://example.com)"),
247
+ }, async ({ url }) => {
248
+ const fullUrl = url.startsWith("http") ? url : "https://" + url;
249
+ const { status, headers } = await fetchHeaders(fullUrl);
250
+ const lines = [
251
+ "HTTP Header Analysis — " + fullUrl,
252
+ "===================================",
253
+ "Status: " + status,
254
+ "",
255
+ ];
256
+ // Server info
257
+ lines.push("Server Info:");
258
+ lines.push(" Server: " + (headers["server"] || "Not disclosed"));
259
+ lines.push(" X-Powered-By: " + (headers["x-powered-by"] || "Not disclosed"));
260
+ lines.push(" Via: " + (headers["via"] || "N/A"));
261
+ lines.push(" Content-Type: " + (headers["content-type"] || "N/A"));
262
+ // Security headers
263
+ lines.push("\nSecurity Headers:");
264
+ const secHeaders = [
265
+ ["Strict-Transport-Security", "strict-transport-security", "HSTS"],
266
+ ["Content-Security-Policy", "content-security-policy", "CSP"],
267
+ ["X-Frame-Options", "x-frame-options", "Clickjack protection"],
268
+ ["X-Content-Type-Options", "x-content-type-options", "MIME sniffing protection"],
269
+ ["X-XSS-Protection", "x-xss-protection", "XSS filter"],
270
+ ["Referrer-Policy", "referrer-policy", "Referrer control"],
271
+ ["Permissions-Policy", "permissions-policy", "Feature permissions"],
272
+ ];
273
+ let secScore = 0;
274
+ for (const [name, key, desc] of secHeaders) {
275
+ const val = headers[key];
276
+ const present = val ? "PASS" : "MISS";
277
+ if (val)
278
+ secScore++;
279
+ lines.push(" " + present + " " + name + ": " + (val || "Not set") + " (" + desc + ")");
280
+ }
281
+ lines.push(" Security Score: " + secScore + "/" + secHeaders.length);
282
+ // Caching
283
+ lines.push("\nCaching:");
284
+ lines.push(" Cache-Control: " + (headers["cache-control"] || "Not set"));
285
+ lines.push(" ETag: " + (headers["etag"] || "Not set"));
286
+ lines.push(" Last-Modified: " + (headers["last-modified"] || "Not set"));
287
+ lines.push(" Age: " + (headers["age"] || "N/A"));
288
+ // Tech stack hints
289
+ const techHints = [];
290
+ if (headers["x-powered-by"])
291
+ techHints.push(headers["x-powered-by"]);
292
+ if (headers["server"])
293
+ techHints.push("Server: " + headers["server"]);
294
+ if (headers["x-vercel-id"])
295
+ techHints.push("Vercel");
296
+ if (headers["x-amz-cf-id"] || headers["x-amz-request-id"])
297
+ techHints.push("AWS");
298
+ if (headers["cf-ray"])
299
+ techHints.push("Cloudflare");
300
+ if (headers["x-cache"] && headers["x-cache"].includes("cloudfront"))
301
+ techHints.push("CloudFront");
302
+ if (headers["x-github-request-id"])
303
+ techHints.push("GitHub Pages");
304
+ if (headers["x-netlify-request-id"])
305
+ techHints.push("Netlify");
306
+ if (headers["x-fastly-request-id"])
307
+ techHints.push("Fastly");
308
+ if (techHints.length > 0) {
309
+ lines.push("\nTech Stack Hints:");
310
+ for (const hint of techHints)
311
+ lines.push(" - " + hint);
312
+ }
313
+ return { content: [{ type: "text", text: lines.join("\n") }] };
314
+ });
315
+ // ── Tool 6: check_site_health ────────────────────────────────
316
+ server.tool("check_site_health", "Run a comprehensive site health check. Performs DNS, SSL, header analysis, and basic PageSpeed in parallel. Returns a combined report with pass/fail for each area.", {
317
+ domain: z.string().describe("Domain name (e.g. example.com)"),
318
+ }, async ({ domain }) => {
319
+ const clean = extractDomain(domain);
320
+ const url = "https://" + clean;
321
+ const lines = [
322
+ "Site Health Report — " + clean,
323
+ "===================================",
324
+ "Scan time: " + new Date().toISOString(),
325
+ "",
326
+ ];
327
+ const results = [];
328
+ // Run all checks in parallel
329
+ const [dnsResult, sslResult, headerResult, pageSpeedResult] = await Promise.allSettled([
330
+ // DNS
331
+ (async () => {
332
+ const data = await fetchJSON("https://dns.google/resolve?name=" + encodeURIComponent(clean) + "&type=A");
333
+ const hasRecords = data.Answer && data.Answer.length > 0;
334
+ const ips = hasRecords ? data.Answer.map((r) => r.data) : [];
335
+ return { hasRecords, ips };
336
+ })(),
337
+ // SSL
338
+ (async () => {
339
+ const certs = await fetchJSON("https://crt.sh/?q=" + encodeURIComponent(clean) + "&output=json", 20000);
340
+ if (!Array.isArray(certs) || certs.length === 0)
341
+ return { valid: false, daysLeft: 0, issuer: "N/A" };
342
+ const latest = certs[0];
343
+ const expiry = new Date(latest.not_after);
344
+ const daysLeft = Math.ceil((expiry.getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24));
345
+ return { valid: daysLeft > 0, daysLeft, issuer: latest.issuer_name };
346
+ })(),
347
+ // Headers
348
+ (async () => {
349
+ const { status, headers } = await fetchHeaders(url);
350
+ const hasHSTS = !!headers["strict-transport-security"];
351
+ const hasCSP = !!headers["content-security-policy"];
352
+ const hasXFO = !!headers["x-frame-options"];
353
+ const hasXCTO = !!headers["x-content-type-options"];
354
+ const secCount = [hasHSTS, hasCSP, hasXFO, hasXCTO].filter(Boolean).length;
355
+ return { status, secCount, server: headers["server"] || "Unknown" };
356
+ })(),
357
+ // PageSpeed (basic)
358
+ (async () => {
359
+ const data = await fetchJSON("https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=" + encodeURIComponent(url) + "&strategy=mobile", 60000);
360
+ const score = data.lighthouseResult?.categories?.performance?.score;
361
+ const perfScore = score != null ? Math.round(score * 100) : null;
362
+ const fcp = data.lighthouseResult?.audits?.["first-contentful-paint"]?.displayValue || "N/A";
363
+ const lcp = data.lighthouseResult?.audits?.["largest-contentful-paint"]?.displayValue || "N/A";
364
+ return { perfScore, fcp, lcp };
365
+ })(),
366
+ ]);
367
+ // DNS
368
+ if (dnsResult.status === "fulfilled") {
369
+ const dns = dnsResult.value;
370
+ results.push({
371
+ area: "DNS",
372
+ status: dns.hasRecords ? "PASS" : "FAIL",
373
+ details: dns.hasRecords ? ["A records: " + dns.ips.join(", ")] : ["No A records found"],
374
+ });
375
+ }
376
+ else {
377
+ results.push({ area: "DNS", status: "FAIL", details: ["Error: " + dnsResult.reason] });
378
+ }
379
+ // SSL
380
+ if (sslResult.status === "fulfilled") {
381
+ const ssl = sslResult.value;
382
+ const status = ssl.daysLeft > 30 ? "PASS" : ssl.daysLeft > 0 ? "WARN" : "FAIL";
383
+ results.push({
384
+ area: "SSL",
385
+ status,
386
+ details: [
387
+ "Valid: " + (ssl.valid ? "Yes" : "No"),
388
+ "Days until expiry: " + ssl.daysLeft,
389
+ "Issuer: " + ssl.issuer,
390
+ ],
391
+ });
392
+ }
393
+ else {
394
+ results.push({ area: "SSL", status: "FAIL", details: ["Error: " + sslResult.reason] });
395
+ }
396
+ // Headers / Security
397
+ if (headerResult.status === "fulfilled") {
398
+ const hdr = headerResult.value;
399
+ const status = hdr.secCount >= 3 ? "PASS" : hdr.secCount >= 1 ? "WARN" : "FAIL";
400
+ results.push({
401
+ area: "Security Headers",
402
+ status,
403
+ details: [
404
+ "HTTP status: " + hdr.status,
405
+ "Server: " + hdr.server,
406
+ "Security headers present: " + hdr.secCount + "/4",
407
+ ],
408
+ });
409
+ }
410
+ else {
411
+ results.push({ area: "Security Headers", status: "FAIL", details: ["Error: " + headerResult.reason] });
412
+ }
413
+ // PageSpeed
414
+ if (pageSpeedResult.status === "fulfilled") {
415
+ const ps = pageSpeedResult.value;
416
+ const status = ps.perfScore != null ? (ps.perfScore >= 90 ? "PASS" : ps.perfScore >= 50 ? "WARN" : "FAIL") : "FAIL";
417
+ results.push({
418
+ area: "Performance",
419
+ status,
420
+ details: [
421
+ "Score: " + (ps.perfScore ?? "N/A") + "/100",
422
+ "FCP: " + ps.fcp,
423
+ "LCP: " + ps.lcp,
424
+ ],
425
+ });
426
+ }
427
+ else {
428
+ results.push({ area: "Performance", status: "WARN", details: ["PageSpeed check timed out or failed"] });
429
+ }
430
+ // Build report
431
+ let passCount = 0;
432
+ for (const r of results) {
433
+ const icon = r.status === "PASS" ? "PASS" : r.status === "WARN" ? "WARN" : "FAIL";
434
+ lines.push("[" + icon + "] " + r.area);
435
+ for (const d of r.details)
436
+ lines.push(" " + d);
437
+ lines.push("");
438
+ if (r.status === "PASS")
439
+ passCount++;
440
+ }
441
+ const overall = passCount === results.length ? "HEALTHY" : passCount >= results.length / 2 ? "NEEDS ATTENTION" : "CRITICAL";
442
+ lines.push("===================================");
443
+ lines.push("Overall: " + overall + " (" + passCount + "/" + results.length + " checks passed)");
444
+ return { content: [{ type: "text", text: lines.join("\n") }] };
445
+ });
446
+ // ── Start ────────────────────────────────────────────────────
447
+ async function main() {
448
+ telemetryPing();
449
+ const transport = new StdioServerTransport();
450
+ await server.connect(transport);
451
+ }
452
+ main().catch((err) => {
453
+ console.error("Fatal:", err);
454
+ process.exit(1);
455
+ });
456
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "site-audit-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for AI agents \u00e2\u20ac\u201d website performance, WHOIS lookup, DNS records, SSL info, and tech stack detection. Free, no API key.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "seo-mcp": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsx src/index.ts",
13
+ "start": "node dist/index.js"
14
+ },
15
+ "keywords": [
16
+ "mcp",
17
+ "seo",
18
+ "website",
19
+ "performance",
20
+ "whois",
21
+ "dns",
22
+ "ssl",
23
+ "pagespeed",
24
+ "lighthouse",
25
+ "ai-agent"
26
+ ],
27
+ "files": [
28
+ "dist",
29
+ "README.md",
30
+ "package.json"
31
+ ],
32
+ "license": "MIT",
33
+ "dependencies": {
34
+ "@modelcontextprotocol/sdk": "^1.29.0",
35
+ "zod": "^4.3.6"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^25.5.0",
39
+ "tsx": "^4.21.0",
40
+ "typescript": "^6.0.2"
41
+ }
42
+ }