@cyanheads/whois-mcp-server 0.1.5 → 0.1.6

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 (39) hide show
  1. package/AGENTS.md +9 -8
  2. package/CLAUDE.md +9 -8
  3. package/Dockerfile +44 -33
  4. package/README.md +15 -29
  5. package/changelog/0.1.x/0.1.6.md +41 -0
  6. package/dist/app.d.ts +21 -4
  7. package/dist/app.d.ts.map +1 -1
  8. package/dist/mcp-server/tools/definitions/whois-check-availability.tool.d.ts.map +1 -1
  9. package/dist/mcp-server/tools/definitions/whois-check-availability.tool.js +1 -3
  10. package/dist/mcp-server/tools/definitions/whois-check-availability.tool.js.map +1 -1
  11. package/dist/mcp-server/tools/definitions/whois-get-dns.tool.d.ts +17 -0
  12. package/dist/mcp-server/tools/definitions/whois-get-dns.tool.d.ts.map +1 -1
  13. package/dist/mcp-server/tools/definitions/whois-get-dns.tool.js +21 -14
  14. package/dist/mcp-server/tools/definitions/whois-get-dns.tool.js.map +1 -1
  15. package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.d.ts.map +1 -1
  16. package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.js +39 -31
  17. package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.js.map +1 -1
  18. package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.d.ts +2 -2
  19. package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.d.ts.map +1 -1
  20. package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.js +6 -5
  21. package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.js.map +1 -1
  22. package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.d.ts.map +1 -1
  23. package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.js +2 -5
  24. package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.js.map +1 -1
  25. package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.d.ts +2 -2
  26. package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.d.ts.map +1 -1
  27. package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.js +11 -12
  28. package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.js.map +1 -1
  29. package/dist/services/doh/doh-service.d.ts.map +1 -1
  30. package/dist/services/doh/doh-service.js +10 -12
  31. package/dist/services/doh/doh-service.js.map +1 -1
  32. package/dist/services/doh/types.d.ts +4 -0
  33. package/dist/services/doh/types.d.ts.map +1 -1
  34. package/dist/services/rdap/rdap-service.d.ts +10 -3
  35. package/dist/services/rdap/rdap-service.d.ts.map +1 -1
  36. package/dist/services/rdap/rdap-service.js +67 -109
  37. package/dist/services/rdap/rdap-service.js.map +1 -1
  38. package/package.json +8 -7
  39. package/server.json +3 -3
package/AGENTS.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** whois-mcp-server
4
- **Version:** 0.1.5
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.6`
4
+ **Version:** 0.1.6
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.10`
6
6
  **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
- **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0
7
+ **MCP SDK:** `@modelcontextprotocol/server` ^2.1.0
8
8
  **Zod:** ^4.6.5
9
9
 
10
10
  > **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
@@ -151,13 +151,14 @@ Handlers receive a unified `ctx` object. Key properties:
151
151
  | Property | Description |
152
152
  |:---------|:------------|
153
153
  | `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. Dual-sink: Pino **and** `notifications/message` to the client, so treat it as client-visible. |
154
- | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
154
+ | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any JSON-serializable value; reads return its JSON form (a `Date` comes back as an ISO string). |
155
155
  | `ctx.requestInput` | Suspend and ask the caller for more input — `return ctx.requestInput({ inputRequests: { key: inputRequired.elicit({ message, requestedSchema }) } })`. Never returns; the handler is re-entered with the answers. Always present. |
156
- | `ctx.inputs` | Reader over a retried request's responses — `.accepted(key, schema)`, `.view(key)`, `.state()`, `.dropped`. Empty on the first round. |
156
+ | `ctx.inputs` | The request's responses — `.accepted(key, schema)`, `.view(key)`, `.state()`, `.dropped` — limited to what the client declared (`elicitation` and its form/url modes, `sampling`, `roots`). Client-supplied: a consent gate trusts only a `ctx.state` record it stored when it asked, bound to the operation, caller, and target (see the `api-context` skill). |
157
+ | `ctx.clientCapabilities` | What the client declared for this request, `undefined` when no view exists. Decides whether to ask for optional context (e.g. roots); never a reason to skip a consent prompt. |
157
158
  | `ctx.enrich` | Success-path agent context (empty-result notices, query echo, pagination totals) — `ctx.enrich(...)` or `.notice()` / `.total()` / `.echo()` / `.truncated()`. Reaches `structuredContent` and `content[]`; lands only when the definition declares an `enrichment` block (no-op otherwise). |
158
159
  | `ctx.content` | Non-text content blocks — `.image(data, mimeType)`, `.audio(data, mimeType)`, or `ctx.content(block)` for a raw block. Prepended to `content[]` after `format()`; never enters `structuredContent`. |
159
160
  | `ctx.signal` | `AbortSignal` for cancellation. |
160
- | `ctx.requestId` | Unique request ID. |
161
+ | `ctx.requestId` | Request ID — the one every log record of the call carries and its error envelope returns as `data.requestId`. |
161
162
  | `ctx.tenantId` | Tenant ID from JWT; `'default'` for stdio or HTTP with auth off. |
162
163
 
163
164
  ---
@@ -166,7 +167,7 @@ Handlers receive a unified `ctx` object. Key properties:
166
167
 
167
168
  Handlers throw — the framework catches, classifies, and formats.
168
169
 
169
- **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable?, severity?, thrownBy? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, linter enforces conformance against the handler body. `recovery` is required (≥ 5 words, lint-validated) — the single source of truth for the agent's next move. Pass `ctx.recoveryFor('reason')` as the throw's data to put it on the wire (`data.recovery.hint`, mirrored into `content[]` text unless the message already contains it verbatim); override with an explicit `{ recovery: { hint: '...' } }` when dynamic runtime context matters. Forwarding it is lint-enforced per throw site (`error-contract-recovery-unforwarded`). Mark an entry the service layer throws with `thrownBy: 'service'` so `error-contract-unthrown` skips it — lint-only metadata, nothing at runtime reads it. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely and don't need declaring.
170
+ **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable?, severity?, thrownBy? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, linter enforces conformance against the handler body. `recovery` is required (≥ 5 words, lint-validated) — the single source of truth for the agent's next move. The framework puts it on the wire whenever a failure carrying that `reason` arrives without a hint — a bare `ctx.fail('reason')` or a service throw with `data: { reason }` — as `data.recovery.hint`, mirrored into `content[]` text unless the message already contains it verbatim; override with an explicit `{ recovery: { hint: '...' } }` when dynamic runtime context matters. Every error envelope also carries `data.requestId`, the id the server's log records for that call carry, and `content[]` closes with `(reason … · request <id>)`. Mark an entry the service layer throws with `thrownBy: 'service'` so `error-contract-unthrown` skips it — lint-only metadata, nothing at runtime reads it. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely and don't need declaring.
170
171
 
171
172
  ```ts
