import type { Stream } from 'node:stream'; import { MastraBase } from '@mastra/core/base'; import type { MCPServerBase } from '@mastra/core/mcp'; import type { Tool } from '@mastra/core/tools'; import type { ProgressNotification, Prompt, Resource, ResourceTemplateType } from '@modelcontextprotocol/client'; import type { MastraMCPServerDefinition, MCPServerAuthState } from './client.js'; import type { MCPDiscoveryErrorDetails } from './error-utils.js'; import type { MCPServerImplementation, SerializableMCPToolCatalog, SerializableMCPToolDefinition } from './types.js'; /** Options for aggregate discovery across configured MCP servers. */ export interface MCPDiscoveryOptions { /** Maximum time to wait for each server's discovery operation, in milliseconds. */ perServerTimeoutMs?: number; } /** * Configuration options for creating an MCPClient instance. */ export interface MCPClientOptions { /** Optional unique identifier to prevent memory leaks when creating multiple instances with identical configurations */ id?: string; /** Map of server names to their connection configurations (stdio or HTTP-based) */ servers: Record; /** Optional global timeout in milliseconds for all servers (default: 60000ms) */ timeout?: number; } /** * Manages Model Context Protocol (MCP) server connections and tool namespacing, * with access to tools, resources, prompts, and elicitation. * * Configure authentication when required by your servers. * * @example * `yourServerUrl` is a URL for a running MCP server's HTTP endpoint. * ```typescript * import { MCPClient } from '@mastra/mcp'; * * const mcp = new MCPClient({ * servers: { * remote: { url: yourServerUrl }, * }, * }); * ``` * * @see For documentation bundled with your installed package, locate * `@mastra/mcp/package.json` with your project's resolver or package-manager * tooling, then read `dist/docs/SKILL.md` from that package root and follow its * reference links. Use package-manager tools for virtual or archived packages. * * @see [MCP client documentation](https://mastra.ai/reference/tools/mcp-client) * if packaged docs are unavailable. */ export declare class MCPClient extends MastraBase { private serverConfigs; private id; private defaultTimeout; private mcpClientsById; private disconnectPromise; private authFlowsByServer; private authCallbackServersByServer; /** * Per-server abort controllers for in-flight authorization flows. Created * synchronously at the start of {@link runAuthorizationFlow} — before the * callback server exists — so cancel/disconnect can interrupt the setup phase * (discovery, registration, port binding) and not just the waitForCode wait. */ private authAbortControllersByServer; /** * Creates a new MCPClient instance for managing MCP server connections. * * The client automatically manages connection lifecycle and prevents memory leaks by * caching instances with identical configurations. * * @param args - Configuration options * @param args.id - Optional unique identifier to allow multiple instances with same config * @param args.servers - Map of server names to server configurations * @param args.timeout - Optional global timeout in milliseconds (default: 60000) * * @throws {Error} If multiple instances with identical config are created without an ID * * @example * ```typescript * const mcp = new MCPClient({ * servers: { * weatherServer: { * url: new URL('http://localhost:8080/mcp'), * requestInit: { * headers: { Authorization: 'Bearer token' } * } * } * }, * timeout: 30000 * }); * ``` */ constructor(args: MCPClientOptions); /** * Provides access to progress-related operations for tracking long-running operations. * * Progress tracking allows MCP servers to send updates about the status of ongoing operations, * providing real-time feedback to users about task completion and current state. * * @example * ```typescript * // Set up handler for progress updates from a server * await mcp.progress.onUpdate('serverName', (params) => { * console.log(`Progress: ${params.progress}%`); * console.log(`Status: ${params.message}`); * * if (params.total) { * console.log(`Completed ${params.progress} of ${params.total} items`); * } * }); * ``` */ get progress(): { onUpdate: (serverName: string, handler: (params: ProgressNotification['params']) => void) => Promise; }; /** * Provides access to resource-related operations across all configured servers. * * Resources represent data exposed by MCP servers (files, database records, API responses, etc.). * * @example * ```typescript * // List all resources from all servers * const allResources = await mcp.resources.list(); * Object.entries(allResources).forEach(([serverName, resources]) => { * console.log(`${serverName}: ${resources.length} resources`); * }); * * // Read a specific resource * const content = await mcp.resources.read('weatherServer', 'file://data.json'); * * // Receive resource updates * await mcp.resources.onUpdated('weatherServer', async (params) => { * console.log(`Resource updated: ${params.uri}`); * }); * await mcp.resources.subscribe('weatherServer', 'file://data.json'); * ``` */ get resources(): { /** * Lists all available resources from all configured servers. * * Returns a map of server names to their resource arrays. Errors for individual * servers are logged but don't throw - failed servers return empty arrays. * * @returns Promise resolving to object mapping server names to resource arrays * * @example * ```typescript * const resources = await mcp.resources.list(); * console.log(resources.weatherServer); // Array of resources * ``` */ list: () => Promise>; /** * Lists resources while preserving per-server discovery failures. * The existing `list()` method remains the success-only convenience API. */ listWithErrors: (options?: MCPDiscoveryOptions) => Promise<{ resources: Record; errors: Record; errorDetails: Record; durations?: Record; }>; /** * Lists all available resource templates from all configured servers. * * Resource templates are URI templates (RFC 6570) describing dynamic resources. * Errors for individual servers are logged but don't throw. * * @returns Promise resolving to object mapping server names to template arrays * * @example * ```typescript * const templates = await mcp.resources.templates(); * console.log(templates.weatherServer); // Array of resource templates * ``` */ templates: () => Promise>; /** * Lists resource templates while preserving per-server discovery failures. * The existing `templates()` method remains the success-only convenience API. */ templatesWithErrors: (options?: MCPDiscoveryOptions) => Promise<{ templates: Record; errors: Record; errorDetails: Record; durations?: Record; }>; /** * Reads the content of a specific resource from a server. * * @param serverName - Name of the server to read from * @param uri - URI of the resource to read * @returns Promise resolving to the resource content * @throws {MastraError} If reading the resource fails * * @example * ```typescript * const content = await mcp.resources.read('weatherServer', 'file://config.json'); * console.log(content.contents[0].text); * ``` */ read: (serverName: string, uri: string) => Promise<{ [x: string]: unknown; _meta?: { [x: string]: unknown; "io.modelcontextprotocol/serverInfo"?: { version: string; websiteUrl?: string | undefined; description?: string | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "dark" | "light" | undefined; }[] | undefined; name: string; title?: string | undefined; } | undefined; } | undefined; contents: ({ uri: string; mimeType?: string | undefined; _meta?: { [x: string]: unknown; } | undefined; text: string; } | { uri: string; mimeType?: string | undefined; _meta?: { [x: string]: unknown; } | undefined; blob: string; })[]; }>; /** * Subscribes to update notifications for a resource on a server. Subscriptions ride * the client's single `subscriptions/listen` stream and are restored after reconnects. * * @param serverName - Name of the server * @param uri - URI of the resource to watch * @throws {MastraError} If the server declines the subscription * * @example * ```typescript * await mcp.resources.onUpdated('weatherServer', ({ uri }) => console.log(`updated ${uri}`)); * await mcp.resources.subscribe('weatherServer', 'file://data.json'); * ``` */ subscribe: (serverName: string, uri: string) => Promise; /** * Stops update notifications for a resource previously passed to `subscribe`. * * @param serverName - Name of the server * @param uri - URI of the resource * @throws {MastraError} If the stream cannot be updated */ unsubscribe: (serverName: string, uri: string) => Promise; /** * Sets a notification handler for when subscribed resources are updated on a server. * Updates arrive for resources passed to `subscribe`. * * @param serverName - Name of the server to monitor * @param handler - Callback function receiving the updated resource URI * @returns Promise resolving when handler is registered * @throws {MastraError} If setting up the handler fails * * @example * ```typescript * await mcp.resources.onUpdated('weatherServer', async (params) => { * console.log(`Resource updated: ${params.uri}`); * const content = await mcp.resources.read('weatherServer', params.uri); * }); * ``` */ onUpdated: (serverName: string, handler: (params: { uri: string; }) => void) => Promise; /** * Sets a notification handler for when the resource list changes on a server. * * @param serverName - Name of the server to monitor * @param handler - Callback function invoked when resources are added/removed * @returns Promise resolving when handler is registered * @throws {MastraError} If setting up the handler fails * * @example * ```typescript * await mcp.resources.onListChanged('weatherServer', async () => { * console.log('Resource list changed, re-fetching...'); * const resources = await mcp.resources.list(); * }); * ``` */ onListChanged: (serverName: string, handler: () => void) => Promise; }; /** * Provides access to prompt-related operations across all configured servers. * * Prompts are reusable message templates exposed by MCP servers that can be parameterized * and used for AI interactions. * * @example * ```typescript * // List all prompts from all servers * const allPrompts = await mcp.prompts.list(); * Object.entries(allPrompts).forEach(([serverName, prompts]) => { * console.log(`${serverName}: ${prompts.map(p => p.name).join(', ')}`); * }); * * // Get a specific prompt with arguments * const prompt = await mcp.prompts.get({ * serverName: 'weatherServer', * name: 'forecast-template', * args: { city: 'London', days: 7 } * }); * ``` */ get prompts(): { /** * Lists all available prompts from all configured servers. * * Returns a map of server names to their prompt arrays. Errors for individual * servers are logged but don't throw - failed servers return empty arrays. * * @returns Promise resolving to object mapping server names to prompt arrays * * @example * ```typescript * const prompts = await mcp.prompts.list(); * console.log(prompts.weatherServer); // Array of prompts * ``` */ list: () => Promise>; /** * Lists prompts while preserving per-server discovery failures. * The existing `list()` method remains the success-only convenience API. */ listWithErrors: (options?: MCPDiscoveryOptions) => Promise<{ prompts: Record; errors: Record; errorDetails: Record; durations?: Record; }>; /** * Retrieves a specific prompt with its messages from a server. * * @param params - Parameters for the prompt request * @param params.serverName - Name of the server to retrieve from * @param params.name - Name of the prompt to retrieve * @param params.args - Optional arguments to populate the prompt template * @returns Promise resolving to the prompt result with messages * @throws {MastraError} If fetching the prompt fails * * @example * ```typescript * const prompt = await mcp.prompts.get({ * serverName: 'weatherServer', * name: 'forecast', * args: { city: 'London' }, * }); * console.log(prompt.messages); * ``` */ get: ({ serverName, name, args }: { serverName: string; name: string; args?: Record; }) => Promise<{ [x: string]: unknown; _meta?: { [x: string]: unknown; "io.modelcontextprotocol/serverInfo"?: { version: string; websiteUrl?: string | undefined; description?: string | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "dark" | "light" | undefined; }[] | undefined; name: string; title?: string | undefined; } | undefined; } | undefined; description?: string | undefined; messages: { role: "assistant" | "user"; content: { type: "text"; text: string; annotations?: { audience?: ("assistant" | "user")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { type: "image"; data: string; mimeType: string; annotations?: { audience?: ("assistant" | "user")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { type: "audio"; data: string; mimeType: string; annotations?: { audience?: ("assistant" | "user")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { uri: string; description?: string | undefined; mimeType?: string | undefined; size?: number | undefined; annotations?: { audience?: ("assistant" | "user")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "dark" | "light" | undefined; }[] | undefined; name: string; title?: string | undefined; type: "resource_link"; } | { type: "resource"; resource: { uri: string; mimeType?: string | undefined; _meta?: { [x: string]: unknown; } | undefined; text: string; } | { uri: string; mimeType?: string | undefined; _meta?: { [x: string]: unknown; } | undefined; blob: string; }; annotations?: { audience?: ("assistant" | "user")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; }; }[]; }>; /** * Sets a notification handler for when the prompt list changes on a server. * * @param serverName - Name of the server to monitor * @param handler - Callback function invoked when prompts are added/removed/modified * @returns Promise resolving when handler is registered * @throws {MastraError} If setting up the handler fails * * @example * ```typescript * await mcp.prompts.onListChanged('weatherServer', async () => { * console.log('Prompt list changed, re-fetching...'); * const prompts = await mcp.prompts.list(); * }); * ``` */ onListChanged: (serverName: string, handler: () => void) => Promise; }; /** * Provides access to tool-related notification operations across all configured servers. * * To fetch tools, use `listTools()` or `listToolsets()`. * * @example * ```typescript * // React to tool list changes on a server * await mcp.tools.onListChanged('weatherServer', async () => { * console.log('Tool list changed, re-fetching...'); * const tools = await mcp.listTools(); * }); * ``` */ get tools(): { /** * Sets a notification handler for when the tool list changes on a server. * * @param serverName - Name of the server to monitor * @param handler - Callback function invoked when tools are added/removed/modified * @returns Promise resolving when handler is registered * @throws {MastraError} If setting up the handler fails * * @example * ```typescript * await mcp.tools.onListChanged('weatherServer', async () => { * const tools = await mcp.listTools(); * }); * ``` */ onListChanged: (serverName: string, handler: () => void) => Promise; }; private addToInstanceCache; private makeId; /** * Disconnects from all MCP servers and cleans up resources. * * This method gracefully closes all server connections and clears internal caches. * Safe to call multiple times - subsequent calls will wait for the first disconnect to complete. * * @example * ```typescript * // Cleanup on application shutdown * process.on('SIGTERM', async () => { * await mcp.disconnect(); * process.exit(0); * }); * ``` */ disconnect(): Promise; /** * Reconnects a single MCP server by name. * * If the server is already connected, it will be forcefully disconnected and reconnected. * If the server has never been connected, a new connection will be established. * * @param serverName - The name of the server to reconnect (must match a key in `servers`) * @throws {Error} If the server name is not found in the configuration * * @example * ```typescript * // Reconnect a specific server after it fails * await mcp.reconnectServer('weatherServer'); * ``` */ reconnectServer(serverName: string): Promise; /** * Runs the interactive OAuth authorization-code flow for a server. * * Requires the server to be configured with an MCPOAuthClientProvider whose * redirect URL points at a loopback address. The flow: * * 1. Starts a loopback callback server on the redirect URL's port (falling * back to the next sequential ports when it is in use) * 2. Attempts a connection so the SDK runs authorization server discovery * (identifying the client by its pre-registered id or its client metadata * URL) and delivers the authorization URL through the provider's * `onRedirectToAuthorization` callback — the host directs the user there * 3. Waits for the browser to deliver the authorization code, validates the * OAuth state, exchanges the code for tokens, and reconnects * * Concurrent calls for the same server join the pending flow (the joiner's * options are ignored — the pending flow keeps its own timeout); different * servers authenticate independently. Each server needs its own provider * instance: the flow pins session state on the provider, so sharing one * MCPOAuthClientProvider across servers is not supported. Hosts with custom * redirect handling (e.g. a web app with an HTTPS redirect URL) should * drive MCPOAuthClientProvider directly instead. * * @param serverName - The name of the server to authenticate (must match a key in `servers`) * @param options.timeoutMs - How long to wait for the browser callback (default 5 minutes) * @throws {Error} If the server has no MCPOAuthClientProvider or its redirect URL is not loopback * * @example * ```typescript * if (mcp.getServerAuthState('weatherServer') === 'needs-auth') { * await mcp.authenticate('weatherServer'); * } * ``` */ authenticate(serverName: string, options?: { timeoutMs?: number; }): Promise; /** * OAuth authorization state of a configured server. * * Returns `undefined` for servers without an authProvider and for servers * that have not attempted a connection yet. */ getServerAuthState(serverName: string): MCPServerAuthState | undefined; private runAuthorizationFlow; /** * Cancels a pending {@link authenticate} flow for a server. * * Tears down the loopback callback server immediately — the pending * authenticate() call rejects. Useful when the user closed the browser * without completing consent, which the host cannot observe. * * The resulting auth state depends on how far the flow had progressed: a flow * cancelled after the server rejected the connection with a 401 stays in the * `needs-auth` state so it can be retried right away, while a flow cancelled * during the setup phase (before any connection was attempted) leaves the * state unchanged — typically `undefined`. * * @param serverName - The name of the server whose flow to cancel * @returns `true` if a pending flow was cancelled, `false` when no flow was pending */ cancelAuthentication(serverName: string): Promise; /** * Returns instructions advertised by connected MCP servers during discovery. * * Servers that have not connected yet, or did not advertise instructions, * return `undefined`. */ getServerInstructions(): Record; /** * Returns the identity each connected MCP server announced when the * connection was established (`serverInfo`: name, version, and optionally * title, description, websiteUrl, and icons), keyed by server name. * * A server's entry is `undefined` if it has not connected yet, or if it * connected over the 2026-07-28 revision without announcing an identity, so * don't use this to check connection state. Icon and website URLs come from * the remote server and are not validated. */ getServerInfo(): Record; /** * The protocol revision negotiated with each configured server, keyed by * server name. Servers that have not connected yet return `undefined`. */ getServerProtocolVersions(): Record; /** * Retrieves all tools from all configured servers with namespaced names. * * Tool names are namespaced as `serverName_toolName` to prevent conflicts between servers. * This method is intended to be passed directly to an Agent definition. * * @returns Object mapping namespaced tool names to tool implementations. * Errors for individual servers are logged but don't throw - failed servers are skipped. * Transient connection failures are retried once after reconnecting the affected server. * * @example * ```typescript * const agent = new Agent({ * id: 'multi-tool-agent', * name: 'Multi-tool Agent', * instructions: 'You have access to weather and stock tools.', * model: 'openai/gpt-4', * tools: await mcp.listTools(), // weather_getWeather, stockPrice_getPrice * }); * ``` */ listTools(): Promise>>; /** * Retrieves all tools from all configured servers with namespaced names, * along with any per-server errors. * * Like listTools(), but also returns errors for servers that failed to connect * or list tools. This allows callers to report specific failure reasons per server. * * @returns Object with successful `tools`, legacy string `errors`, and structured `errorDetails`. * Transient connection failures are retried once after reconnecting the affected server. * * @example * ```typescript * const { tools, errors, errorDetails } = await mcp.listToolsWithErrors(); * for (const [name, err] of Object.entries(errors)) { * console.error(`Server ${name} failed: ${err}`, errorDetails[name]); * } * ``` */ listToolsWithErrors(options?: MCPDiscoveryOptions): Promise<{ tools: Record>; errors: Record; errorDetails: Record; durations?: Record; }>; /** * Returns toolsets organized by server name for dynamic tool injection. * * Unlike listTools(), this returns tools grouped by server without namespacing. * This is intended to be passed dynamically to the generate() or stream() method. * * @returns Object mapping server names to their tool collections. * Errors for individual servers are logged but don't throw - failed servers are skipped. * * @example * ```typescript * const agent = new Agent({ * id: 'dynamic-agent', * name: 'Dynamic Agent', * instructions: 'You can use tools dynamically.', * model: 'openai/gpt-4', * }); * * const response = await agent.stream(prompt, { * toolsets: await mcp.listToolsets(), // { weather: {...}, stockPrice: {...} } * }); * ``` */ listToolsets(): Promise>>>; /** * Returns toolsets organized by server name, along with any per-server errors. * * Like listToolsets(), but also returns errors for servers that failed to connect * or list tools. This allows callers to report specific failure reasons per server. * * @returns Object with successful `toolsets`, legacy string `errors`, and structured `errorDetails`. * Transient connection failures are retried once after reconnecting the affected server. * * @example * ```typescript * const { toolsets, errors, errorDetails } = await mcp.listToolsetsWithErrors(); * for (const [name, err] of Object.entries(errors)) { * console.error(`Server ${name} failed: ${err}`, errorDetails[name]); * } * ``` */ listToolsetsWithErrors(options?: MCPDiscoveryOptions): Promise<{ toolsets: Record>>; errors: Record; errorDetails: Record; durations?: Record; }>; /** * Discovers every configured server's tools as plain, serializable definitions. * * Unlike `listTools()`/`listToolsets()`, the result contains no functions or references to a * live client, so it can be JSON-serialized and cached (Redis, a database, a build artifact) * and reused by other processes. Rebuild an executable tool from a cached definition with * {@link toolFromDefinition}, which does not reconnect. * * Definitions are grouped by server and keyed by the server's own tool name, without the * `serverName_toolName` namespacing that `listTools()` applies. * * @example * ```typescript * // Once, at build time or on the first worker: * const definitions = await mcp.listToolDefinitions(); * await cache.set('mcp-tools', JSON.stringify(definitions)); * * // In every other worker, with no MCP connections opened: * const definitions = JSON.parse(await cache.get('mcp-tools')); * const tool = mcp.toolFromDefinition('weather', definitions.weather.getForecast); * ``` */ listToolDefinitions(): Promise; /** * Like {@link listToolDefinitions}, but also returns errors for servers that failed to * connect instead of surfacing only the servers that succeeded. * * Useful when caching a catalog, since it lets you avoid persisting a partial manifest that * silently omits a server which happened to be down at discovery time. * `errors` remains a string map for compatibility; `errorDetails` preserves * machine-readable transport status and error codes when available. */ listToolDefinitionsWithErrors(options?: MCPDiscoveryOptions): Promise<{ definitions: SerializableMCPToolCatalog; errors: Record; errorDetails: Record; durations?: Record; }>; /** * Rebuilds an executable Mastra tool from a cached {@link SerializableMCPToolDefinition}. * * No MCP connection is opened here — that is the point of the method. The underlying client * connects lazily, the first time the returned tool is actually executed, so a worker can * reconstruct an entire tool map at startup and only pay for connections to the servers whose * tools the model really calls. * * The returned tool behaves exactly like one from `listTools()`: same strict-mode metadata, * approval policy, structured content handling, in-band tool errors, progress metadata, abort * signal support, and reconnect/retry behavior. * * @param serverName Name of the server the definition came from, as configured on this client. * @param definition A definition previously obtained from {@link listToolDefinitions}. */ toolFromDefinition({ serverName, definition, }: { serverName: string; definition: SerializableMCPToolDefinition; }): Promise>; /** * Rebuilds an entire cached catalog into a namespaced tool map, without connecting. * * This is the cached counterpart to `listTools()`: it produces the same `serverName_toolName` * keys, so an agent's tool map can be reconstructed on a cold start from a catalog in Redis * and dropped straight into the agent, with connections opened lazily per tool call. * * Servers present in the catalog but no longer configured on this client are skipped, so a * stale cached manifest degrades gracefully instead of throwing. * * @example * ```typescript * const definitions = JSON.parse(await cache.get('mcp-tools')); * const agent = new Agent({ tools: await mcp.toolsFromDefinitions({ definitions }), ... }); * ``` */ toolsFromDefinitions({ definitions: catalog, }: { definitions: SerializableMCPToolCatalog; }): Promise>>; private listResourcesWithErrors; private listResourceTemplatesWithErrors; private listPromptsWithErrors; private discoverValuesWithErrors; /** * Runs a per-server discovery `operation` against every configured server * concurrently, isolating and logging per-server failures. Results are * returned in configuration order (`Object.keys(serverConfigs)`) so callers * fold them back deterministically. * * Mirrors the parallel teardown in `disconnect()`: each server is bounded by * its own request timeout, so total time is the slowest single server rather * than the sum, and one slow or unresponsive server never stalls the others. * Backs `listTools`/`listToolsets`, `resources.list`/`templates`, and * `prompts.list`. */ private discoverAcrossServers; /** * Creates `MCPServerBase` proxy objects for each server connection in this * MCPClient. The returned record can be spread directly into Mastra's * `mcpServers` config so that external (non-Mastra) servers appear in Studio * alongside local MCPServer instances. * * @returns Record mapping server names to proxy instances * * @example * ```typescript * const mcp = new MCPClient({ * servers: { * trailhead: { command: 'npx', args: ['trailhead-server'] }, * }, * }); * * const mastra = new Mastra({ * mcpServers: { * ...mcp.toMCPServerProxies(), * }, * }); * ``` */ toMCPServerProxies(): Record; /** * Gets the stderr stream of a connected stdio server. * * Only available for servers using stdio transport with `stderr: 'pipe'`. * Returns null if the server is not connected, not using stdio, or stderr is not piped. * * @param serverName - The name of the server * @returns The stderr stream, or null */ getServerStderr(serverName: string): Stream | null; private getServerConfig; private getOrCreateClient; private getConnectedClient; private handleConnectError; private getConnectedClientForServer; private getClientForServer; private getToolsForServer; } //# sourceMappingURL=configuration.d.ts.map