/** An environment-variable source: typically `process.env`. */ export type EnvSource = Record; /** Options shared by the env-reading helpers. */ export interface ReadEnvOptions { /** The source to read from. Defaults to {@link process.env}. */ env?: EnvSource; /** Value to return when the variable is unset. */ default?: string; } /** * Read an environment variable defensively. * * The value is trimmed of surrounding whitespace and treated as **unset** when * it is: * - absent or a non-string, * - empty / whitespace-only, * - the literal string `'undefined'` or `'null'`, or * - an unsubstituted `${...}` placeholder. * * When unset, returns `opts.default` if provided, otherwise `undefined`. * * Consolidates the `readVar`/`readEnv`/`readEnvString`/`sanitizeEnvVar` snippet * duplicated across 12+ MCP servers. */ export declare function readEnvVar(key: string, opts?: ReadEnvOptions): string | undefined; /** Options for {@link requireEnvVar}. */ export interface RequireEnvOptions { /** The source to read from. Defaults to {@link process.env}. */ env?: EnvSource; /** Remediation text appended to the thrown error ("here's how to fix it"). */ hint?: string; } /** * Like {@link readEnvVar} but throws a helpful, value-free error when the * variable is unset (or a placeholder/sentinel). The error names only the * variable and the optional `hint` — never the offending value — so a leaked * placeholder is not echoed back to the caller. */ export declare function requireEnvVar(key: string, opts?: RequireEnvOptions): string; /** Options for {@link parseBoolEnv}. */ export interface ParseBoolEnvOptions { /** The source to read from. Defaults to {@link process.env}. */ env?: EnvSource; /** Result when the variable is unset or unrecognised. Defaults to `false`. */ default?: boolean; } /** * Parse a boolean-ish environment variable. Recognises (case-insensitively) * `1/true/yes/on` as `true` and `0/false/no/off` as `false`. Anything unset, * placeholder/sentinel, or unrecognised falls back to `opts.default` (`false`). * * Consolidates the `['1','true','yes','on'].includes(...)` `*_DISABLE_*` flag * pattern duplicated across the fleet. */ export declare function parseBoolEnv(key: string, opts?: ParseBoolEnvOptions): boolean; /** * Expand a user-provided filesystem path: * - a leading `~` or `~/...` expands to the user's home directory, and * - any remaining relative path is resolved against the current working dir. * * Note: `~user` (other-user home lookup) and mid-path `~` are intentionally * NOT expanded — only the current user's home is ever substituted. */ export declare function expandPath(p: string): string; /** Options for {@link readPortEnv}. */ export interface ReadPortEnvOptions { /** The source to read from. Defaults to {@link process.env}. */ env?: EnvSource; } /** * Read a TCP port from an environment variable, hardened the way * {@link readEnvVar} hardens any var (trim, treat blank / `'undefined'` / * `'null'` / unsubstituted `${...}` placeholder as unset) PLUS numeric * validation: the value must parse to an integer in the valid port range * `1..65535`. * * Returns `fallback` when the variable is unset, a placeholder, non-numeric, or * out of range. Consolidates the bare `Number(process.env.X_WS_PORT)` pattern * across compass/redfin/homes/musescore, which yields `NaN` on an unexpanded * `${...}` placeholder or junk and then hands `NaN` to the server. * * @example readPortEnv('REDFIN_WS_PORT', 37149) */ export declare function readPortEnv(key: string, fallback: number, opts?: ReadPortEnvOptions): number; /** A minimal injectable file reader: returns the file's UTF-8 contents. */ export type ReadFileSyncFn = (path: string) => string; /** Options for {@link createCachedJsonArrayLoader}. */ export interface CachedJsonArrayLoaderOptions { /** Name of the env var holding the path to a JSON string-array file. */ envVar: string; /** Returned when the var is unset, or the file is missing/unreadable/invalid. */ defaults: string[]; /** The source to read env from. Defaults to {@link process.env}. */ env?: EnvSource; /** * Injectable file reader (for tests). Defaults to a `node:fs` reader that * throws when the file is missing — a missing file is caught and * negative-cached like any other read failure. */ readFile?: ReadFileSyncFn; /** * Label woven into the stderr warning on a missing/invalid file (e.g. * `'redfin-mcp'`). Defaults to the env-var name. */ label?: string; } /** * Build a cached, negative-cached loader for an env-named JSON string-array * file — the `loadCommunities` + `DEFAULT_COMMUNITIES` pattern quadruplicated * across redfin/zillow/homes/onehome (only the env var differs: * `REDFIN_/ZILLOW_/HOMES_/ONEHOME_COMMUNITIES_FILE`). * * The returned function: * - reads the file path from `envVar` via {@link readEnvVar} (placeholder * hardening), returning `defaults` when unset (and clearing any cache), * - parses the file as a JSON array of strings; on success caches and returns * it (keyed by the env-var value, so a path change re-reads), * - on a missing / unreadable file, invalid JSON, or non-string-array, * logs a single stderr warning and **negative-caches** — it returns * `defaults` without re-reading on subsequent calls for the same path, * - never re-reads a successfully-cached file. * * @example * const loadCommunities = createCachedJsonArrayLoader({ * envVar: 'REDFIN_COMMUNITIES_FILE', * defaults: DEFAULT_COMMUNITIES, * label: 'redfin-mcp', * }); */ export declare function createCachedJsonArrayLoader(opts: CachedJsonArrayLoaderOptions): () => string[]; /** Options for {@link loadDotenvSafely}. */ export interface LoadDotenvOptions { /** Path to the `.env` file. Defaults to dotenv's own resolution (CWD). */ path?: string; /** * When `true`, `.env` values overwrite already-set `process.env` entries. * Defaults to `false` so real host-provided env always wins. */ override?: boolean; } /** * Load a `.env` file for local development, swallowing any failure. * * `dotenv` is imported dynamically and the whole thing is wrapped so that a * missing module (e.g. inside an mcpb bundle, where credentials arrive via the * host's `mcp_config.env`) is a silent no-op rather than a crash. Real * environment values take precedence unless `override` is set. * * @returns `true` if a `.env` file was loaded without error, `false` otherwise. */ export declare function loadDotenvSafely(opts?: LoadDotenvOptions): Promise; /** Options for {@link readIntEnv}. */ export interface ReadIntEnvOptions { /** The source to read from. Defaults to {@link process.env}. */ env?: EnvSource; /** Result when the variable is unset, junk, or out of range. */ default?: number; /** Inclusive lower bound. Defaults to `0` — the fleet's env ints (timeouts, counts) are non-negative. */ min?: number; /** Inclusive upper bound. Unbounded when omitted. */ max?: number; } /** * Read an integer from an environment variable, hardened like {@link readEnvVar} * (trim, treat blank / `'undefined'` / `'null'` / unsubstituted `${...}` as * unset) PLUS a strict integer parse (`12abc`, `1.5`, `0x10` are rejected) and * an optional `[min, max]` range check. * * Returns `opts.default` (or `undefined`) when unset, junk, or out of range. * Consolidates the hand-rolled numeric env readers across the fleet * (alltrails `getRequestTimeoutMs`, getyourguide `requestTimeoutMs`, …) the way * {@link readPortEnv} consolidated the port variant. */ export declare function readIntEnv(key: string, opts?: ReadIntEnvOptions): number | undefined; /** * Read a TTL expressed in **seconds** from an environment variable and return * **milliseconds** — the `_CACHE_TTL` / `_STATIC_CACHE_TTL` reader * triplicated across flightaware / viator / tripadvisor. * * Semantics (matching all three donors): * - unset / placeholder / junk / negative → `defaultMs`, * - an explicit `'0'` → `0` (caching disabled) — NOT the default, * - a non-negative integer → `n * 1000`. */ export declare function readTtlMsEnv(key: string, defaultMs: number, opts?: { env?: EnvSource; }): number; //# sourceMappingURL=index.d.ts.map