172
173
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
@@ -178,7 +179,7 @@ errors: [
178
179
  ],
179
180
  async handler(input, ctx) {
180
181
  const item = await db.find(input.id);
181
- if (!item) throw ctx.fail('no_match', `No item ${input.id}`, ctx.recoveryFor('no_match'));
182
+ if (!item) throw ctx.fail('no_match', `No item ${input.id}`);
182
183
  return item;
183
184
  }
184
185
  ```
package/CLAUDE.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** whois-mcp-server
4
- **Version:** 0.1.5
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.6`
4
+ **Version:** 0.1.6
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.10`
6
6
  **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
- **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0
7
+ **MCP SDK:** `@modelcontextprotocol/server` ^2.1.0
8
8
  **Zod:** ^4.6.5
9
9
 
10
10
  > **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
@@ -151,13 +151,14 @@ Handlers receive a unified `ctx` object. Key properties:
151
151
  | Property | Description |
152
152
  |:---------|:------------|
153
153
  | `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. Dual-sink: Pino **and** `notifications/message` to the client, so treat it as client-visible. |
154
- | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
154
+ | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any JSON-serializable value; reads return its JSON form (a `Date` comes back as an ISO string). |
155
155
  | `ctx.requestInput` | Suspend and ask the caller for more input — `return ctx.requestInput({ inputRequests: { key: inputRequired.elicit({ message, requestedSchema }) } })`. Never returns; the handler is re-entered with the answers. Always present. |
156
- | `ctx.inputs` | Reader over a retried request's responses — `.accepted(key, schema)`, `.view(key)`, `.state()`, `.dropped`. Empty on the first round. |
156
+ | `ctx.inputs` | The request's responses — `.accepted(key, schema)`, `.view(key)`, `.state()`, `.dropped` — limited to what the client declared (`elicitation` and its form/url modes, `sampling`, `roots`). Client-supplied: a consent gate trusts only a `ctx.state` record it stored when it asked, bound to the operation, caller, and target (see the `api-context` skill). |
157
+ | `ctx.clientCapabilities` | What the client declared for this request, `undefined` when no view exists. Decides whether to ask for optional context (e.g. roots); never a reason to skip a consent prompt. |
157
158
  | `ctx.enrich` | Success-path agent context (empty-result notices, query echo, pagination totals) — `ctx.enrich(...)` or `.notice()` / `.total()` / `.echo()` / `.truncated()`. Reaches `structuredContent` and `content[]`; lands only when the definition declares an `enrichment` block (no-op otherwise). |
158
159
  | `ctx.content` | Non-text content blocks — `.image(data, mimeType)`, `.audio(data, mimeType)`, or `ctx.content(block)` for a raw block. Prepended to `content[]` after `format()`; never enters `structuredContent`. |
159
160
  | `ctx.signal` | `AbortSignal` for cancellation. |
160
- | `ctx.requestId` | Unique request ID. |
161
+ | `ctx.requestId` | Request ID — the one every log record of the call carries and its error envelope returns as `data.requestId`. |
161
162
  | `ctx.tenantId` | Tenant ID from JWT; `'default'` for stdio or HTTP with auth off. |
162
163
 
163
164
  ---
@@ -166,7 +167,7 @@ Handlers receive a unified `ctx` object. Key properties:
166
167
 
167
168
  Handlers throw — the framework catches, classifies, and formats.
168
169
 
