@cyanheads/whois-mcp-server 0.1.6 → 0.2.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/AGENTS.md +21 -9
- package/CLAUDE.md +21 -9
- package/Dockerfile +7 -4
- package/README.md +20 -11
- package/changelog/0.2.x/0.2.0.md +40 -0
- package/dist/app.d.ts +46 -22
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +7 -5
- package/dist/app.js.map +1 -1
- package/dist/mcp-server/tools/definitions/_fqdn.d.ts +9 -3
- package/dist/mcp-server/tools/definitions/_fqdn.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/_fqdn.js +10 -14
- package/dist/mcp-server/tools/definitions/_fqdn.js.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-check-availability.tool.d.ts +11 -5
- package/dist/mcp-server/tools/definitions/whois-check-availability.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-check-availability.tool.js +25 -38
- package/dist/mcp-server/tools/definitions/whois-check-availability.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-get-dns.tool.d.ts +6 -4
- package/dist/mcp-server/tools/definitions/whois-get-dns.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-get-dns.tool.js +25 -16
- package/dist/mcp-server/tools/definitions/whois-get-dns.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.d.ts +0 -5
- package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.js +20 -23
- package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.js +3 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.d.ts +16 -9
- package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.js +60 -21
- package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.d.ts +14 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.js +34 -6
- package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.js.map +1 -1
- package/dist/services/doh/doh-service.d.ts +3 -3
- package/dist/services/doh/doh-service.d.ts.map +1 -1
- package/dist/services/doh/doh-service.js +61 -12
- package/dist/services/doh/doh-service.js.map +1 -1
- package/dist/services/doh/types.d.ts +12 -0
- package/dist/services/doh/types.d.ts.map +1 -1
- package/dist/services/rdap/rdap-service.d.ts +10 -5
- package/dist/services/rdap/rdap-service.d.ts.map +1 -1
- package/dist/services/rdap/rdap-service.js +133 -36
- package/dist/services/rdap/rdap-service.js.map +1 -1
- package/dist/services/rdap/types.d.ts +32 -2
- package/dist/services/rdap/types.d.ts.map +1 -1
- package/package.json +12 -11
- package/server.json +11 -25
|
@@ -5,8 +5,20 @@
|
|
|
5
5
|
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
6
|
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
export declare const whoisLookupDomain: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
|
|
8
|
+
include_registrar: z.ZodDefault<z.ZodBoolean>;
|
|
8
9
|
domain: z.ZodString;
|
|
9
10
|
}, z.core.$strip>, z.ZodObject<{
|
|
11
|
+
registrar_detail: z.ZodOptional<z.ZodObject<{
|
|
12
|
+
status: z.ZodEnum<{
|
|
13
|
+
failed: "failed";
|
|
14
|
+
found: "found";
|
|
15
|
+
no_referral: "no_referral";
|
|
16
|
+
}>;
|
|
17
|
+
source: z.ZodOptional<z.ZodString>;
|
|
18
|
+
registrant_org: z.ZodOptional<z.ZodString>;
|
|
19
|
+
registrant_redacted: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
20
|
+
source_error: z.ZodOptional<z.ZodString>;
|
|
21
|
+
}, z.core.$strip>>;
|
|
10
22
|
domain: z.ZodString;
|
|
11
23
|
rdap_coverage: z.ZodBoolean;
|
|
12
24
|
handle: z.ZodOptional<z.ZodString>;
|
|
@@ -18,15 +30,10 @@ export declare const whoisLookupDomain: import("@cyanheads/mcp-ts-core").ToolDef
|
|
|
18
30
|
rdap_last_updated: z.ZodOptional<z.ZodString>;
|
|
19
31
|
status: z.ZodArray<z.ZodString>;
|
|
20
32
|
nameservers: z.ZodArray<z.ZodString>;
|
|
21
|
-
dnssec_signed: z.ZodBoolean
|
|
33
|
+
dnssec_signed: z.ZodNullable<z.ZodBoolean>;
|
|
22
34
|
registrant_org: z.ZodOptional<z.ZodString>;
|
|
23
|
-
registrant_redacted: z.ZodBoolean
|
|
35
|
+
registrant_redacted: z.ZodNullable<z.ZodBoolean>;
|
|
24
36
|
}, z.core.$strip>, readonly [{
|
|
25
|
-
readonly reason: "invalid_domain";
|
|
26
|
-
readonly code: JsonRpcErrorCode.ValidationError;
|
|
27
|
-
readonly when: "Input is not a valid FQDN.";
|
|
28
|
-
readonly recovery: "Provide a valid fully-qualified domain name like \"example.com\" or \"sub.example.org\".";
|
|
29
|
-
}, {
|
|
30
37
|
readonly reason: "rdap_no_coverage";
|
|
31
38
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
32
39
|
readonly when: "TLD has no RDAP server in the IANA bootstrap — cannot perform lookup.";
|
|
@@ -34,7 +41,7 @@ export declare const whoisLookupDomain: import("@cyanheads/mcp-ts-core").ToolDef
|
|
|
34
41
|
}, {
|
|
35
42
|
readonly reason: "domain_not_found";
|
|
36
43
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
37
|
-
readonly when: "RDAP server returned 404 — domain
|
|
38
|
-
readonly recovery: "
|
|
44
|
+
readonly when: "RDAP server returned 404 — no domain record found.";
|
|
45
|
+
readonly recovery: "Use whois_check_availability for record status; a missing record does not establish registration eligibility.";
|
|
39
46
|
}], undefined>;
|
|
40
47
|
//# sourceMappingURL=whois-lookup-domain.tool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whois-lookup-domain.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-domain.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAK3E,eAAO,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"whois-lookup-domain.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-domain.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAK3E,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAgM5B,CAAC"}
|
|
@@ -5,22 +5,54 @@
|
|
|
5
5
|
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
6
|
import { JsonRpcErrorCode, McpError } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
import { getRdapService } from '../../../services/rdap/rdap-service.js';
|
|
8
|
-
import {
|
|
8
|
+
import { REGISTRATION_NAME_PATTERN } from './_fqdn.js';
|
|
9
9
|
export const whoisLookupDomain = tool('whois_lookup_domain', {
|
|
10
10
|
title: 'Domain Registration Lookup',
|
|
11
11
|
description: "Look up a domain's registration record — registrar, created/expiry dates, nameservers, EPP status codes, " +
|
|
12
|
-
'DNSSEC
|
|
12
|
+
'provider DNSSEC evidence, and public registrant organization independently of contact redaction. Uses IANA bootstrap to select ' +
|
|
13
13
|
'the correct per-TLD RDAP server, returning one normalized shape regardless of TLD. When the TLD has no RDAP ' +
|
|
14
|
-
'coverage, throws rdap_no_coverage.
|
|
15
|
-
'whois_check_availability
|
|
14
|
+
'coverage, throws rdap_no_coverage. A missing registry object throws domain_not_found; ' +
|
|
15
|
+
'whois_check_availability returns record status without an eligibility guarantee. include_registrar opts into one ' +
|
|
16
|
+
'bounded registrar referral with separate contact detail; registry fields remain authoritative.',
|
|
16
17
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
17
18
|
input: z.object({
|
|
19
|
+
include_registrar: z
|
|
20
|
+
.boolean()
|
|
21
|
+
.default(false)
|
|
22
|
+
.describe('Follow one guarded registrar RDAP referral for optional contact detail. Registry fields remain authoritative; failed detail is disclosed without discarding the registry record.'),
|
|
18
23
|
domain: z
|
|
19
24
|
.string()
|
|
25
|
+
.max(253)
|
|
26
|
+
.regex(REGISTRATION_NAME_PATTERN, 'Provide a dot-separated ASCII hostname such as example.com; labels are 1–63 characters, without underscores, whitespace or a root dot.')
|
|
20
27
|
.describe('Fully qualified domain name to look up (e.g., "example.com", "github.com"). ' +
|
|
21
28
|
'Must be a valid FQDN — labels separated by dots, each label up to 63 chars.'),
|
|
22
29
|
}),
|
|
23
30
|
output: z.object({
|
|
31
|
+
registrar_detail: z
|
|
32
|
+
.object({
|
|
33
|
+
status: z
|
|
34
|
+
.enum(['found', 'no_referral', 'failed'])
|
|
35
|
+
.describe('Optional registrar lookup outcome.'),
|
|
36
|
+
source: z
|
|
37
|
+
.string()
|
|
38
|
+
.optional()
|
|
39
|
+
.describe('Registrar RDAP source URL, or attempted referral on failure.'),
|
|
40
|
+
registrant_org: z
|
|
41
|
+
.string()
|
|
42
|
+
.optional()
|
|
43
|
+
.describe('Public registrar-reported organization, independent of contact redaction.'),
|
|
44
|
+
registrant_redacted: z
|
|
45
|
+
.boolean()
|
|
46
|
+
.nullable()
|
|
47
|
+
.optional()
|
|
48
|
+
.describe('Explicit registrar privacy evidence; null when absent.'),
|
|
49
|
+
source_error: z
|
|
50
|
+
.string()
|
|
51
|
+
.optional()
|
|
52
|
+
.describe('Optional detail failure; registry fields remain usable.'),
|
|
53
|
+
})
|
|
54
|
+
.optional()
|
|
55
|
+
.describe('Registrar contact detail only when include_registrar is true.'),
|
|
24
56
|
domain: z.string().describe('Normalized domain name (lowercased).'),
|
|
25
57
|
rdap_coverage: z
|
|
26
58
|
.boolean()
|
|
@@ -45,22 +77,20 @@ export const whoisLookupDomain = tool('whois_lookup_domain', {
|
|
|
45
77
|
.array(z.string())
|
|
46
78
|
.describe('EPP status codes (e.g., clientTransferProhibited, serverDeleteProhibited).'),
|
|
47
79
|
nameservers: z.array(z.string()).describe('Authoritative nameservers for this domain.'),
|
|
48
|
-
dnssec_signed: z
|
|
80
|
+
dnssec_signed: z
|
|
81
|
+
.boolean()
|
|
82
|
+
.nullable()
|
|
83
|
+
.describe('Provider delegationSigned value; null when absent.'),
|
|
49
84
|
registrant_org: z
|
|
50
85
|
.string()
|
|
51
86
|
.optional()
|
|
52
|
-
.describe('
|
|
87
|
+
.describe('Public registrant organization from jCard org. Omitted when absent or a placeholder; contact redaction is independent.'),
|
|
53
88
|
registrant_redacted: z
|
|
54
89
|
.boolean()
|
|
55
|
-
.
|
|
90
|
+
.nullable()
|
|
91
|
+
.describe('True for explicit registrant redaction evidence; null when privacy evidence is absent.'),
|
|
56
92
|
}),
|
|
57
93
|
errors: [
|
|
58
|
-
{
|
|
59
|
-
reason: 'invalid_domain',
|
|
60
|
-
code: JsonRpcErrorCode.ValidationError,
|
|
61
|
-
when: 'Input is not a valid FQDN.',
|
|
62
|
-
recovery: 'Provide a valid fully-qualified domain name like "example.com" or "sub.example.org".',
|
|
63
|
-
},
|
|
64
94
|
{
|
|
65
95
|
reason: 'rdap_no_coverage',
|
|
66
96
|
code: JsonRpcErrorCode.NotFound,
|
|
@@ -70,18 +100,15 @@ export const whoisLookupDomain = tool('whois_lookup_domain', {
|
|
|
70
100
|
{
|
|
71
101
|
reason: 'domain_not_found',
|
|
72
102
|
code: JsonRpcErrorCode.NotFound,
|
|
73
|
-
when: 'RDAP server returned 404 — domain
|
|
74
|
-
recovery: '
|
|
103
|
+
when: 'RDAP server returned 404 — no domain record found.',
|
|
104
|
+
recovery: 'Use whois_check_availability for record status; a missing record does not establish registration eligibility.',
|
|
75
105
|
},
|
|
76
106
|
],
|
|
77
107
|
async handler(input, ctx) {
|
|
78
|
-
if (!isValidFqdn(input.domain)) {
|
|
79
|
-
throw ctx.fail('invalid_domain', `"${input.domain}" is not a valid FQDN.`);
|
|
80
|
-
}
|
|
81
108
|
ctx.log.info('RDAP domain lookup', { domain: input.domain });
|
|
82
109
|
let record;
|
|
83
110
|
try {
|
|
84
|
-
record = await getRdapService().lookupDomain(input.domain, ctx);
|
|
111
|
+
record = await getRdapService().lookupDomain(input.domain, ctx, input.include_registrar);
|
|
85
112
|
}
|
|
86
113
|
catch (err) {
|
|
87
114
|
// Re-throw domain_not_found with recovery hint from the typed contract
|
|
@@ -121,14 +148,26 @@ export const whoisLookupDomain = tool('whois_lookup_domain', {
|
|
|
121
148
|
lines.push(`**RDAP DB Updated:** ${result.rdap_last_updated}`);
|
|
122
149
|
if (result.handle)
|
|
123
150
|
lines.push(`**Handle:** ${result.handle}`);
|
|
124
|
-
lines.push(`**DNSSEC:** ${result.dnssec_signed ? 'Signed' : 'Not signed'}`);
|
|
125
|
-
lines.push(`**Registrant Redacted:** ${result.registrant_redacted ? 'Yes (GDPR/privacy)' : 'No'}`);
|
|
151
|
+
lines.push(`**DNSSEC:** ${result.dnssec_signed === null ? 'Unknown' : result.dnssec_signed ? 'Signed' : 'Not signed'}`);
|
|
152
|
+
lines.push(`**Registrant Redacted:** ${result.registrant_redacted === null ? 'Unknown' : result.registrant_redacted ? 'Yes (GDPR/privacy)' : 'No'}`);
|
|
126
153
|
if (result.registrant_org)
|
|
127
154
|
lines.push(`**Registrant Org:** ${result.registrant_org}`);
|
|
128
155
|
if (result.status.length > 0)
|
|
129
156
|
lines.push(`**Status:** ${result.status.join(', ')}`);
|
|
130
157
|
if (result.nameservers.length > 0)
|
|
131
158
|
lines.push(`**Nameservers:** ${result.nameservers.join(', ')}`);
|
|
159
|
+
if (result.registrar_detail) {
|
|
160
|
+
const detail = result.registrar_detail;
|
|
161
|
+
lines.push(`**Registrar Detail:** ${detail.status}`);
|
|
162
|
+
if (detail.source)
|
|
163
|
+
lines.push(`**Registrar Source:** ${detail.source}`);
|
|
164
|
+
if (detail.registrant_org)
|
|
165
|
+
lines.push(`**Registrar Registrant Org:** ${detail.registrant_org}`);
|
|
166
|
+
if (detail.status === 'found')
|
|
167
|
+
lines.push(`**Registrar Registrant Redacted:** ${detail.registrant_redacted === null ? 'Unknown' : detail.registrant_redacted ? 'Yes' : 'No'}`);
|
|
168
|
+
if (detail.source_error)
|
|
169
|
+
lines.push(`**Registrar Detail Error:** ${detail.source_error}`);
|
|
170
|
+
}
|
|
132
171
|
return [{ type: 'text', text: lines.join('\n') }];
|
|
133
172
|
},
|
|
134
173
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whois-lookup-domain.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-domain.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"whois-lookup-domain.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-domain.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@ export declare const whoisLookupIp: import("@cyanheads/mcp-ts-core").ToolDefinit
|
|
|
12
12
|
start_address: z.ZodOptional<z.ZodString>;
|
|
13
13
|
end_address: z.ZodOptional<z.ZodString>;
|
|
14
14
|
cidr: z.ZodOptional<z.ZodString>;
|
|
15
|
+
cidrs: z.ZodArray<z.ZodString>;
|
|
15
16
|
ip_version: z.ZodOptional<z.ZodString>;
|
|
16
17
|
name: z.ZodOptional<z.ZodString>;
|
|
17
18
|
type: z.ZodOptional<z.ZodString>;
|
|
@@ -19,8 +20,21 @@ export declare const whoisLookupIp: import("@cyanheads/mcp-ts-core").ToolDefinit
|
|
|
19
20
|
org_name: z.ZodOptional<z.ZodString>;
|
|
20
21
|
abuse_email: z.ZodOptional<z.ZodString>;
|
|
21
22
|
ptr: z.ZodNullable<z.ZodString>;
|
|
23
|
+
ptr_status: z.ZodEnum<{
|
|
24
|
+
failed: "failed";
|
|
25
|
+
found: "found";
|
|
26
|
+
not_found: "not_found";
|
|
27
|
+
}>;
|
|
28
|
+
ptr_source_error: z.ZodOptional<z.ZodString>;
|
|
22
29
|
rdap_source: z.ZodOptional<z.ZodString>;
|
|
23
30
|
}, z.core.$strip>, readonly [{
|
|
31
|
+
readonly reason: "ip_no_rdap_route";
|
|
32
|
+
readonly code: JsonRpcErrorCode.NotFound;
|
|
33
|
+
readonly when: "A successfully loaded IANA bootstrap has no covering RIR route.";
|
|
34
|
+
readonly recovery: "Try another address; this range has no RDAP route in the IANA bootstrap.";
|
|
35
|
+
readonly retryable: false;
|
|
36
|
+
readonly thrownBy: "service";
|
|
37
|
+
}, {
|
|
24
38
|
readonly reason: "invalid_ip";
|
|
25
39
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
26
40
|
readonly when: "Input is not a valid IPv4, IPv6, or CIDR address.";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whois-lookup-ip.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-ip.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"whois-lookup-ip.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-ip.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAKjE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA6IxB,CAAC"}
|
|
@@ -6,17 +6,21 @@ import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
|
6
6
|
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
import { getDohService } from '../../../services/doh/doh-service.js';
|
|
8
8
|
import { getRdapService, ipv4ToPtr, ipv6ToPtr, validateIp } from '../../../services/rdap/rdap-service.js';
|
|
9
|
+
import { IP_PATTERN } from './_fqdn.js';
|
|
9
10
|
export const whoisLookupIp = tool('whois_lookup_ip', {
|
|
10
11
|
title: 'IP Address / Network Lookup',
|
|
11
12
|
description: 'Look up an IP address or CIDR block via RIR RDAP (ARIN, RIPE, APNIC, LACNIC, AFRINIC — auto-routed ' +
|
|
12
|
-
'via IANA bootstrap). Returns netblock, org, country,
|
|
13
|
-
'via DoH. PTR
|
|
13
|
+
'via IANA bootstrap). Returns netblock, org, country, all provider CIDRs, abuse contact email, and reverse DNS (PTR) ' +
|
|
14
|
+
'via DoH. PTR status distinguishes found, not_found, and failed with ptr_source_error. Alias traversal is limited ' +
|
|
15
|
+
'to five transitions under one DNS deadline. The base address is queried for CIDR input. ' +
|
|
14
16
|
'The server excludes IPv4 0/8, 10/8, 100.64/10, 127/8, 169.254/16, 172.16/12, 192.168/16, 255/8 ' +
|
|
15
17
|
'and IPv6 ::1/128, fc00::/7, fe80::/10. Other special-use addresses remain eligible for lookup.',
|
|
16
18
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
17
19
|
input: z.object({
|
|
18
20
|
ip: z
|
|
19
21
|
.string()
|
|
22
|
+
.min(1)
|
|
23
|
+
.regex(IP_PATTERN, 'Provide an IPv4/IPv6 address with at most one decimal CIDR prefix; no spaces, brackets or zone IDs.')
|
|
20
24
|
.describe('IPv4 address (e.g., "8.8.8.8"), IPv6 address (e.g., "2001:4860:4860::8888"), or CIDR notation ' +
|
|
21
25
|
'(e.g., "192.0.2.0/24"). One decimal prefix in 0–32 (IPv4) or 0–128 (IPv6); no whitespace, ' +
|
|
22
26
|
'zone IDs, or brackets. IPv4-mapped IPv6 uses its embedded IPv4 for lookup and PTR.'),
|
|
@@ -26,7 +30,13 @@ export const whoisLookupIp = tool('whois_lookup_ip', {
|
|
|
26
30
|
handle: z.string().optional().describe('RIR handle / object identifier.'),
|
|
27
31
|
start_address: z.string().optional().describe('Start address of the IP netblock.'),
|
|
28
32
|
end_address: z.string().optional().describe('End address of the IP netblock.'),
|
|
29
|
-
cidr: z
|
|
33
|
+
cidr: z
|
|
34
|
+
.string()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe('Provider CIDR only when the allocation has exactly one component.'),
|
|
37
|
+
cidrs: z
|
|
38
|
+
.array(z.string())
|
|
39
|
+
.describe('All provider CIDR components in upstream order; empty when absent.'),
|
|
30
40
|
ip_version: z.string().optional().describe('IP version: "v4" or "v6".'),
|
|
31
41
|
name: z.string().optional().describe('Network name assigned by the RIR.'),
|
|
32
42
|
type: z.string().optional().describe('Network type (e.g., "DIRECT ALLOCATION").'),
|
|
@@ -40,12 +50,27 @@ export const whoisLookupIp = tool('whois_lookup_ip', {
|
|
|
40
50
|
.string()
|
|
41
51
|
.nullable()
|
|
42
52
|
.describe('Reverse DNS hostname (PTR record). Null when PTR lookup fails, returns no answer, or domain is NXDOMAIN.'),
|
|
53
|
+
ptr_status: z
|
|
54
|
+
.enum(['found', 'not_found', 'failed'])
|
|
55
|
+
.describe('PTR outcome: matching hostname, successful absence, or failed resolver/alias traversal.'),
|
|
56
|
+
ptr_source_error: z
|
|
57
|
+
.string()
|
|
58
|
+
.optional()
|
|
59
|
+
.describe('PTR failure explanation; RDAP data remains usable.'),
|
|
43
60
|
rdap_source: z
|
|
44
61
|
.string()
|
|
45
62
|
.optional()
|
|
46
63
|
.describe('RIR that provided the RDAP data (ARIN, RIPE, APNIC, LACNIC, AFRINIC).'),
|
|
47
64
|
}),
|
|
48
65
|
errors: [
|
|
66
|
+
{
|
|
67
|
+
reason: 'ip_no_rdap_route',
|
|
68
|
+
code: JsonRpcErrorCode.NotFound,
|
|
69
|
+
when: 'A successfully loaded IANA bootstrap has no covering RIR route.',
|
|
70
|
+
recovery: 'Try another address; this range has no RDAP route in the IANA bootstrap.',
|
|
71
|
+
retryable: false,
|
|
72
|
+
thrownBy: 'service',
|
|
73
|
+
},
|
|
49
74
|
{
|
|
50
75
|
reason: 'invalid_ip',
|
|
51
76
|
code: JsonRpcErrorCode.ValidationError,
|
|
@@ -79,7 +104,7 @@ export const whoisLookupIp = tool('whois_lookup_ip', {
|
|
|
79
104
|
const { base, isIpv6 } = parsed;
|
|
80
105
|
const ptrName = isIpv6 ? ipv6ToPtr(base) : ipv4ToPtr(base);
|
|
81
106
|
const ptr = await getDohService().ptrLookup(ptrName, ctx);
|
|
82
|
-
return { ...network, ptr };
|
|
107
|
+
return { ...network, ...ptr };
|
|
83
108
|
},
|
|
84
109
|
format: (result) => {
|
|
85
110
|
const lines = [];
|
|
@@ -88,8 +113,8 @@ export const whoisLookupIp = tool('whois_lookup_ip', {
|
|
|
88
113
|
lines.push(`**RIR Source:** ${result.rdap_source}`);
|
|
89
114
|
if (result.org_name)
|
|
90
115
|
lines.push(`**Organization:** ${result.org_name}`);
|
|
91
|
-
if (result.
|
|
92
|
-
lines.push(`**
|
|
116
|
+
if (result.cidrs.length)
|
|
117
|
+
lines.push(`**CIDRs:** ${result.cidrs.join(', ')}`);
|
|
93
118
|
if (result.start_address && result.end_address) {
|
|
94
119
|
lines.push(`**Range:** ${result.start_address} — ${result.end_address}`);
|
|
95
120
|
}
|
|
@@ -106,6 +131,9 @@ export const whoisLookupIp = tool('whois_lookup_ip', {
|
|
|
106
131
|
if (result.abuse_email)
|
|
107
132
|
lines.push(`**Abuse Email:** ${result.abuse_email}`);
|
|
108
133
|
lines.push(`**Reverse DNS (PTR):** ${result.ptr ?? 'Not available'}`);
|
|
134
|
+
lines.push(`**PTR Status:** ${result.ptr_status}`);
|
|
135
|
+
if (result.ptr_source_error)
|
|
136
|
+
lines.push(`**PTR Error:** ${result.ptr_source_error}`);
|
|
109
137
|
return [{ type: 'text', text: lines.join('\n') }];
|
|
110
138
|
},
|
|
111
139
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whois-lookup-ip.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-ip.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"whois-lookup-ip.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-ip.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import type { Context } from '@cyanheads/mcp-ts-core';
|
|
7
7
|
import type { AppConfig } from '@cyanheads/mcp-ts-core/config';
|
|
8
8
|
import type { StorageService } from '@cyanheads/mcp-ts-core/storage';
|
|
9
|
-
import type { DnsLookupResult, DnsRecordType } from './types.js';
|
|
9
|
+
import type { DnsLookupResult, DnsRecordType, PtrLookupResult } from './types.js';
|
|
10
10
|
export declare class DohService {
|
|
11
11
|
/** Fetch DNS records for one type from a single DoH endpoint */
|
|
12
12
|
private fetchSingleType;
|
|
@@ -21,9 +21,9 @@ export declare class DohService {
|
|
|
21
21
|
* Perform a reverse DNS (PTR) lookup for an IP address.
|
|
22
22
|
* IPv4: reverses octets + .in-addr.arpa
|
|
23
23
|
* IPv6: reverses nibbles + .ip6.arpa
|
|
24
|
-
*
|
|
24
|
+
* Follows reachable aliases under one deadline; distinguishes absence from failure.
|
|
25
25
|
*/
|
|
26
|
-
ptrLookup(ptrName: string, ctx: Context): Promise<
|
|
26
|
+
ptrLookup(ptrName: string, ctx: Context): Promise<PtrLookupResult>;
|
|
27
27
|
}
|
|
28
28
|
export declare function initDohService(_config: AppConfig, _storage: StorageService): void;
|
|
29
29
|
export declare function getDohService(): DohService;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doh-service.d.ts","sourceRoot":"","sources":["../../../src/services/doh/doh-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"doh-service.d.ts","sourceRoot":"","sources":["../../../src/services/doh/doh-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGrE,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EAGb,eAAe,EAChB,MAAM,YAAY,CAAC;AAWpB,qBAAa,UAAU;IACrB,gEAAgE;IAChE,OAAO,CAAC,eAAe;IA8CvB;;;;;OAKG;IACG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CA4D3F;IAED;;;;;OAKG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CA2CvE;CACF;AAMD,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAEjF;AAED,wBAAgB,aAAa,IAAI,UAAU,CAK1C"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* CAA records always use NextDNS because Cloudflare returns raw hex wire format for them.
|
|
4
4
|
* @module services/doh/doh-service
|
|
5
5
|
*/
|
|
6
|
+
import { serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
|
|
6
7
|
import { fetchWithTimeout, withRetry } from '@cyanheads/mcp-ts-core/utils';
|
|
7
8
|
import { getServerConfig } from '../../config/server-config.js';
|
|
8
9
|
import { DNS_TYPE_NUMBERS } from './types.js';
|
|
@@ -15,13 +16,26 @@ export class DohService {
|
|
|
15
16
|
fetchSingleType(domain, type, baseUrl, timeoutMs, ctx, source) {
|
|
16
17
|
const url = `${baseUrl}?name=${encodeURIComponent(domain)}&type=${encodeURIComponent(type)}`;
|
|
17
18
|
return withRetry(async () => {
|
|
19
|
+
ctx.signal.throwIfAborted();
|
|
18
20
|
const response = await fetchWithTimeout(url, timeoutMs, ctx, {
|
|
19
21
|
headers: {
|
|
20
22
|
Accept: 'application/dns-json',
|
|
21
23
|
},
|
|
22
24
|
signal: ctx.signal,
|
|
23
25
|
});
|
|
24
|
-
|
|
26
|
+
const data = (await response.json());
|
|
27
|
+
ctx.signal.throwIfAborted();
|
|
28
|
+
if (data.TC === true || (data.Status !== 0 && data.Status !== 3)) {
|
|
29
|
+
throw serviceUnavailable(`DNS ${type} query via ${source} failed: ${data.TC ? 'truncated response' : `RCODE ${data.Status}`}.`, {
|
|
30
|
+
reason: 'dns_response_failed',
|
|
31
|
+
type,
|
|
32
|
+
resolver: source,
|
|
33
|
+
status: data.Status,
|
|
34
|
+
truncated: data.TC === true,
|
|
35
|
+
recovery: { hint: 'Retry the DNS query later or choose another record type.' },
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return data;
|
|
25
39
|
}, {
|
|
26
40
|
operation: `doh.fetchSingleType.${source}`,
|
|
27
41
|
context: ctx,
|
|
@@ -37,6 +51,7 @@ export class DohService {
|
|
|
37
51
|
* Returns `nxdomain: true` when NXDOMAIN (Status 3) is returned.
|
|
38
52
|
*/
|
|
39
53
|
async lookup(domain, types, ctx) {
|
|
54
|
+
ctx.signal.throwIfAborted();
|
|
40
55
|
const config = getServerConfig();
|
|
41
56
|
const records = [];
|
|
42
57
|
let nxdomain = false;
|
|
@@ -48,7 +63,10 @@ export class DohService {
|
|
|
48
63
|
try {
|
|
49
64
|
resp = await this.fetchSingleType(domain, type, primaryUrl, config.dohTimeoutMs, ctx, source);
|
|
50
65
|
}
|
|
51
|
-
catch {
|
|
66
|
+
catch (error) {
|
|
67
|
+
ctx.signal.throwIfAborted();
|
|
68
|
+
if (type === 'CAA')
|
|
69
|
+
throw error;
|
|
52
70
|
// Fallback to NextDNS for non-CAA types
|
|
53
71
|
resp = await this.fetchSingleType(domain, type, NEXTDNS_DOH, config.dohTimeoutMs, ctx, 'nextdns');
|
|
54
72
|
source = 'nextdns';
|
|
@@ -80,20 +98,51 @@ export class DohService {
|
|
|
80
98
|
* Perform a reverse DNS (PTR) lookup for an IP address.
|
|
81
99
|
* IPv4: reverses octets + .in-addr.arpa
|
|
82
100
|
* IPv6: reverses nibbles + .ip6.arpa
|
|
83
|
-
*
|
|
101
|
+
* Follows reachable aliases under one deadline; distinguishes absence from failure.
|
|
84
102
|
*/
|
|
85
103
|
async ptrLookup(ptrName, ctx) {
|
|
104
|
+
const signal = AbortSignal.any([
|
|
105
|
+
ctx.signal,
|
|
106
|
+
AbortSignal.timeout(getServerConfig().dohTimeoutMs),
|
|
107
|
+
]);
|
|
108
|
+
const ptrCtx = { ...ctx, signal };
|
|
109
|
+
const normalize = (name) => name.toLowerCase().replace(/\.$/, '');
|
|
110
|
+
let owner = normalize(ptrName);
|
|
111
|
+
let hops = 0;
|
|
112
|
+
const visited = new Set([owner]);
|
|
86
113
|
try {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
114
|
+
while (true) {
|
|
115
|
+
signal.throwIfAborted();
|
|
116
|
+
const result = await this.lookup(owner, ['PTR'], ptrCtx);
|
|
117
|
+
if (result.nxdomain)
|
|
118
|
+
return { ptr: null, ptr_status: 'not_found' };
|
|
119
|
+
let followed = false;
|
|
120
|
+
while (true) {
|
|
121
|
+
const ptr = result.records.find((record) => record.type === 'PTR' && normalize(record.name) === owner);
|
|
122
|
+
if (ptr)
|
|
123
|
+
return { ptr: normalize(ptr.data), ptr_status: 'found' };
|
|
124
|
+
const alias = result.records.find((record) => record.type === 'CNAME' && normalize(record.name) === owner);
|
|
125
|
+
if (!alias)
|
|
126
|
+
break;
|
|
127
|
+
const target = normalize(alias.data);
|
|
128
|
+
if (visited.has(target) || hops === 5)
|
|
129
|
+
throw serviceUnavailable('Reverse DNS alias loop or five-transition limit reached.');
|
|
130
|
+
visited.add(target);
|
|
131
|
+
owner = target;
|
|
132
|
+
hops++;
|
|
133
|
+
followed = true;
|
|
134
|
+
}
|
|
135
|
+
if (!followed)
|
|
136
|
+
return { ptr: null, ptr_status: 'not_found' };
|
|
137
|
+
}
|
|
94
138
|
}
|
|
95
|
-
catch {
|
|
96
|
-
|
|
139
|
+
catch (error) {
|
|
140
|
+
ctx.signal.throwIfAborted();
|
|
141
|
+
return {
|
|
142
|
+
ptr: null,
|
|
143
|
+
ptr_status: 'failed',
|
|
144
|
+
ptr_source_error: error instanceof Error ? error.message : String(error),
|
|
145
|
+
};
|
|
97
146
|
}
|
|
98
147
|
}
|
|
99
148
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doh-service.js","sourceRoot":"","sources":["../../../src/services/doh/doh-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"doh-service.js","sourceRoot":"","sources":["../../../src/services/doh/doh-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -46,4 +46,16 @@ export interface DnsLookupResult {
|
|
|
46
46
|
records: NormalizedDnsRecord[];
|
|
47
47
|
source: 'cloudflare' | 'nextdns';
|
|
48
48
|
}
|
|
49
|
+
/** Best-effort reverse lookup distinguishes a hostname, successful absence and failure. */
|
|
50
|
+
export type PtrLookupResult = {
|
|
51
|
+
ptr: string;
|
|
52
|
+
ptr_status: 'found';
|
|
53
|
+
} | {
|
|
54
|
+
ptr: null;
|
|
55
|
+
ptr_status: 'not_found';
|
|
56
|
+
} | {
|
|
57
|
+
ptr: null;
|
|
58
|
+
ptr_status: 'failed';
|
|
59
|
+
ptr_source_error: string;
|
|
60
|
+
};
|
|
49
61
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/doh/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GAAG,GAAG,GAAG,MAAM,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEjG,6BAA6B;AAC7B,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAU1D,CAAC;AAEF,uCAAuC;AACvC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,4BAA4B;AAC5B,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,OAAO,CAAC;CACd;AAED,qCAAqC;AACrC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,MAAM,EAAE,YAAY,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;IAChF,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,MAAM,EAAE,YAAY,GAAG,SAAS,CAAC;CAClC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/doh/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GAAG,GAAG,GAAG,MAAM,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEjG,6BAA6B;AAC7B,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAU1D,CAAC;AAEF,uCAAuC;AACvC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,4BAA4B;AAC5B,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,OAAO,CAAC;CACd;AAED,qCAAqC;AACrC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,MAAM,EAAE,YAAY,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;IAChF,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,MAAM,EAAE,YAAY,GAAG,SAAS,CAAC;CAClC;AAED,2FAA2F;AAC3F,MAAM,MAAM,eAAe,GACvB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,GACpC;IAAE,GAAG,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,WAAW,CAAA;CAAE,GACtC;IAAE,GAAG,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,QAAQ,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
|
@@ -34,19 +34,24 @@ export declare class RdapService {
|
|
|
34
34
|
/** Find the RDAP server URL for an ASN via IANA bootstrap */
|
|
35
35
|
findAsnRdapServer(asnNum: number, ctx: Context): Promise<string | null>;
|
|
36
36
|
/** Look up a domain registration record via RDAP */
|
|
37
|
-
lookupDomain(domain: string, ctx: Context): Promise<NormalizedDomain>;
|
|
37
|
+
lookupDomain(domain: string, ctx: Context, includeRegistrar?: boolean): Promise<NormalizedDomain>;
|
|
38
|
+
/** One optional registrar exchange, with guarded redirects and a total deadline. */
|
|
39
|
+
private registrarDetail;
|
|
38
40
|
/**
|
|
39
|
-
* Check
|
|
40
|
-
*
|
|
41
|
-
* or `{ available: null }` when TLD has no RDAP coverage.
|
|
41
|
+
* Check registry record presence; a miss never establishes registration eligibility.
|
|
42
|
+
* Recognized ICANN subdomains are rejected without querying their parent.
|
|
42
43
|
*/
|
|
43
44
|
checkAvailability(domain: string, ctx: Context): Promise<{
|
|
44
|
-
available:
|
|
45
|
+
available: null;
|
|
46
|
+
registration_status: 'not_found';
|
|
47
|
+
rdap_coverage: true;
|
|
45
48
|
} | {
|
|
46
49
|
available: false;
|
|
50
|
+
registration_status: 'registered';
|
|
47
51
|
record: NormalizedDomain;
|
|
48
52
|
} | {
|
|
49
53
|
available: null;
|
|
54
|
+
registration_status: 'unknown';
|
|
50
55
|
rdap_coverage: false;
|
|
51
56
|
}>;
|
|
52
57
|
/** Look up an IP address or CIDR via RIR RDAP */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rdap-service.d.ts","sourceRoot":"","sources":["../../../src/services/rdap/rdap-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAO/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"rdap-service.d.ts","sourceRoot":"","sources":["../../../src/services/rdap/rdap-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAO/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAIrE,OAAO,KAAK,EAEV,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EAMpB,MAAM,YAAY,CAAC;AAUpB,qFAAqF;AACrF,KAAK,QAAQ,GAAG;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhG,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,CAuBlE;AAuBD,wDAAwD;AACxD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE5C;AAsBD,wDAAwD;AACxD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAG5C;AA0ND,qBAAa,WAAW;IACtB,OAAO,CAAC,cAAc,CAAsE;IAE5F,iDAAiD;YACnC,cAAc;IAgB5B,qEAAqE;IAC/D,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAe/E;IAED,oEAAoE;IAC9D,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiDxF;IAED,6DAA6D;IACvD,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAe5E;IAED,oDAAoD;IAC9C,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,OAAO,EACZ,gBAAgB,UAAQ,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAoD3B;IAED,oFAAoF;YACtE,eAAe;IAqE7B;;;OAGG;IACG,iBAAiB,CACrB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,OAAO,GACX,OAAO,CACN;QAAE,SAAS,EAAE,IAAI,CAAC;QAAC,mBAAmB,EAAE,WAAW,CAAC;QAAC,aAAa,EAAE,IAAI,CAAA;KAAE,GAC1E;QAAE,SAAS,EAAE,KAAK,CAAC;QAAC,mBAAmB,EAAE,YAAY,CAAC;QAAC,MAAM,EAAE,gBAAgB,CAAA;KAAE,GACjF;QAAE,SAAS,EAAE,IAAI,CAAC;QAAC,mBAAmB,EAAE,SAAS,CAAC;QAAC,aAAa,EAAE,KAAK,CAAA;KAAE,CAC5E,CAkDA;IAED,iDAAiD;IAC3C,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAiErE;IAED,kCAAkC;IAC5B,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAwDjE;CACF;AAMD,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAElF;AAED,wBAAgB,cAAc,IAAI,WAAW,CAK5C"}
|