@tocharianou/abuseipdb-mcp 1.0.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.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +306 -0
  3. package/dist/index.d.ts +12 -0
  4. package/dist/index.js +148 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/src/blacklist-tools.d.ts +3 -0
  7. package/dist/src/blacklist-tools.js +41 -0
  8. package/dist/src/blacklist-tools.js.map +1 -0
  9. package/dist/src/block-tools.d.ts +3 -0
  10. package/dist/src/block-tools.js +38 -0
  11. package/dist/src/block-tools.js.map +1 -0
  12. package/dist/src/handlers/blacklist.d.ts +7 -0
  13. package/dist/src/handlers/blacklist.js +57 -0
  14. package/dist/src/handlers/blacklist.js.map +1 -0
  15. package/dist/src/handlers/block.d.ts +7 -0
  16. package/dist/src/handlers/block.js +34 -0
  17. package/dist/src/handlers/block.js.map +1 -0
  18. package/dist/src/handlers/index.d.ts +3 -0
  19. package/dist/src/handlers/index.js +4 -0
  20. package/dist/src/handlers/index.js.map +1 -0
  21. package/dist/src/handlers/ip.d.ts +14 -0
  22. package/dist/src/handlers/ip.js +106 -0
  23. package/dist/src/handlers/ip.js.map +1 -0
  24. package/dist/src/ip-tools.d.ts +3 -0
  25. package/dist/src/ip-tools.js +79 -0
  26. package/dist/src/ip-tools.js.map +1 -0
  27. package/dist/src/types/abuseipdb.d.ts +69 -0
  28. package/dist/src/types/abuseipdb.js +37 -0
  29. package/dist/src/types/abuseipdb.js.map +1 -0
  30. package/dist/src/types.d.ts +18 -0
  31. package/dist/src/types.js +21 -0
  32. package/dist/src/types.js.map +1 -0
  33. package/dist/src/utils/api.d.ts +10 -0
  34. package/dist/src/utils/api.js +30 -0
  35. package/dist/src/utils/api.js.map +1 -0
  36. package/dist/src/utils/token-limiter.d.ts +8 -0
  37. package/dist/src/utils/token-limiter.js +29 -0
  38. package/dist/src/utils/token-limiter.js.map +1 -0
  39. package/logos/logo-240.svg +13 -0
  40. package/logos/logo-48.svg +9 -0
  41. package/package.json +54 -0
  42. package/server.json +43 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blacklist.js","sourceRoot":"","sources":["../../../src/handlers/blacklist.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { AxiosInstance } from 'axios';
