/** * @fileoverview Low-level HTTP client for BrAPI v2 servers. Handles URL * construction, header assembly, JSON envelope parsing, retry with exponential * backoff, and the async-search poll loop * (`POST /search/{noun}` → `searchResultsDbId` → `GET /search/{noun}/{id}`). * Stateless across connections — callers pass `baseUrl` and resolved auth per * call; connection state is owned by `ServerRegistry` (added in a later phase). * * @module services/brapi-client/brapi-client */ import type { Context } from '@cyanheads/mcp-ts-core'; import { McpError } from '@cyanheads/mcp-ts-core/errors'; import type { FetchWithTimeoutOptions } from '@cyanheads/mcp-ts-core/utils'; import type { ServerConfig } from '../../config/server-config.js'; import type { BinaryResponse, BrapiEnvelope, BrapiRequestOptions, SearchResponse } from './types.js'; /** * Signature of the underlying HTTP fetcher. Accepts the handler `Context` * directly so callers (and tests) don't have to cast; the default * implementation adapts to `fetchWithTimeout`. */ export type Fetcher = (url: string | URL, timeoutMs: number, context: Context, options?: FetchWithTimeoutOptions) => Promise; export declare class BrapiClient { private readonly serverConfig; private readonly fetcher; constructor(serverConfig: ServerConfig, fetcher?: Fetcher); /** * GET /{path} with optional query params and auth. When `options.dialect` is * supplied, `params` are routed through the dialect adapter at the client * edge — single source of truth for plural/singular translation across every * call site (find_* tools, FK lookups, count probes). Throws a structured * `validationError` (with `data.reason = DIALECT_ALL_DROPPED_REASON`) when * the dialect drops every supplied filter, so callers can detect and skip * without parsing message text. */ get(baseUrl: string, path: string, ctx: Context, options?: BrapiRequestOptions): Promise>; /** * GET /{path} returning raw bytes — used for image content and other binary * payloads. Honors the same retry policy as `get()`. The `accept` option * overrides the default `image/*`. */ getBinary(baseUrl: string, path: string, ctx: Context, options?: BrapiRequestOptions & { accept?: string; }): Promise; /** * Fetch binary bytes from an arbitrary URL — used as a fallback when a * BrAPI server doesn't expose `/images/{id}/imagecontent` but the image's * metadata carries an `imageURL` (CDN, S3, etc.). No auth is attached; the * assumption is that these URLs are publicly reachable. Still honors the * private-IP guard and request timeout. */ fetchBinaryUrl(url: string, ctx: Context, accept?: string): Promise; /** * POST /search/{noun}. Returns a discriminated union — `sync` when the * server returns full results inline, `async` when it returns a * `searchResultsDbId` the caller must poll via `getSearchResults`. */ postSearch(baseUrl: string, noun: string, body: Record, ctx: Context, options?: BrapiRequestOptions): Promise>; /** * POST /{path} with a JSON body. Used for write endpoints (e.g. creating * observations). Same retry + classification policy as `get()`. The body is * serialized as JSON and `Content-Type: application/json` is forced. */ post(baseUrl: string, path: string, body: unknown, ctx: Context, options?: BrapiRequestOptions): Promise>; /** * PUT /{path} with a JSON body. Used for upsert / update endpoints. BrAPI * routes update calls (`PUT /observations`, `PUT /germplasm`) through this. */ put(baseUrl: string, path: string, body: unknown, ctx: Context, options?: BrapiRequestOptions): Promise>; private sendJson; /** * Poll `GET /search/{noun}/{searchResultsDbId}`. Returns the envelope once * the server replies with 200. 202 means "still processing" — the method * sleeps `searchPollIntervalMs` and retries until `searchPollTimeoutMs`. */ getSearchResults(baseUrl: string, noun: string, searchResultsDbId: string, ctx: Context, options?: BrapiRequestOptions): Promise>; private doFetch; private buildUrl; private buildHeaders; private parseEnvelope; } /** * True when `err` was thrown by the client-level dialect adapter to signal * "every supplied filter dropped." Used by companion call sites to convert * the throw into a graceful warn-and-skip instead of propagating to the user. */ export declare function isDialectAllDropped(err: unknown): err is McpError; export declare function initBrapiClient(serverConfig: ServerConfig, fetcher?: Fetcher): void; export declare function getBrapiClient(): BrapiClient; /** Test-only — clears the singleton so successive suites start clean. */ export declare function resetBrapiClient(): void; //# sourceMappingURL=brapi-client.d.ts.map