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 +24 -6
- package/server.json +2 -2
- package/src/server.js +12 -5
package/package.json
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "url-safety-validator-mcp",
|
|
3
|
-
"
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
?
|
|
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' } : {})
|