2
+ export interface CheckBlockArgs {
3
+ network: string;
4
+ max_age_days?: number;
5
+ confidence_threshold?: number;
6
+ }
7
+ export declare function handleCheckBlock(client: AxiosInstance, args: CheckBlockArgs): Promise<string>;
@@ -0,0 +1,34 @@
1
+ export async function handleCheckBlock(client, args) {
2
+ const { network, max_age_days = 30, confidence_threshold = 75 } = args;
3
+ const { data: resp } = await client.get('/check-block', {
4
+ params: { network, maxAgeInDays: max_age_days },
5
+ });
6
+ const d = resp.data;
7
+ const reported = d.reportedAddress ?? [];
8
+ const highConfidence = reported.filter((a) => a.abuseConfidencePercentage >= confidence_threshold);
9
+ const lines = [
10
+ `Network: ${d.networkAddress}/${d.netmask}`,
11
+ `Address Range: ${d.minAddress} – ${d.maxAddress}`,
12
+ `Possible Hosts: ${d.numPossibleHosts.toLocaleString()}`,
13
+ `Address Space: ${d.addressSpaceDesc}`,
14
+ `Reported IPs: ${reported.length}`,
15
+ `High Confidence: ${highConfidence.length} (≥${confidence_threshold}%)`,
16
+ ];
17
+ if (highConfidence.length > 0) {
18
+ lines.push(`\n⚠️ ${highConfidence.length} high-confidence threats detected in this block`);
19
+ }
20
+ if (reported.length > 0) {
21
+ lines.push('\nTop Reported Addresses:');
22
+ const sorted = [...reported].sort((a, b) => b.abuseConfidencePercentage - a.abuseConfidencePercentage);
23
+ sorted.slice(0, 10).forEach((a) => {
24
+ lines.push(` • ${a.ipAddress} – ${a.abuseConfidencePercentage}% confidence (${a.numReports} reports, last: ${a.mostRecentReport ?? 'Unknown'})`);
25
+ });
26
+ if (reported.length > 10)
27
+ lines.push(` ... and ${reported.length - 10} more`);
28
+ }
29
+ else {
30
+ lines.push('\n✅ No reported IP addresses found in this block');
31
+ }
32
+ return lines.join('\n');
33
+ }
34
+ //# sourceMappingURL=block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block.js","sourceRoot":"","sources":["../../../src/handlers/block.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAqB,EACrB,IAAoB;IAEpB,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,EAAE,EAAE,oBAAoB,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;IAEvE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAqB,cAAc,EAAE;QAC1E,MAAM,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE;KAChD,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;IACpB,MAAM,QAAQ,GAAG,CAAC,CAAC,eAAe,IAAI,EAAE,CAAC;IACzC,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,yBAAyB,IAAI,oBAAoB,CAC3D,CAAC;IAEF,MAAM,KAAK,GAAG;QACZ,sBAAsB,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,OAAO,EAAE;QACrD,sBAAsB,CAAC,CAAC,UAAU,MAAM,CAAC,CAAC,UAAU,EAAE;QACtD,sBAAsB,CAAC,CAAC,gBAAgB,CAAC,cAAc,EAAE,EAAE;QAC3D,sBAAsB,CAAC,CAAC,gBAAgB,EAAE;QAC1C,sBAAsB,QAAQ,CAAC,MAAM,EAAE;QACvC,sBAAsB,cAAc,CAAC,MAAM,MAAM,oBAAoB,IAAI;KAC1E,CAAC;IAEF,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,SAAS,cAAc,CAAC,MAAM,iDAAiD,CAAC,CAAC;IAC9F,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAC/B,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,yBAAyB,GAAG,CAAC,CAAC,yBAAyB,CACpE,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YAChC,KAAK,CAAC,IAAI,CACR,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,yBAAyB,iBAAiB,CAAC,CAAC,UAAU,mBAAmB,CAAC,CAAC,gBAAgB,IAAI,SAAS,GAAG,CACtI,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,IAAI,QAAQ,CAAC,MAAM,GAAG,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,aAAa,QAAQ,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC,CAAC;IACjF,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { handleCheckIp, handleBulkCheck } from './ip.js';
2
+ export { handleCheckBlock } from './block.js';
3
+ export { handleGetBlacklist } from './blacklist.js';
@@ -0,0 +1,4 @@
1
+ export { handleCheckIp, handleBulkCheck } from './ip.js';
2
+ export { handleCheckBlock } from './block.js';
3
+ export { handleGetBlacklist } from './blacklist.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/handlers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { AxiosInstance } from 'axios';
2
+ export interface CheckIpArgs {
3
+ ip_address: string;
4
+ max_age_days?: number;
5
+ verbose?: boolean;
6
+ threshold?: number;
7
+ }
8
+ export interface BulkCheckArgs {
9
+ ip_addresses: string[];
10
+ max_age_days?: number;
11
+ threshold?: number;
12
+ }
13
+ export declare function handleCheckIp(client: AxiosInstance, args: CheckIpArgs): Promise<string>;
14
+ export declare function handleBulkCheck(client: AxiosInstance, args: BulkCheckArgs): Promise<string>;
@@ -0,0 +1,106 @@
1
+ import { assessRiskLevel, ABUSE_CATEGORIES, } from '../types/abuseipdb.js';
2
+ export async function handleCheckIp(client, args) {
3
+ const { ip_address, max_age_days = 30, verbose = false, threshold = 75 } = args;
4
+ const params = {
5
+ ipAddress: ip_address,
6
+ maxAgeInDays: max_age_days,
7
+ verbose: verbose ? 'true' : 'false',
8
+ };
9
+ const { data: resp } = await client.get('/check', { params });
10
+ const d = resp.data;
11
+ const riskLevel = assessRiskLevel(d.abuseConfidenceScore);
12
+ const isFlagged = d.abuseConfidenceScore >= threshold;
13
+ const lines = [
14
+ `IP Address: ${d.ipAddress}`,
15
+ `Risk Level: ${riskLevel}`,
16
+ `Abuse Confidence: ${d.abuseConfidenceScore}%`,
17
+ `Total Reports: ${d.totalReports}`,
18
+ `Distinct Reporters:${d.numDistinctUsers}`,
19
+ `Last Reported: ${d.lastReportedAt ?? 'Never'}`,
20
+ `Country: ${d.countryName ?? d.countryCode ?? 'Unknown'}`,
21
+ `ISP: ${d.isp ?? 'Unknown'}`,
22
+ `Domain: ${d.domain ?? 'Unknown'}`,
23
+ `Usage Type: ${d.usageType ?? 'Unknown'}`,
24
+ `Is Public: ${d.isPublic}`,
25
+ `Is Whitelisted: ${d.isWhitelisted}`,
26
+ `Is Tor: ${d.isTor}`,
27
+ ];
28
+ if (isFlagged)
29
+ lines.push(`\n⚠️ FLAGGED: Abuse confidence ${d.abuseConfidenceScore}% exceeds threshold of ${threshold}%`);
30
+ if (d.isWhitelisted)
31
+ lines.push('✅ Whitelisted');
32
+ if (verbose && d.reports && d.reports.length > 0) {
33
+ lines.push('\nRecent Reports (up to 10):');
34
+ d.reports.slice(0, 10).forEach((r) => {
35
+ const cats = r.categories.map((c) => ABUSE_CATEGORIES[c] ?? `Category ${c}`).join(', ');
36
+ lines.push(` • ${r.reportedAt} [${cats}] – ${r.comment || '(no comment)'}`);
37
+ });
38
+ }
39
+ return lines.join('\n');
40
+ }
41
+ export async function handleBulkCheck(client, args) {
42
+ const { ip_addresses, max_age_days = 30, threshold = 75 } = args;
43
+ if (!ip_addresses || ip_addresses.length === 0)
44
+ throw new Error('ip_addresses list is required');
45
+ if (ip_addresses.length > 100)
46
+ throw new Error('Maximum 100 IP addresses per bulk check');
47
+ const unique = [...new Set(ip_addresses.map((ip) => ip.trim()).filter(Boolean))];
48
+ const results = [];
49
+ // Sequential requests to respect rate limits
50
+ for (const ip of unique) {
51
+ try {
52
+ const { data: resp } = await client.get('/check', {
53
+ params: { ipAddress: ip, maxAgeInDays: max_age_days, verbose: 'false' },
54
+ });
55
+ const d = resp.data;
56
+ results.push({
57
+ ip,
58
+ success: true,
59
+ score: d.abuseConfidenceScore,
60
+ country: d.countryName ?? d.countryCode,
61
+ isp: d.isp,
62
+ reports: d.totalReports,
63
+ });
64
+ }
65
+ catch (err) {
66
+ const msg = err instanceof Error ? err.message : String(err);
67
+ results.push({ ip, success: false, error: msg });
68
+ }
69
+ }
70
+ const successful = results.filter((r) => r.success);
71
+ const failed = results.filter((r) => !r.success);
72
+ const flagged = successful.filter((r) => (r.score ?? 0) >= threshold);
73
+ const lines = [
74
+ `Bulk Check Results:`,
75
+ ` Unique IPs processed: ${unique.length}`,
76
+ ` Successful: ${successful.length}`,
77
+ ` Failed: ${failed.length}`,
78
+ ` Flagged (≥${threshold}%): ${flagged.length}`,
79
+ ];
80
+ if (flagged.length > 0) {
81
+ lines.push('\n⚠️ Flagged IPs:');
82
+ flagged.slice(0, 20).forEach((r) => {
83
+ lines.push(` • ${r.ip} – ${r.score}% (${r.country ?? 'Unknown'}, ${r.reports} reports)`);
84
+ });
85
+ if (flagged.length > 20)
86
+ lines.push(` ... and ${flagged.length - 20} more`);
87
+ }
88
+ if (failed.length > 0) {
89
+ lines.push('\n❌ Failed IPs:');
90
+ failed.slice(0, 5).forEach((r) => lines.push(` • ${r.ip}: ${r.error}`));
91
+ if (failed.length > 5)
92
+ lines.push(` ... and ${failed.length - 5} more`);
93
+ }
94
+ lines.push('\nAll Results:');
95
+ results.forEach((r) => {
96
+ if (r.success) {
97
+ const level = assessRiskLevel(r.score ?? 0);
98
+ lines.push(` ${r.ip} – ${level} (${r.score}%) – ${r.country ?? 'Unknown'} – ${r.isp ?? 'Unknown ISP'}`);
99
+ }
100
+ else {
101
+ lines.push(` ${r.ip} – ERROR: ${r.error}`);
102
+ }
103
+ });
104
+ return lines.join('\n');
105
+ }
106
+ //# sourceMappingURL=ip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ip.js","sourceRoot":"","sources":["../../../src/handlers/ip.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { AxiosInstance } from 'axios';
3
+ export declare function registerIpTools(server: McpServer, client: AxiosInstance, maxTokenCall?: number): void;
@@ -0,0 +1,79 @@
1
+ import { z } from 'zod';
2
+ import { handleCheckIp, handleBulkCheck } from './handlers/ip.js';
3
+ import { checkTokenLimit } from './utils/token-limiter.js';
4
+ // Note: server.tool is called via (server as any) cast to avoid TypeScript
5
+ // exceeding instantiation-depth limits when inferring Zod schema generics.
6
+ const CheckIpSchema = z.object({
7
+ ip_address: z.string().describe('IPv4 or IPv6 address to check'),
8
+ max_age_days: z
9
+ .number()
10
+ .int()
11
+ .min(1)
12
+ .max(365)
13
+ .optional()
14
+ .describe('Look-back window in days for abuse reports (1–365, default: 30)'),
15
+ verbose: z
16
+ .boolean()
17
+ .optional()
18
+ .describe('Include individual report details in the response (default: false)'),
19
+ threshold: z
20
+ .number()
21
+ .int()
22
+ .min(0)
23
+ .max(100)
24
+ .optional()
25
+ .describe('Abuse confidence % threshold for flagging the IP (0–100, default: 75)'),
26
+ break_token_rule: z
27
+ .boolean()
28
+ .optional()
29
+ .default(false)
30
+ .describe('Set to true to bypass token limits in critical situations (default: false)'),
31
+ });
32
+ const BulkCheckSchema = z.object({
33
+ ip_addresses: z
34
+ .array(z.string())
35
+ .min(1)
36
+ .max(100)
37
+ .describe('List of IPv4/IPv6 addresses to check (up to 100)'),
38
+ max_age_days: z
39
+ .number()
40
+ .int()
41
+ .min(1)
42
+ .max(365)
43
+ .optional()
44
+ .describe('Look-back window in days (1–365, default: 30)'),
45
+ threshold: z
46
+ .number()
47
+ .int()
48
+ .min(0)
49
+ .max(100)
50
+ .optional()
51
+ .describe('Abuse confidence % threshold for flagging (0–100, default: 75)'),
52
+ break_token_rule: z
53
+ .boolean()
54
+ .optional()
55
+ .default(false)
56
+ .describe('Set to true to bypass token limits in critical situations (default: false)'),
57
+ });
58
+ export function registerIpTools(server, client, maxTokenCall = 20000) {
59
+ const registerTool = server.tool.bind(server);
60
+ registerTool('check_ip', 'Check the reputation of a single IP address using AbuseIPDB. Returns abuse confidence score (0–100%), risk level, ISP, country, total reports, and optional verbose report details.', CheckIpSchema.shape, async (args) => {
61
+ const parsed = CheckIpSchema.parse(args);
62
+ const text = await handleCheckIp(client, parsed);
63
+ const tokenCheck = checkTokenLimit(text, maxTokenCall, parsed.break_token_rule ?? false);
64
+ if (!tokenCheck.allowed) {
65
+ return { content: [{ type: 'text', text: tokenCheck.error }] };
66
+ }
67
+ return { content: [{ type: 'text', text }] };
68
+ });
69
+ registerTool('bulk_check', 'Check the reputation of multiple IP addresses in batch (up to 100). Returns a summary of flagged IPs with confidence scores, risk levels, and country/ISP information.', BulkCheckSchema.shape, async (args) => {
70
+ const parsed = BulkCheckSchema.parse(args);
71
+ const text = await handleBulkCheck(client, parsed);
72
+ const tokenCheck = checkTokenLimit(text, maxTokenCall, parsed.break_token_rule ?? false);
73
+ if (!tokenCheck.allowed) {
74
+ return { content: [{ type: 'text', text: tokenCheck.error }] };
75
+ }
76
+ return { content: [{ type: 'text', text }] };
77
+ });
78
+ }
79
+ //# sourceMappingURL=ip-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ip-tools.js","sourceRoot":"","sources":["../../src/ip-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ export interface ReportEntry {
2
+ reportedAt: string;
3
+ comment: string;
4
+ categories: number[];
5
+ reporterId: number;
6
+ reporterCountryCode: string;
7
+ reporterCountryName: string;
8
+ }
9
+ export interface IPCheckData {
10
+ ipAddress: string;
11
+ isPublic: boolean;
12
+ ipVersion: number;
13
+ isWhitelisted: boolean;
14
+ abuseConfidenceScore: number;
15
+ countryCode: string | null;
16
+ countryName: string | null;
17
+ usageType: string | null;
18
+ isp: string | null;
19
+ domain: string | null;
20
+ hostnames: string[];
21
+ isTor: boolean;
22
+ totalReports: number;
23
+ numDistinctUsers: number;
24
+ lastReportedAt: string | null;
25
+ reports?: ReportEntry[];
26
+ }
27
+ export interface IPCheckResponse {
28
+ data: IPCheckData;
29
+ }
30
+ export interface BlockAddressEntry {
31
+ ipAddress: string;
32
+ numReports: number;
33
+ mostRecentReport: string | null;
34
+ abuseConfidencePercentage: number;
35
+ countryCode: string | null;
36
+ }
37
+ export interface BlockCheckData {
38
+ networkAddress: string;
39
+ netmask: string;
40
+ minAddress: string;
41
+ maxAddress: string;
42
+ numPossibleHosts: number;
43
+ addressSpaceDesc: string;
44
+ reportedAddress: BlockAddressEntry[];
45
+ }
46
+ export interface BlockCheckResponse {
47
+ data: BlockCheckData;
48
+ }
49
+ export interface BlacklistEntry {
50
+ ipAddress: string;
51
+ abuseConfidenceScore: number;
52
+ countryCode: string | null;
53
+ usageType: string | null;
54
+ isp: string | null;
55
+ domain: string | null;
56
+ totalReports: number;
57
+ numDistinctUsers: number;
58
+ lastReportedAt: string | null;
59
+ }
60
+ export interface BlacklistMeta {
61
+ generatedAt: string;
62
+ }
63
+ export interface BlacklistResponse {
64
+ meta: BlacklistMeta;
65
+ data: BlacklistEntry[];
66
+ }
67
+ export type RiskLevel = 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'CLEAN';
68
+ export declare function assessRiskLevel(score: number): RiskLevel;
69
+ export declare const ABUSE_CATEGORIES: Record<number, string>;
@@ -0,0 +1,37 @@
1
+ export function assessRiskLevel(score) {
2
+ if (score >= 90)
3
+ return 'CRITICAL';
4
+ if (score >= 75)
5
+ return 'HIGH';
6
+ if (score >= 25)
7
+ return 'MEDIUM';
8
+ if (score >= 1)
9
+ return 'LOW';
10
+ return 'CLEAN';
11
+ }
12
+ export const ABUSE_CATEGORIES = {
13
+ 1: 'DNS Compromise',
14
+ 2: 'DNS Poisoning',
15
+ 3: 'Fraud Orders',
16
+ 4: 'DDoS Attack',
17
+ 5: 'FTP Brute-Force',
18
+ 6: 'Ping of Death',
19
+ 7: 'Phishing',
20
+ 8: 'Fraud VoIP',
21
+ 9: 'Open Proxy',
22
+ 10: 'Web Spam',
23
+ 11: 'Email Spam',
24
+ 12: 'Blog Spam',
25
+ 13: 'VPN IP',
26
+ 14: 'Port Scan',
27
+ 15: 'Hacking',
28
+ 16: 'SQL Injection',
29
+ 17: 'Spoofing',
30
+ 18: 'Brute-Force',
31
+ 19: 'Bad Web Bot',
32
+ 20: 'Exploited Host',
33
+ 21: 'Web App Attack',
34
+ 22: 'SSH',
35
+ 23: 'IoT Targeted',
36
+ };
37
+ //# sourceMappingURL=abuseipdb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abuseipdb.js","sourceRoot":"","sources":["../../../src/types/abuseipdb.ts"],"names":[],"mappings":"AA6EA,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,UAAU,CAAC;IACnC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,MAAM,CAAC;IAC/B,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,QAAQ,CAAC;IACjC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAA2B;IACtD,CAAC,EAAE,gBAAgB;IACnB,CAAC,EAAE,eAAe;IAClB,CAAC,EAAE,cAAc;IACjB,CAAC,EAAE,aAAa;IAChB,CAAC,EAAE,iBAAiB;IACpB,CAAC,EAAE,eAAe;IAClB,CAAC,EAAE,UAAU;IACb,CAAC,EAAE,YAAY;IACf,CAAC,EAAE,YAAY;IACf,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,eAAe;IACnB,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,aAAa;IACjB,EAAE,EAAE,aAAa;IACjB,EAAE,EAAE,gBAAgB;IACpB,EAAE,EAAE,gBAAgB;IACpB,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,cAAc;CACnB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ export declare const AbuseIPDBConfigSchema: z.ZodObject<{
3
+ apiKey: z.ZodOptional<z.ZodString>;
4
+ baseUrl: z.ZodOptional<z.ZodString>;
5
+ authToken: z.ZodOptional<z.ZodString>;
6
+ timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ timeout: number;
9
+ apiKey?: string | undefined;
10
+ baseUrl?: string | undefined;
11
+ authToken?: string | undefined;
12
+ }, {
13
+ apiKey?: string | undefined;
14
+ baseUrl?: string | undefined;
15
+ authToken?: string | undefined;
16
+ timeout?: number | undefined;
17
+ }>;
18
+ export type AbuseIPDBConfig = z.infer<typeof AbuseIPDBConfigSchema>;
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ export const AbuseIPDBConfigSchema = z.object({
3
+ apiKey: z
4
+ .string()
5
+ .optional()
6
+ .describe('AbuseIPDB API key sent as Key header (BYOK mode). ' +
7
+ 'Get yours at https://www.abuseipdb.com/account/api'),
8
+ baseUrl: z
9
+ .string()
10
+ .optional()
11
+ .describe('Override the AbuseIPDB API base URL. ' +
12
+ 'Defaults to https://api.abuseipdb.com/api/v2. ' +
13
+ 'Set this to a proxy endpoint to route requests through a backend.'),
14
+ authToken: z
15
+ .string()
16
+ .optional()
17
+ .describe('Bearer token sent as Authorization header when using a proxy base URL. ' +
18
+ 'Ignored when apiKey is set directly.'),
19
+ timeout: z.number().optional().default(30000).describe('Request timeout in milliseconds'),
20
+ });
21
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,oDAAoD;QAClD,oDAAoD,CACvD;IACH,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,uCAAuC;QACrC,gDAAgD;QAChD,mEAAmE,CACtE;IACH,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,yEAAyE;QACvE,sCAAsC,CACzC;IACH,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,iCAAiC,CAAC;CAC1F,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { AxiosInstance } from 'axios';
2
+ import { AbuseIPDBConfig } from '../types.js';
3
+ /**
4
+ * Creates an Axios client for AbuseIPDB.
5
+ *
6
+ * Auth strategy:
7
+ * BYOK mode → apiKey present → sends `Key: <apiKey>` header (AbuseIPDB native auth)
8
+ * Hub mode → no apiKey, baseUrl points to proxy → sends `Authorization: Bearer <authToken>`
9
+ */
10
+ export declare function createAbuseIPDBClient(config: AbuseIPDBConfig): AxiosInstance;
@@ -0,0 +1,30 @@
1
+ import axios from 'axios';
2
+ const DEFAULT_BASE_URL = 'https://api.abuseipdb.com/api/v2';
3
+ /**
4
+ * Creates an Axios client for AbuseIPDB.
5
+ *
6
+ * Auth strategy:
7
+ * BYOK mode → apiKey present → sends `Key: <apiKey>` header (AbuseIPDB native auth)
8
+ * Hub mode → no apiKey, baseUrl points to proxy → sends `Authorization: Bearer <authToken>`
9
+ */
10
+ export function createAbuseIPDBClient(config) {
11
+ const baseURL = config.baseUrl || DEFAULT_BASE_URL;
12
+ const headers = {
13
+ Accept: 'application/json',
14
+ 'Content-Type': 'application/json',
15
+ };
16
+ if (config.apiKey) {
17
+ // BYOK: AbuseIPDB uses "Key" header for authentication
18
+ headers['Key'] = config.apiKey;
19
+ }
20
+ else if (config.authToken) {
21
+ // Hub proxy: authenticate with Bearer token; proxy injects the real API key
22
+ headers['Authorization'] = `Bearer ${config.authToken}`;
23
+ }
24
+ return axios.create({
25
+ baseURL,
26
+ headers,
27
+ timeout: config.timeout ?? 30000,
28
+ });
29
+ }
30
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/utils/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAwB,MAAM,OAAO,CAAC;AAG7C,MAAM,gBAAgB,GAAG,kCAAkC,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAuB;IAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,gBAAgB,CAAC;IAEnD,MAAM,OAAO,GAA2B;QACtC,MAAM,EAAE,kBAAkB;QAC1B,cAAc,EAAE,kBAAkB;KACnC,CAAC;IAEF,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,uDAAuD;QACvD,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACjC,CAAC;SAAM,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QAC5B,4EAA4E;QAC5E,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,CAAC,SAAS,EAAE,CAAC;IAC1D,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,CAAC;QAClB,OAAO;QACP,OAAO;QACP,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;KACjC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { TiktokenModel } from 'tiktoken';
2
+ export interface TokenCheckResult {
3
+ allowed: boolean;
4
+ tokens: number;
5
+ error?: string;
6
+ }
7
+ export declare function calculateTokens(text: string, model?: TiktokenModel): number;
8
+ export declare function checkTokenLimit(result: unknown, maxTokens: number, breakRule?: boolean): TokenCheckResult;
@@ -0,0 +1,29 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { encoding_for_model } from 'tiktoken';
3
+ export function calculateTokens(text, model = 'gpt-4') {
4
+ const enc = encoding_for_model(model);
5
+ try {
6
+ return enc.encode(text).length;
7
+ }
8
+ finally {
9
+ enc.free();
10
+ }
11
+ }
12
+ export function checkTokenLimit(result, maxTokens, breakRule = false) {
13
+ if (breakRule) {
14
+ return { allowed: true, tokens: 0 };
15
+ }
16
+ const resultText = typeof result === 'string' ? result : JSON.stringify(result);
17
+ const tokens = calculateTokens(resultText);
18
+ if (tokens > maxTokens) {
19
+ return {
20
+ allowed: false,
21
+ tokens,
22
+ error: `Token limit exceeded: result contains ${tokens} tokens (limit: ${maxTokens}). ` +
23
+ `To reduce output size, try: raise confidence_minimum (e.g. 90+), reduce the limit parameter, ` +
24
+ `use max_age_days to narrow the time window, or set break_token_rule: true to bypass this check.`,
25
+ };
26
+ }
27
+ return { allowed: true, tokens };
28
+ }
29
+ //# sourceMappingURL=token-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-limiter.js","sourceRoot":"","sources":["../../../src/utils/token-limiter.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,EAAE,kBAAkB,EAAiB,MAAM,UAAU,CAAC;AAQ7D,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,QAAuB,OAAO;IAC1E,MAAM,GAAG,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IACjC,CAAC;YAAS,CAAC;QACT,GAAG,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,MAAe,EACf,SAAiB,EACjB,SAAS,GAAG,KAAK;IAEjB,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACtC,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAChF,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAE3C,IAAI,MAAM,GAAG,SAAS,EAAE,CAAC;QACvB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM;YACN,KAAK,EACH,yCAAyC,MAAM,mBAAmB,SAAS,KAAK;gBAChF,+FAA+F;gBAC/F,iGAAiG;SACpG,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACnC,CAAC"}
@@ -0,0 +1,13 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 80" width="240" height="80">
2
+ <rect width="240" height="80" rx="12" fill="#DC2626"/>
3
+ <!-- Shield icon -->
4
+ <path d="M28 16 L44 22 L44 40 C44 52 36 60 28 64 C20 60 12 52 12 40 L12 22 Z"
5
+ fill="none" stroke="white" stroke-width="2.5" stroke-linejoin="round" stroke-opacity="0.9"/>
6
+ <rect x="26.5" y="27" width="3" height="19" rx="1.5" fill="white"/>
7
+ <circle cx="28" cy="51" r="2.2" fill="white"/>
8
+ <!-- Text -->
9
+ <text x="60" y="44" font-family="system-ui, -apple-system, sans-serif" font-size="22"
10
+ font-weight="700" fill="white" letter-spacing="-0.3">AbuseIPDB</text>
11
+ <text x="61" y="62" font-family="system-ui, -apple-system, sans-serif" font-size="12"
12
+ fill="rgba(255,255,255,0.75)" letter-spacing="0.2">IP Reputation Intelligence</text>
13
+ </svg>
@@ -0,0 +1,9 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
2
+ <rect width="48" height="48" rx="10" fill="#DC2626"/>
3
+ <!-- Shield shape -->
4
+ <path d="M24 8 L36 13 L36 24 C36 31 30 37 24 40 C18 37 12 31 12 24 L12 13 Z"
5
+ fill="none" stroke="white" stroke-width="1.8" stroke-linejoin="round" stroke-opacity="0.9"/>
6
+ <!-- Warning exclamation -->
7
+ <rect x="22.5" y="17" width="3" height="11" rx="1.5" fill="white"/>
8
+ <circle cx="24" cy="32" r="1.8" fill="white"/>
9
+ </svg>
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@tocharianou/abuseipdb-mcp",
3
+ "description": "AbuseIPDB MCP Server – IP reputation, abuse confidence scoring, and threat blacklist",
4
+ "version": "1.0.1",
5
+ "mcpName": "io.github.TocharianOU/abuseipdb",
6
+ "license": "Apache-2.0",
7
+ "author": "TocharianOU",
8
+ "type": "module",
9
+ "main": "dist/index.js",
10
+ "module": "dist/index.js",
11
+ "bin": {
12
+ "abuseipdb-mcp": "dist/index.js"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/TocharianOU/abuseipdb-mcp.git"
17
+ },
18
+ "bugs": {
19
+ "url": "https://github.com/TocharianOU/abuseipdb-mcp/issues"
20
+ },
21
+ "homepage": "https://github.com/TocharianOU/abuseipdb-mcp#readme",
22
+ "keywords": [
23
+ "abuseipdb", "mcp", "mcp-server", "model-context-protocol",
24
+ "security", "threat-intelligence", "ip-reputation",
25
+ "abuse-detection", "blacklist", "soc", "claude", "anthropic"
26
+ ],
27
+ "files": ["dist", "logos", "LICENSE", "README.md", "server.json"],
28
+ "scripts": {
29
+ "build": "tsc && shx chmod +x dist/index.js",
30
+ "prepare": "npm run build",
31
+ "watch": "tsc --watch",
32
+ "start": "node dist/index.js",
33
+ "start:http": "MCP_TRANSPORT=http node dist/index.js",
34
+ "inspector": "npx @modelcontextprotocol/inspector node dist/index.js",
35
+ "release": "./scripts/create-release.sh",
36
+ "release:npm": "npm run build && tar -czf abuseipdb-mcp-v$npm_package_version.tar.gz dist logos LICENSE README.md server.json package.json"
37
+ },
38
+ "dependencies": {
39
+ "@modelcontextprotocol/sdk": "1.23.0",
40
+ "@types/express": "^5.0.3",
41
+ "axios": "^1.8.4",
42
+ "tiktoken": "^1.0.7",
43
+ "dotenv": "^16.4.5",
44
+ "express": "^5.1.0",
45
+ "zod": "^3.24.2"
46
+ },
47
+ "engines": { "node": ">=18" },
48
+ "devDependencies": {
49
+ "@types/node": "22.13.15",
50
+ "shx": "0.4.0",
51
+ "typescript": "^5.8.3"
52
+ },
53
+ "publishConfig": { "access": "public" }
54
+ }