169
- **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable?, severity?, thrownBy? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, linter enforces conformance against the handler body. `recovery` is required (≥ 5 words, lint-validated) — the single source of truth for the agent's next move. Pass `ctx.recoveryFor('reason')` as the throw's data to put it on the wire (`data.recovery.hint`, mirrored into `content[]` text unless the message already contains it verbatim); override with an explicit `{ recovery: { hint: '...' } }` when dynamic runtime context matters. Forwarding it is lint-enforced per throw site (`error-contract-recovery-unforwarded`). Mark an entry the service layer throws with `thrownBy: 'service'` so `error-contract-unthrown` skips it — lint-only metadata, nothing at runtime reads it. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely and don't need declaring.
170
+ **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable?, severity?, thrownBy? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, linter enforces conformance against the handler body. `recovery` is required (≥ 5 words, lint-validated) — the single source of truth for the agent's next move. The framework puts it on the wire whenever a failure carrying that `reason` arrives without a hint — a bare `ctx.fail('reason')` or a service throw with `data: { reason }` — as `data.recovery.hint`, mirrored into `content[]` text unless the message already contains it verbatim; override with an explicit `{ recovery: { hint: '...' } }` when dynamic runtime context matters. Every error envelope also carries `data.requestId`, the id the server's log records for that call carry, and `content[]` closes with `(reason … · request <id>)`. Mark an entry the service layer throws with `thrownBy: 'service'` so `error-contract-unthrown` skips it — lint-only metadata, nothing at runtime reads it. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely and don't need declaring.
170
171
 
171
172
  ```ts
172
173
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
@@ -178,7 +179,7 @@ errors: [
178
179
  ],
179
180
  async handler(input, ctx) {
180
181
  const item = await db.find(input.id);
181
- if (!item) throw ctx.fail('no_match', `No item ${input.id}`, ctx.recoveryFor('no_match'));
182
+ if (!item) throw ctx.fail('no_match', `No item ${input.id}`);
182
183
  return item;
183
184
  }
184
185
  ```
package/Dockerfile CHANGED
@@ -4,7 +4,7 @@
4
4
  # This stage installs all dependencies (including dev), builds the TypeScript
5
5
  # source code into JavaScript, and prepares the production assets.
6
6
  # ==============================================================================
7
- FROM --platform=$BUILDPLATFORM oven/bun:1.4.0 AS build
7
+ FROM --platform=$BUILDPLATFORM oven/bun:1.4.2 AS build
8
8
 
9
9
  WORKDIR /usr/src/app
10
10
 
@@ -23,6 +23,45 @@ COPY . .
23
23
  RUN bun run build
24
24
 
25
25
 
26
+ # ==============================================================================
27
+ # Production Dependencies Stage
28
+ #
29
+ # Run the scanner and OTel installer natively, cross-installing dependencies for
30
+ # the target architecture. Only node_modules enters the production image.
31
+ # ==============================================================================
32
+ FROM --platform=$BUILDPLATFORM oven/bun:1.4.2 AS deps
33
+
34
+ WORKDIR /usr/src/app
35
+
36
+ COPY package.json bun.lock bunfig.toml ./
37
+
38
+ # Seed the scanner omitted by the production install; bunfig.toml retains both
39
+ # the scanner and release-age protections for all dependency resolution.
40
+ COPY --from=build /usr/src/app/node_modules/@socketsecurity/bun-security-scanner ./node_modules/@socketsecurity/bun-security-scanner
41
+
42
+ ARG TARGETOS
43
+ ARG TARGETARCH
44
+ RUN case "$TARGETARCH" in \
45
+ amd64) echo x64 ;; \
46
+ arm64) echo arm64 ;; \
47
+ *) echo "Unsupported TARGETARCH '$TARGETARCH': expected amd64 or arm64" >&2; exit 1 ;; \
48
+ esac > .bun-cpu
49
+
50
+ RUN --mount=type=cache,target=/root/.bun/install/cache \
51
+ bun install --production --omit=peer --frozen-lockfile --ignore-scripts \
52
+ --os="$TARGETOS" --cpu="$(cat .bun-cpu)"
53
+
54
+ # Read the OTel package list and ranges from the installed framework.
55
+ COPY scripts/install-otel.ts ./scripts/
56
+ ARG OTEL_ENABLED=true
57
+ RUN --mount=type=cache,target=/root/.bun/install/cache \
58
+ if [ "$OTEL_ENABLED" = "true" ]; then \
59
+ bun scripts/install-otel.ts --os="$TARGETOS" --cpu="$(cat .bun-cpu)"; \
60
+ fi
61
+
62
+ RUN rm -rf node_modules/@socketsecurity/bun-security-scanner
63
+
64
+
26
65
  # ==============================================================================
27
66
  # Production Stage
28
67
  #
@@ -30,7 +69,7 @@ RUN bun run build
30
69
  # application. It uses a slim base image and only includes production
31
70
  # dependencies and build artifacts.
32
71
  # ==============================================================================
33
- FROM oven/bun:1.4.0-slim AS production
72
+ FROM oven/bun:1.4.2-slim AS production
34
73
 
