import { type VariableLoader } from '@utcp/sdk'; import type { HexisMcpConfig } from './config.js'; import { type LocalManualInfo } from './deployment.js'; /** * Resolving a LOCAL tool's `${VAR}`s from the deployment's Secrets Vault. * * A local-only `.tool` executes here, on the user's machine, so its credentials * have to be here too. Until now they could only come from `process.env` — the * MCP client config that launched this process — which meant every person * running a local tool hand-placed its credentials on their own laptop, and a * rotation had to be repeated everywhere. * * This closes that gap without widening what a caller can ask for. The request * names a MANUAL, never a variable; the deployment re-reads the `.tool` file * and resolves exactly what it declares, so the knowledge base is the allowlist * and this process cannot extend it. What comes back is bound to that manual's * UTCP namespace, which is what keeps one local tool from resolving another's * secret — the same per-manual isolation the hosted client relies on. * * Two limits are deliberate: * * - **Local manuals only.** A remote manual's tools still execute on the * deployment and resolve their credentials there; asking for them here would * move a secret onto a laptop for no benefit at all. * - **Values are never returned to a caller.** They are expanded into a tool * invocation by UTCP's substitutor and go no further. An agent talking to * this server calls `git.push(...)`; it never sees the token that made the * push work. * * `process.env` remains the last tier underneath this one, so an existing * setup that provisions a local tool from the client config keeps working — * the vault answer simply arrives first when there is one. */ export declare const HEXIS_LOCAL_LOADER_TYPE = "hexis_local_tool_variables"; /** * Point a loader at a deployment and the set of manuals that resolve through * it. Returns the id to put in the client config's loader descriptor. * * Call before building the UTCP client. Each call is a NEW binding with its own * cache; re-binding after a credential renewal therefore drops the old cached * values, which is what that case wants. */ export declare function bindLocalVariableResolver(config: HexisMcpConfig, local: ReadonlyMap, now?: () => number): string; /** * Release one binding, or every binding when called with no id. * * MUST be called when a server shuts down, and when its construction fails * partway. A binding holds a deployment's configuration and its cached secret * VALUES; a long-lived host that creates servers over time would otherwise * accumulate them for the life of the process with no way to reclaim them. */ export declare function resetLocalVariableResolver(id?: string): void; /** * Forget every value a binding has resolved so far, keeping the binding. * * For a catalog refresh that swaps the set of local manuals under a live * client: a manual that kept its name but changed its file may now declare * other variables, or be addressed by another slug, and the values cached * against its OLD definition would otherwise be handed to its new tools for * the rest of the cache's life. In-flight resolutions are left to finish — * their result is dropped on arrival, because the generation they started * under is no longer the current one (see `variablesFor`) — and collision * reports are cleared with the values, so a collision the new set removed is * not still suppressed, and one it introduced is reported once. */ export declare function dropLocalVariableCache(id: string): void; export declare class HexisLocalVariableLoader implements VariableLoader { readonly variable_loader_type = "hexis_local_tool_variables"; readonly binding_id: string; [key: string]: unknown; constructor(bindingId: string); /** * Resolve one UTCP-namespaced key, or null to fall through to `process.env`. * * Null is returned for anything that is not a local manual's variable — * including every remote-manual key — so this loader can never become a path * by which a server-side credential is pulled onto the machine. */ get(effectiveKey: string): Promise; } /** * Register the loader type. `UtcpClient.create` re-validates its whole config * through the serializer registry, so a live loader object cannot be handed in * directly — it has to be rebuilt from a plain descriptor. */ export declare function registerLocalVariableLoader(): void; /** The descriptor to put in a client config's `load_variables_from`. */ export declare function localVariableLoaderConfig(bindingId: string): Record; //# sourceMappingURL=local-variables.d.ts.map