/** * @fileoverview HTTP client for the NIST NVD API 2.0 with rate-limit pacing. * Manages API key injection, queue-based pacing of every request attempt, retry with backoff, * and Retry-After header parsing. * @module services/nvd-http/nvd-http-client */ import type { Context } from '@cyanheads/mcp-ts-core'; import { McpError } from '@cyanheads/mcp-ts-core/errors'; /** * The error thrown when NVD answers HTTP 404 because it rejected the request parameters * (malformed CVE ID, unusable match string) rather than reporting an absent record. * Deterministic, so it carries `retryable: false`: the framework's opt-out stops `withRetry` * from re-sending a request that can never succeed. * * `detail` is NVD's own diagnosis from the `message` header — it names the offending parameter, * which the generic text cannot. * * Exported so callers translate it to a domain error and tests reproduce it exactly. */ export declare function nvdRequestRejected(endpoint: string, detail?: string): McpError; /** True when `err` is the {@link nvdRequestRejected} throw. */ export declare function isNvdRequestRejected(err: unknown): boolean; export declare class NvdHttpClient { private readonly apiKey; private readonly timeoutMs; private lastRequestAt; /** Epoch ms before which no request may be sent — set from a 403's Retry-After. */ private backoffUntil; private queue; private draining; constructor(apiKey: string | undefined, timeoutMs: number); /** * Fetch from the NVD API. * * Retry wraps the pacing queue rather than sitting inside it, so every attempt — the first * try and each retry — waits its turn and counts against the rate budget. */ get(endpoint: string, params: Record, ctx: Context): Promise; /** Enqueue one request attempt, paced behind the inter-request gap and any active 403 backoff. */ private schedule; private drainNext; private fetchOnce; /** * Classify NVD's HTTP 404, which covers two unrelated faults separated only by the `message` * header: a rejected request parameter, or an unusable API key. Reporting a malformed CVE ID * when the real fault is `NVD_API_KEY` sends the caller to fix the wrong thing — no correction * to the ID can succeed while the key is refused. Both are deterministic, so neither retries. */ private rejectionFor; /** * Build the 403 error and hold the queue until NVD's window resets, so every pending request — * not just this call's retry — stops firing into a limit that is already exceeded. */ private rateLimitError; private buildUrl; private buildHeaders; } export declare function initNvdHttpClient(apiKey: string | undefined, timeoutMs: number): void; export declare function getNvdHttpClient(): NvdHttpClient; //# sourceMappingURL=nvd-http-client.d.ts.map