35
74
  WORKDIR /usr/src/app
36
75
 
@@ -46,36 +85,9 @@ LABEL org.opencontainers.image.source="https://github.com/cyanheads/whois-mcp-se
46
85
  LABEL org.opencontainers.image.licenses="Apache-2.0"
47
86
  LABEL org.opencontainers.image.version="${APP_VERSION}"
48
87
 
49
- # Copy dependency manifests
50
- COPY package.json bun.lock ./
51
-
52
- # Install only production dependencies, ignoring any lifecycle scripts (like 'prepare')
53
- # that are not needed in the final production image.
54
- # `--omit=peer` drops the framework's optional peer tiers (test runner, service
55
- # SDKs, parsers) that Bun would otherwise auto-install. Anything this server
56
- # actually imports belongs in its own `dependencies`, so nothing needed at
57
- # runtime is lost. The OTEL step below carries the same flag — without it, that
58
- # install re-resolves the graph and pulls every optional peer back in.
59
- RUN --mount=type=cache,target=/root/.bun/install/cache \
60
- bun install --production --omit=peer --frozen-lockfile --ignore-scripts
61
-
62
- # Conditionally install OpenTelemetry optional peer dependencies (Tier 3).
63
- # These are not bundled by default to keep the base image lean. Enable at build time
64
- # with: docker build --build-arg OTEL_ENABLED=true
65
- ARG OTEL_ENABLED=true
66
- RUN --mount=type=cache,target=/root/.bun/install/cache \
67
- if [ "$OTEL_ENABLED" = "true" ]; then \
68
- bun add --omit=dev --omit=peer --ignore-scripts @hono/otel \
69
- @opentelemetry/instrumentation-http \
70
- @opentelemetry/exporter-metrics-otlp-http \
71
- @opentelemetry/exporter-trace-otlp-http \
72
- @opentelemetry/instrumentation-pino \
73
- @opentelemetry/resources \
74
- @opentelemetry/sdk-metrics \
75
- @opentelemetry/sdk-node \
76
- @opentelemetry/sdk-trace-node \
77
- @opentelemetry/semantic-conventions; \
78
- fi
88
+ # Keep the original manifest; the deps-stage OTel install rewrites its copy.
89
+ COPY package.json ./
90
+ COPY --from=deps /usr/src/app/node_modules ./node_modules
79
91
 
80
92
  # Copy the compiled application code from the build stage
81
93
  COPY --from=build /usr/src/app/dist ./dist
@@ -101,7 +113,6 @@ ENV MCP_TRANSPORT_TYPE="http"
101
113
  ENV MCP_SESSION_MODE="stateless"
102
114
  ENV MCP_LOG_LEVEL="info"
103
115
  ENV LOGS_DIR="/var/log/whois-mcp-server"
104
- ENV MCP_FORCE_CONSOLE_LOGGING="true"
105
116
 
106
117
  # Expose the port the server listens on
107
118
  EXPOSE ${MCP_HTTP_PORT}
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  <div align="center">
9
9
 
