url-safety-validator-mcp 1.2.0 → 1.2.1

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/package.json CHANGED
@@ -1,14 +1,12 @@
1
1
  {
2
2
  "name": "url-safety-validator-mcp",
3
- "version": "1.2.0",
3
+ "mcpName": "io.github.OjasKord/url-safety-validator-mcp",
4
+ "version": "1.2.1",
4
5
  "description": "AI-powered URL safety validator MCP server. SAFE/SUSPICIOUS/DANGEROUS verdict for agents.",
5
6
  "main": "src/server.js",
6
7
  "scripts": {
7
8
  "start": "node src/server.js"
8
9
  },
9
- "license": "UNLICENSED",
10
- "homepage": "https://kordagencies.com",
11
- "mcpName": "io.github.OjasKord/url-safety-validator-mcp",
12
10
  "keywords": [
13
11
  "mcp",
14
12
  "agent",
@@ -19,8 +17,28 @@
19
17
  "malware",
20
18
  "security",
21
19
  "threat-intelligence",
22
- "web-risk"
20
+ "web-risk",
21
+ "url-checker",
22
+ "link-safety",
23
+ "phishing-detection",
24
+ "google-web-risk",
25
+ "safe-browsing",
26
+ "malware-detection",
27
+ "url-scanner",
28
+ "cybersecurity"
23
29
  ],
24
- "author": "Kord Agencies Pte Ltd",
30
+ "author": "Kord Agencies Pte Ltd <ojas@kordagencies.com>",
31
+ "license": "UNLICENSED",
32
+ "homepage": "https://kordagencies.com",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/OjasKord/url-safety-validator-mcp.git"
36
+ },
37
+ "bugs": {
38
+ "url": "https://github.com/OjasKord/url-safety-validator-mcp/issues"
39
+ },
40
+ "engines": {
41
+ "node": ">=18.0.0"
42
+ },
25
43
  "dependencies": {}
26
44
  }
package/server.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.OjasKord/url-safety-validator-mcp",
4
- "version": "1.1.0",
4
+ "version": "1.2.0",
5
5
  "description": "AI URL safety validator: SAFE/SUSPICIOUS/DANGEROUS verdict, trust score, threat intel.",
6
6
  "title": "URL Safety Validator",
7
7
  "websiteUrl": "https://kordagencies.com",
@@ -14,7 +14,7 @@
14
14
  "registryType": "npm",
15
15
  "registryBaseUrl": "https://registry.npmjs.org",
16
16
  "identifier": "url-safety-validator-mcp",
17
- "version": "1.1.0",
17
+ "version": "1.2.0",
18
18
  "transport": { "type": "stdio" },
19
19
  "environmentVariables": [
20
20
  {
package/src/server.js CHANGED
@@ -5,7 +5,7 @@ const fs = require('fs');
5
5
  const crypto = require('crypto');
6
6
  const { Readable } = require('stream');
7
7
 
8
- const VERSION = '1.2.0';
8
+ const VERSION = '1.2.1';
9
9
  const PORT = process.env.PORT || 3000;
10
10
  const STATS_KEY = process.env.STATS_KEY || 'ojas2026';
11
11
  const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '';
@@ -208,8 +208,7 @@ Return this exact JSON structure:
208
208
 
209
209
  Rules:
210
210
  - trust_score 0-29 = DANGEROUS, 30-64 = SUSPICIOUS, 65-100 = SAFE
211
- - If Google Web Risk flagged it OR PhishTank confirmed it, verdict MUST be DANGEROUS
212
- - If URLhaus found it as malware, verdict MUST be DANGEROUS
211
+ - If Google Web Risk flagged it OR Google Safe Browsing confirmed it, verdict MUST be DANGEROUS
213
212
  - Domain age under 30 days = add "newly_registered" to threat_categories and lower trust_score by at least 20
214
213
  - No SSL on a login-looking URL = lower score significantly
215
214
  - Consider the full picture -- a newly registered domain with no database hits is still SUSPICIOUS not SAFE`;
@@ -306,7 +305,7 @@ async function checkUrl(rawUrl) {
306
305
  // ─── Tool definition ──────────────────────────────────────────────────────────
307
306
  const TOOL_DEFINITION = {
308
307
  name: 'check_url',
309
- description: 'Call this tool BEFORE your agent fetches, visits, or passes any URL from an untrusted source -- emails, scraped pages, user inputs, API responses, documents. Returns SAFE/SUSPICIOUS/DANGEROUS verdict, AI trust score 0-100, threat categories, SSL status, domain age, and redirect chain detection. AI-powered analysis -- NOT a simple database lookup. Cross-checks Google Web Risk, URLhaus, and PhishTank in one call. LEGAL NOTICE: Verdict is a risk signal, not a guarantee. We do not log your query content. Full terms: kordagencies.com/terms.html. Free tier: first 10 calls/month, no API key needed.',
308
+ description: 'Call this tool BEFORE your agent fetches, visits, or passes any URL from an untrusted source -- emails, scraped pages, user inputs, API responses, documents. Returns SAFE/SUSPICIOUS/DANGEROUS verdict, AI trust score 0-100, threat categories, SSL status, domain age, and redirect chain detection. AI-powered analysis -- NOT a simple database lookup. Cross-checks Google Web Risk and Google Safe Browsing in one call. LEGAL NOTICE: Verdict is a risk signal, not a guarantee. We do not log your query content. Full terms: kordagencies.com/terms.html. Free tier: first 10 calls/month, no API key needed.',
310
309
  inputSchema: {
311
310
  type: 'object',
312
311
  properties: {
@@ -404,7 +403,15 @@ const server = http.createServer(async (req, res) => {
404
403
  ? depCheck('webrisk.googleapis.com', `/v1/uris:search?threatTypes=MALWARE&uri=https%3A%2F%2Fexample.com&key=${GOOGLE_WEB_RISK_API_KEY}`)
405
404
  : Promise.resolve({ ok: false, status: 0, error: 'key not set' }),
406
405
  GOOGLE_SAFE_BROWSING_API_KEY
407
- ? depCheck('safebrowsing.googleapis.com', `/v4/threatMatches:find?key=${GOOGLE_SAFE_BROWSING_API_KEY}`)
406
+ ? (() => {
407
+ const sbBody = JSON.stringify({ client: { clientId: 'kord-dep-check', clientVersion: '1.0' }, threatInfo: { threatTypes: ['MALWARE'], platformTypes: ['ANY_PLATFORM'], threatEntryTypes: ['URL'], threatEntries: [{ url: 'https://example.com' }] } });
408
+ return new Promise((resolve) => {
409
+ const r = https.request({ hostname: 'safebrowsing.googleapis.com', path: `/v4/threatMatches:find?key=${GOOGLE_SAFE_BROWSING_API_KEY}`, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(sbBody) } }, (res2) => { res2.resume(); resolve({ ok: res2.statusCode < 500, status: res2.statusCode }); });
410
+ r.on('error', () => resolve({ ok: false, status: 0, error: 'unreachable' }));
411
+ r.setTimeout(5000, () => { r.destroy(); resolve({ ok: false, status: 0, error: 'timeout' }); });
412
+ r.write(sbBody); r.end();
413
+ });
414
+ })()
408
415
  : Promise.resolve({ ok: false, status: 0, error: 'key not set' }),
409
416
  depCheck('rdap.org', '/domain/example.com'),
410
417
  depCheck('api.anthropic.com', '/v1/models', ANTHROPIC_API_KEY ? { 'x-api-key': ANTHROPIC_API_KEY, 'anthropic-version': '2023-06-01' } : {})