/** * MCP Server Manager. * * Discovers, connects to, and manages MCP servers. * Handles tool loading and lifecycle. */ import { type TSchema } from "@gajae-code/ai/core"; import type { SourceMeta } from "../capability/types"; import type { CustomTool } from "../extensibility/custom-tools/types"; import type { AuthStorage } from "../session/auth-storage"; import { MCPConnectionPool, type MCPPoolLease } from "./pool"; import type { MCPProtocolObservation } from "./protocol"; import type { MCPToolDetails } from "./tool-bridge"; import type { MCPToolCache } from "./tool-cache"; import type { MCPGetPromptResult, MCPInputRequestHandler, MCPPrompt, MCPRequestOptions, MCPResource, MCPResourceReadResult, MCPResourceTemplate, MCPServerConfig, MCPServerConnection } from "./types"; export declare function resolveStartupTimeoutMs(configs: MCPServerConfig[], maxStartupTimeoutMs?: number): number; export declare function resolveExactConfigStartupTimeoutMs(configs: MCPServerConfig[]): number; /** * Whether `config` declared a connection window that is still open `elapsedMs` * into startup. * * The startup wait bounds how long session start blocks; a declared `timeout` * bounds how long the server itself may take to come up (`connectToServer` * enforces it). Those are different budgets: the wait elapsing says nothing * about whether the operator's declared window has been spent. */ export declare function withinDeclaredConnectionWindow(config: MCPServerConfig, elapsedMs: number): boolean; export declare class MCPManagerLifecycleError extends Error { readonly code: "MCP_MANAGER_LIFECYCLE_CLOSED"; readonly phase: "disconnect" | "reconnect"; constructor(phase: "disconnect" | "reconnect", cause?: unknown); } /** * Stable, total ordering on MCP tools by name. * * Anthropic prompt caching keys on byte-identical tool definitions: any reorder * of the tools array invalidates the tools cache breakpoint and forces a full * prefix rebuild on the next request. MCP servers connect/reconnect at arbitrary * times, so the natural "insertion order" of `#tools` is non-deterministic. * Sorting after every mutation makes the array bytes independent of connection * sequence. */ export declare function sortMCPToolsByName(tools: T[]): T[]; export declare function resolveSubscriptionPostAction(notificationsEnabled: boolean, currentEpoch: number, subscriptionEpoch: number): "rollback" | "ignore" | "apply"; /** Result of loading MCP tools */ export interface MCPLoadResult { /** Loaded tools as CustomTool instances */ tools: CustomTool[]; /** Connection errors by server name */ errors: Map; /** Connected server names */ connectedServers: string[]; /** Extracted Exa API keys from filtered MCP servers */ exaApiKeys: string[]; } /** Options for discovering and connecting to MCP servers */ export interface MCPDiscoverOptions { /** Whether to load project-level config (default: true) */ enableProjectConfig?: boolean; /** Whether to filter out Exa MCP servers (default: true) */ filterExa?: boolean; /** Whether to filter out browser MCP servers when builtin browser tool is enabled (default: false) */ filterBrowser?: boolean; /** Only connect servers with autoload !== false (default: false) */ autoloadOnly?: boolean; /** * Restrict discovery to GJC's native `.gjc` scopes (user + project). * Runtime MCP authority for GJC sessions; Claude Code/Codex files are * explicit import sources into `.gjc`, not implicit runtime authorities. */ nativeOnly?: boolean; /** Called when starting to connect to servers */ onConnecting?: (serverNames: string[]) => void; /** Load only this explicit MCP config file. */ configPath?: string; /** Idle retention for shared MCP pool entries. */ sharedPoolIdleMs?: number; } export interface MCPManagerOptions { /** Restrict this instance to tools from an explicit MCP config. */ toolsOnly?: boolean; /** * Ceiling for the startup wait, in milliseconds. Only ACP lifecycle launches * set this, so a slow ACP MCP handshake gets the readiness budget while every * other consumer keeps the short default. Non-positive or non-finite values * are ignored and the default applies. */ maxStartupTimeoutMs?: number; /** Connection pool used for every physical MCP open/close. */ pool?: MCPConnectionPool; /** Session identity included in per-session pool keys. */ sessionId?: string; /** Idle retention for shared pool entries. */ sharedPoolIdleMs?: number; /** Test seam for deterministic reconnect backoff scheduling. */ sleep?: (milliseconds: number, signal?: AbortSignal) => Promise; /** Test seam for fencing the acquisition-to-registration replacement race. */ afterLeaseAcquiredForTests?: (name: string, lease: MCPPoolLease) => void | Promise; } /** * MCP Server Manager. * * Manages connections to MCP servers and provides tools to the agent. */ export declare class MCPManager { #private; private cwd; private toolCache; /** * Process-global compatibility holder used only by legacy lifecycle/test seams. * Production MCP routing uses the scope-held facade carried through ResolveContext. */ static instance(): MCPManager | undefined; /** Install or clear the process-global compatibility holder. */ static setInstance(value: MCPManager | undefined): void; /** Reset the process-global instance. Test-only. */ static resetForTests(): void; sealConnectionSet(): void; isConnectionSetSealed(): boolean; constructor(cwd: string, toolCache?: MCPToolCache | null, options?: MCPManagerOptions); isToolsOnly(): boolean; /** * Set a callback to receive all server notifications. */ setOnNotification(handler: (serverName: string, method: string, params: unknown) => void): void; /** * Set a callback to fire when any server's tools change. */ setOnToolsChanged(handler: (tools: CustomTool[]) => void): void; /** * Set a callback to fire when any server's resources change. */ setOnResourcesChanged(handler: (serverName: string, uri: string) => void): void; /** * Set a callback to fire when any server's prompts change. */ setOnPromptsChanged(handler: (serverName: string) => void): void; setNotificationsEnabled(enabled: boolean): void; /** * Set the auth storage for resolving OAuth credentials. */ setAuthStorage(authStorage: AuthStorage): void; /** * Register the handler for modern MRTR `input_required` results (structured * elicitation/roots/sampling input requests). Runtimes with an interactive * question surface (e.g. ACP `elicitation/create`) register here; without a * handler, `input_required` fails explicitly instead of hanging. */ setInputRequestHandler(handler: MCPInputRequestHandler | null): void; /** * Discover and connect to all MCP servers from .mcp.json files. * Returns tools and any connection errors. */ discoverAndConnect(options?: MCPDiscoverOptions): Promise; /** * Connect to specific MCP servers. * Connections are made in parallel for faster startup. */ connectServers(configs: Record, sources: Record, onConnecting?: (serverNames: string[]) => void): Promise; /** * Get all loaded tools. */ getTools(): CustomTool[]; /** * Get a specific connection. */ getConnection(name: string): MCPServerConnection | undefined; /** * Get current connection status for a server. */ getConnectionStatus(name: string): "connected" | "connecting" | "disconnected"; /** * Get the authoritative protocol observation for a connected server * (preference, negotiated era/version, downgrade decision, deprecation state). * Secret-free; the single observation model consumed by customization doctor * (#4288) and /extensions (#4291). Returns undefined when not connected. */ getProtocolObservation(name: string): MCPProtocolObservation | undefined; /** * Snapshot of protocol observations for all connected servers. */ getProtocolObservations(): ReadonlyMap; /** * Get the source metadata for a server. */ getSource(name: string): SourceMeta | undefined; /** * Wait for a connection to complete (or fail). */ waitForConnection(name: string): Promise; /** * Resolve auth and shell-command substitutions in config before connecting. */ prepareConfig(config: MCPServerConfig): Promise; /** Acquire a prepared, pool-owned lease for a scoped transient operation. */ withPreparedLease(name: string, config: MCPServerConfig, fn: (lease: MCPPoolLease) => Promise | T, options?: { signal?: AbortSignal; }): Promise; /** Read-only test seam for pending retired lease-release records. */ get retiredLeaseReleaseCountForTests(): number; /** * Get all connected server names. */ getConnectedServers(): string[]; /** * Get all known server names (connected, connecting, or discovered). */ getAllServerNames(): string[]; /** * Disconnect from a specific server. */ disconnectServer(name: string): Promise; /** * Disconnect from all servers. */ disconnectAll(): Promise; /** Release this manager's session leases and all associated MCP state. */ releaseLeases(): Promise; /** * Reconnect to a server after a connection failure. * Tears down the stale connection, re-resolves auth, establishes a new * connection, reloads tools, and notifies consumers. * Concurrent calls for the same server share one reconnection attempt. * Returns the new connection, or null if reconnection failed. */ reconnectServer(name: string): Promise; /** * Refresh tools from a specific server. */ refreshServerTools(name: string): Promise; /** * Refresh tools from all servers. */ refreshAllTools(): Promise; /** * Refresh resources from a specific server. */ refreshServerResources(name: string): Promise; /** * Refresh prompts from a specific server. */ refreshServerPrompts(name: string): Promise; /** * Get resources and templates for a specific server. */ getServerResources(name: string): { resources: MCPResource[]; templates: MCPResourceTemplate[]; } | undefined; /** * Read a specific resource from a server. */ readServerResource(name: string, uri: string, options?: MCPRequestOptions): Promise; /** * Get prompts for a specific server. */ getServerPrompts(name: string): MCPPrompt[] | undefined; /** * Get a specific prompt from a server. */ executePrompt(name: string, promptName: string, args?: Record, options?: MCPRequestOptions): Promise; /** * Get connected-server instructions for request-scoped untrusted user-role context. */ getServerInstructions(): Map; /** * Get notification state for display. */ getNotificationState(): { enabled: boolean; subscriptions: Map>; }; } /** * Create an MCP manager and discover servers. * Convenience function for quick setup. */ export declare function createMCPManager(cwd: string, options?: MCPDiscoverOptions): Promise<{ manager: MCPManager; result: MCPLoadResult; }>;