10
- [![Version](https://img.shields.io/badge/Version-0.1.5-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/whois-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/whois-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/whois-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.0-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-0.1.6-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/whois-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.1.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/whois-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/whois-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.2-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
@@ -42,58 +42,44 @@ Domain and network intelligence via RDAP and DNS-over-HTTPS. Look up domain regi
42
42
 
43
43
  ### `whois_lookup_domain` <sub>tool</sub>
44
44
 
45
- - RDAP-first via IANA auto-bootstrap — automatically selects the correct registry RDAP server per TLD
46
- - Returns registrar, creation/expiry dates, nameservers, EPP status codes, and DNSSEC delegation flag
47
- - Surfaces `registrant_redacted: true` when privacy redaction is in effect (standard post-GDPR for gTLDs)
48
- - Throws `rdap_no_coverage` when the TLD has no RDAP server in the IANA bootstrap — use `whois_check_availability` instead
49
- - Throws `domain_not_found` on an RDAP 404 (domain not registered) — use `whois_check_availability` to confirm
45
+ - Accepts a fully qualified domain name and selects the registry RDAP server through IANA bootstrap.
46
+ - Returns registrar, registration dates, nameservers, EPP status, DNSSEC, and `registrant_redacted`; throws `rdap_no_coverage` or `domain_not_found` when no record can be returned.
50
47
 
51
48
  ---
52
49
 
53
50
  ### `whois_check_availability` <sub>tool</sub>
54
51
 
55
- - RDAP 404 response maps to `available: true`
56
- - Registered domains return `available: false` with `registrar` and `expiry_date`
57
- - `available: null` with `rdap_coverage: false` when the TLD has no RDAP coverage — availability cannot be determined
58
- - Thin response optimized for bulk name sweeps — no extra fields
52
+ - Accepts a fully qualified domain name for a registration check.
53
+ - Returns `available: true` for RDAP 404, `false` with registrar and expiry for a registered domain, or `null` with `rdap_coverage: false` when coverage is absent.
59
54
 
60
55
  ---
61
56
 
62
57
  ### `whois_get_dns` <sub>tool</sub>
63
58
 
64
- - Supports A, AAAA, MX, TXT, NS, CNAME, SOA, CAA, PTR; multiple types fetched in parallel; defaults to A, AAAA, MX, TXT, NS when `types` is omitted
65
- - Cloudflare primary, NextDNS fallback per type (CAA always uses NextDNS — Cloudflare returns raw hex wire format for it)
66
- - Returns records with TTLs and the resolving `source` (`cloudflare` or `nextdns`)
67
- - `nxdomain: true` in the result (not an error) when the domain doesn't exist in DNS
59
+ - Accepts a hostname and optional nonempty `types`: A, AAAA, MX, TXT, NS, CNAME, SOA, CAA, PTR; omission defaults to A, AAAA, MX, TXT, NS. Duplicate types are queried once.
60
+ - Returns records with TTLs and ordered `query_sources: [{type, source}]`, including empty answers and NXDOMAIN. Legacy `source` is `cloudflare` if any query consumed a successful Cloudflare response, otherwise `nextdns`; a nonexistent domain returns `nxdomain: true` as data.
68
61
 
69
62
  ---
70
63
 
71
64
  ### `whois_lookup_ip` <sub>tool</sub>
72
65
 
73
- - Accepts an IPv4/IPv6 address or CIDR block; auto-routes to the correct RIR (ARIN, RIPE, APNIC, LACNIC, AFRINIC) via IANA IP bootstrap
74
- - Returns netblock CIDR, org name, country, abuse contact email
75
- - Fetches PTR (reverse DNS) via DoH as a best-effort step — `ptr: null` on failure, not an error
76
- - Throws `private_range` for RFC 1918, loopback, and link-local addresses — no RIR RDAP record exists for them
77
- - Throws `ip_not_found` on an RIR RDAP 404
66
+ - Accepts a complete IPv4/IPv6 address with at most one decimal CIDR prefix (0–32 / 0–128); no whitespace, zone IDs, or brackets. Queries the base address and echoes the original `ip`. IPv4-mapped IPv6 uses the embedded IPv4 for policy, RDAP, and PTR; other IPv6 uses 32 reversed PTR nibbles.
67
+ - Returns netblock CIDR, organization, country, abuse contact, and best-effort PTR (`null` on failure); throws `invalid_ip` for malformed input or `ip_not_found` on an RIR RDAP 404.
68
+ - `private_range` enforces an explicit policy: IPv4 `0.0.0.0/8`, `10.0.0.0/8`, `100.64.0.0/10`, `127.0.0.0/8`, `169.254.0.0/16`, `172.16.0.0/12`, `192.168.0.0/16`, `255.0.0.0/8`; IPv6 `::1/128`, `fc00::/7`, `fe80::/10`. Other special-use addresses remain eligible for registry records or normal no-coverage/not-found outcomes.
78
69
 
79
70
  ---
80
71
 
81
72
  ### `whois_lookup_asn` <sub>tool</sub>
82
73
 
83
- - Accepts `AS15169` or bare integer `15169` format
84
- - Routes to the correct RIR RDAP endpoint via IANA ASN bootstrap
85
- - Returns `name`, `org_name`, `country`, `rir`, `start_autnum`, `end_autnum`
86
- - Throws `asn_not_found` on an RIR RDAP 404
74
+ - Accepts a decimal ASN from 1 to 4294967295 with an optional case-insensitive `AS` prefix and leading `+` (e.g., `AS15169`, `AS 15169`, `+15169`). Outer whitespace and whitespace after `AS` are allowed; whitespace inside digits or after `+`, suffixes, decimals, and out-of-range values return `invalid_asn`.
75
+ - Returns `name`, `org_name`, `country`, `rir`, `start_autnum`, and `end_autnum`; throws `asn_not_found` when no ASN record exists.
87
76
 
88
77
  ---
89
78
 
90
79
  ### `whois_get_dossier` <sub>tool</sub>
91
80
 
92
- - Runs RDAP domain lookup and DoH (A, MX, NS, TXT) in parallel via `Promise.allSettled`
93
- - Inferred signals: `age_days`, `privacy_redacted`, `registrar`, `ns_provider` (from NS records), `mx_provider` (from MX records)
94
- - No synthesized risk scores — factual signals only; the agent decides the verdict
95
- - Partial results surfaced when one leg fails (`rdap_source_error` / `dns_source_error` on the failed leg)
96
- - Throws `both_legs_failed` only when both RDAP and DNS fail; individual leg failures are data, not errors
81
+ - Accepts a fully qualified domain name for parallel registration and A/MX/NS/TXT lookups.
82
+ - Returns registration, DNS, domain age, privacy status, and inferred NS/MX providers. Individual failures remain partial data in `rdap_source_error` or `dns_source_error`; `both_legs_failed` means neither source succeeded.
97
83
 
98
84
  ---
99
85
 
@@ -182,7 +168,7 @@ MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
182
168
 
183
169
  ### Prerequisites
184
170
 
185
- - [Bun v1.3.0](https://bun.sh/) or higher (or Node.js v24+).
171
+ - [Bun v1.4.0](https://bun.sh/) or higher (or Node.js v24+).
186
172
  - No API keys required — all data sources are public.
187
173
 
188
174
  ### Installation
@@ -0,0 +1,41 @@
1
+ ---
2
+ summary: "Lookup inputs are validated whole before any request, DNS results attribute each query to its resolver, and the dossier renders every TXT record and labels providers by domain."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.1.6 — 2026-09-30
8
+
9
+ ## Added
10
+
11
+ - **`whois_get_dns` `query_sources`** ([#10](https://github.com/cyanheads/whois-mcp-server/issues/10)) — one `{type, source}` entry per requested type, in request order, naming the resolver whose response was consumed, empty answers and NXDOMAIN included. Duplicate types are queried once; `source` stays the aggregate (`cloudflare` when any query used Cloudflare, otherwise `nextdns`).
12
+ - **Contract tests over the real services** — `tests/helpers/upstream.ts` replaces only outbound HTTP, and `tests/fixtures/` holds captured IANA, ARIN, and APNIC responses that the IP suite replays.
13
+
14
+ ## Changed
15
+
16
+ - **Framework `@cyanheads/mcp-ts-core` `^0.13.6` → `^0.13.10`** — tool errors carry `data.requestId` and their text closes with `request <id>`, an integer sent for a string argument is repaired to its digits, and framework-built errors keep stack traces and request context out of `data`.
17
+ - **Recovery hints reach the wire through the framework's contract fill** — throws whose `errors[]` entry supplies the hint no longer forward `ctx.recoveryFor`.
18
+ - **Docker image** — production dependencies and the OpenTelemetry peers install in a `deps` stage on the build platform through `scripts/install-otel.ts`, at the framework's declared peer ranges, so no target-platform stage runs Bun while building. The unread `MCP_FORCE_CONSOLE_LOGGING` is gone.
19
+ - **Packaging** — `package.json` `files` carries `!dist/*.mcpb`, keeping a built bundle out of the npm tarball, and `.mcpbignore` excludes `docs/idea.md` and `logs/` from the bundle.
20
+ - **Tooling synced from the framework** — `lint:packaging` checks the bundle exclusion, `manifest.json` version parity, and the Dockerfile build platform; `lint:mcp` fails on a definition it cannot import; `release:github -- --check` validates the tag annotation.
21
+ - **Docs** — README tool sections state each tool's input and output contract, `docs/design.md` records the IP exclusion policy, and `CLAUDE.md` / `AGENTS.md` plus 31 framework skills follow the 0.13.10 templates.
22
+
23
+ ## Fixed
24
+
25
+ - **`whois_lookup_asn` validates the whole token** ([#5](https://github.com/cyanheads/whois-mcp-server/issues/5)) — a decimal ASN from 1 to 4294967295 with an optional `AS` prefix and leading `+`. `AS15169abc`, `1.5`, and out-of-range values fail as `invalid_asn` before any request instead of resolving a truncated number.
26
+ - **`whois_lookup_ip` parses IP and CIDR input completely** ([#6](https://github.com/cyanheads/whois-mcp-server/issues/6)) — extra slashes, trailing text, whitespace, zone IDs, brackets, and malformed IPv6 fail as `invalid_ip` before any request. A CIDR prefix is one decimal within 0–32 or 0–128.
27
+ - **`private_range` follows the numeric address** — equivalent IPv6 spellings classify alike (`0:0:0:0:0:0:0:1`, `fe90::1`), `::10` is no longer excluded, and the tool description lists the excluded ranges.
28
+ - **IPv6 with a dotted IPv4 tail is accepted** — `2001:db8::192.0.2.1` resolves with a 32-nibble PTR name, and IPv4-mapped addresses (`::ffff:8.8.8.8`) are classified, routed, and PTR-resolved as their embedded IPv4.
29
+ - **`whois_get_dossier` renders every TXT value** ([#8](https://github.com/cyanheads/whois-mcp-server/issues/8)) — `content[]` dropped values past the third. Each value now sits in its own fence, longer than any backtick run inside it.
30
+ - **`whois_get_dns` rejects `types: []`** ([#9](https://github.com/cyanheads/whois-mcp-server/issues/9)) — it fails as `InvalidParams` (`-32602`) before any query instead of reporting a NextDNS lookup that never ran. Omitting `types` still fetches A, AAAA, MX, TXT, NS.
31
+ - **Provider and registry labels match whole domains** ([#12](https://github.com/cyanheads/whois-mcp-server/issues/12)) — `ns_provider` and `mx_provider` compare hostnames at label boundaries with the MX priority removed, and `rdap_source` / `rir` read only the self link's hostname. `ns1.hostname.com` no longer reads as Name.com; Fastmail's `messagingengine.com` is recognized.
32
+ - **`whois_lookup_domain` description** — a TLD without RDAP coverage throws `rdap_no_coverage`; the description previously promised `rdap_coverage: false`.
33
+
34
+ ## Dependencies
35
+
36
+ - `@cyanheads/mcp-ts-core` `^0.13.6` → `^0.13.10`
37
+ - `@socketsecurity/bun-security-scanner` (dev) `^1.1.2` → `^1.1.3`
38
+ - `@types/node` (dev) `^26.6.1` → `^26.6.3`
39
+ - `ignore` (dev) `^7.0.9` → `^7.0.10`
40
+ - `vitest` (dev) `^5.0.1` → `^5.0.2`
41
+ - Bun `1.4.0` → `1.4.2` (`packageManager`, Docker base images)
package/dist/app.d.ts CHANGED
@@ -128,6 +128,23 @@ export declare const appOptions: {
128
128
  cloudflare: "cloudflare";
129
129
  nextdns: "nextdns";
130
130
  }>;
131
+ query_sources: import("zod").ZodArray<import("zod").ZodObject<{
132
+ type: import("zod").ZodEnum<{
133
+ A: "A";
134
+ AAAA: "AAAA";
135
+ CAA: "CAA";
136
+ CNAME: "CNAME";
137
+ MX: "MX";
138
+ NS: "NS";
139
+ PTR: "PTR";
140
+ SOA: "SOA";
141
+ TXT: "TXT";
142
+ }>;
143
+ source: import("zod").ZodEnum<{
144
+ cloudflare: "cloudflare";
145
+ nextdns: "nextdns";
146
+ }>;
147
+ }, import("zod/v4/core").$strip>>;
131
148
  }, import("zod/v4/core").$strip>, readonly [{
132
149
  readonly reason: "invalid_domain";
133
150
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
@@ -157,8 +174,8 @@ export declare const appOptions: {
157
174
  }, {
158
175
  readonly reason: "private_range";
159
176
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
160
- readonly when: "Input is a private or reserved range — no RIR RDAP record exists for it.";
161
- readonly recovery: "Use a public, globally-routable IP address. RFC 1918, loopback, and link-local addresses have no RIR records.";
177
+ readonly when: "The numeric address falls within the server’s explicit excluded ranges.";
178
+ readonly recovery: "Choose an address outside the excluded ranges listed in this tool’s description.";
162
179
  readonly thrownBy: "service";
163
180
  }, {
164
181
  readonly reason: "ip_not_found";
@@ -181,8 +198,8 @@ export declare const appOptions: {
181
198
  }, import("zod/v4/core").$strip>, readonly [{
182
199
  readonly reason: "invalid_asn";
183
200
  readonly code: import("@cyanheads/mcp-ts-core/errors").JsonRpcErrorCode.ValidationError;
184
- readonly when: "Input does not match AS<number> or bare integer format.";
185
- readonly recovery: "Provide a valid ASN like \"AS15169\" or \"15169\". Numbers must be positive integers.";
201
+ readonly when: "The complete token is not a decimal ASN from 1 to 4294967295.";
202
+ readonly recovery: "Provide a decimal integer from 1 to 4294967295, optionally prefixed with AS and +, such as \"AS15169\" or \"+15169\".";
186
203
  readonly thrownBy: "service";
187
204
  }, {
188
205
  readonly reason: "asn_not_found";
package/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,eAAO,MAAM,UAAU;;;IAGrB;;;;;;OAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwBuB,CAAC"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,eAAO,MAAM,UAAU;;;IAGrB;;;;;;OAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwBuB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"whois-check-availability.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-check-availability.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAIjE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;cAoGjC,CAAC"}
1
+ {"version":3,"file":"whois-check-availability.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-check-availability.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAIjE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;cAkGjC,CAAC"}
@@ -40,9 +40,7 @@ export const whoisCheckAvailability = tool('whois_check_availability', {
40
40
  ],
41
41
  async handler(input, ctx) {
42
42
  if (!isValidFqdn(input.domain)) {
43
- throw ctx.fail('invalid_domain', `"${input.domain}" is not a valid FQDN.`, {
44
- ...ctx.recoveryFor('invalid_domain'),
45
- });
43
+ throw ctx.fail('invalid_domain', `"${input.domain}" is not a valid FQDN.`);
46
44
  }
47
45
  ctx.log.info('RDAP availability check', { domain: input.domain });
48
46
  const result = await getRdapService().checkAvailability(input.domain, ctx);
@@ -1 +1 @@
1
- {"version":3,"file":"whois-check-availability.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-check-availability.tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"whois-check-availability.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-check-availability.tool.ts"],"names":[],"mappings":"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"}
@@ -40,6 +40,23 @@ export declare const whoisGetDns: import("@cyanheads/mcp-ts-core").ToolDefinitio
40
40
  cloudflare: "cloudflare";
41
41
  nextdns: "nextdns";
42
42
  }>;
43
+ query_sources: z.ZodArray<z.ZodObject<{
44
+ type: z.ZodEnum<{
45
+ A: "A";
46
+ AAAA: "AAAA";
47
+ CAA: "CAA";
48
+ CNAME: "CNAME";
49
+ MX: "MX";
50
+ NS: "NS";
51
+ PTR: "PTR";
52
+ SOA: "SOA";
53
+ TXT: "TXT";
54
+ }>;
55
+ source: z.ZodEnum<{
56
+ cloudflare: "cloudflare";
57
+ nextdns: "nextdns";
58
+ }>;
59
+ }, z.core.$strip>>;
43
60
  }, z.core.$strip>, readonly [{
44
61
  readonly reason: "invalid_domain";
45
62
  readonly code: JsonRpcErrorCode.ValidationError;
@@ -1 +1 @@
1
- {"version":3,"file":"whois-get-dns.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-get-dns.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAOjE,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA8GtB,CAAC"}
1
+ {"version":3,"file":"whois-get-dns.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-get-dns.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAMjE,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA4HtB,CAAC"}
@@ -19,8 +19,9 @@ export const whoisGetDns = tool('whois_get_dns', {
19
19
  .describe('Fully qualified domain name or hostname to query (e.g., "github.com", "mail.example.com").'),
20
20
  types: z
21
21
  .array(z.enum(DNS_RECORD_TYPES).describe('A DNS record type to fetch.'))
22
+ .min(1)
22
23
  .default(['A', 'AAAA', 'MX', 'TXT', 'NS'])
23
- .describe('DNS record types to fetch. Defaults to [A, AAAA, MX, TXT, NS]. ' +
24
+ .describe('Nonempty list of DNS record types to fetch; duplicates are queried once. Defaults to [A, AAAA, MX, TXT, NS]. ' +
24
25
  'Specify more types to expand coverage (e.g., add CAA to check certificate authority authorization).'),
25
26
  }),
26
27
  output: z.object({
@@ -41,7 +42,20 @@ export const whoisGetDns = tool('whois_get_dns', {
41
42
  .describe('DNS records returned for the requested types.'),
42
43
  source: z
43
44
  .enum(['cloudflare', 'nextdns'])
44
- .describe('The DoH resolver that provided results (cloudflare = primary used for most types, nextdns = fallback or CAA).'),
45
+ .describe('Aggregate resolver indicator: cloudflare when any query consumed a successful Cloudflare response; ' +
46
+ 'otherwise nextdns. See query_sources for each requested type.'),
47
+ query_sources: z
48
+ .array(z
49
+ .object({
50
+ type: z
51
+ .enum(DNS_RECORD_TYPES)
52
+ .describe('Requested DNS record type, which may differ from an answer type.'),
53
+ source: z
54
+ .enum(['cloudflare', 'nextdns'])
55
+ .describe('Resolver whose successful response was consumed, including empty answers and NXDOMAIN.'),
56
+ })
57
+ .describe('Resolver attribution for one requested type.'))
58
+ .describe('One entry per unique requested type, in first-requested order.'),
45
59
  }),
46
60
  errors: [
47
61
  {
@@ -53,23 +67,16 @@ export const whoisGetDns = tool('whois_get_dns', {
53
67
  ],
54
68
  async handler(input, ctx) {
55
69
  if (!isValidFqdn(input.domain)) {
56
- throw ctx.fail('invalid_domain', `"${input.domain}" is not a valid FQDN.`, {
57
- ...ctx.recoveryFor('invalid_domain'),
58
- });
70
+ throw ctx.fail('invalid_domain', `"${input.domain}" is not a valid FQDN.`);
59
71
  }
60
72
  ctx.log.info('DNS lookup via DoH', { domain: input.domain, types: input.types });
61
- const result = await getDohService().lookup(input.domain, input.types, ctx);
62
- return {
63
- domain: result.domain,
64
- nxdomain: result.nxdomain,
65
- records: result.records,
66
- source: result.source,
67
- };
73
+ return await getDohService().lookup(input.domain, input.types, ctx);
68
74
  },
69
75
  format: (result) => {
70
76
  const lines = [];
71
77
  lines.push(`# DNS Records: ${result.domain}`);
72
- lines.push(`**Source:** ${result.source}`);
78
+ lines.push(`**Source (aggregate):** ${result.source} — ${result.source === 'cloudflare' ? 'at least one query used Cloudflare' : 'all queries used NextDNS'}`);
79
+ lines.push(`**Query sources:** ${result.query_sources.map((query) => `${query.type}: ${query.source}`).join(', ')}`);
73
80
  lines.push(`**NXDOMAIN:** ${result.nxdomain === true ? 'Yes — domain does not exist in DNS' : 'No'}`);
74
81
  // Group records by type and render all fields (name, ttl, data)
75
82
  const byType = new Map();
@@ -81,7 +88,7 @@ export const whoisGetDns = tool('whois_get_dns', {
81
88
  for (const [type, recs] of byType) {
82
89
  lines.push(`\n## ${type}`);
83
90
  for (const rec of recs) {
84
- // TXT records are attacker-controlled free-text and must be fenced to prevent prompt injection
91
+ // Backticks distinguish TXT data visually; they are not a security boundary.
85
92
  const data = type === 'TXT' ? `\`${rec.data}\`` : rec.data;
86
93
  lines.push(`- **${data}** | name: ${rec.name} | TTL: ${rec.ttl}s`);
87
94
  }
@@ -1 +1 @@
1
- {"version":3,"file":"whois-get-dns.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-get-dns.tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"whois-get-dns.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-get-dns.tool.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"whois-get-dossier.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-get-dossier.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAyE3E,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAiR1B,CAAC"}
1
+ {"version":3,"file":"whois-get-dossier.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-get-dossier.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAsF3E,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAmR1B,CAAC"}