@mozilla-ai/mcpd 0.0.4 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -20
- package/dist/client.d.ts.map +1 -1
- package/dist/errors.d.ts +68 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +47 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/errors.ts","../src/types.ts","../src/utils/cache.ts","../src/dynamicCaller.ts","../src/utils/typeConverter.ts","../src/functionBuilder.ts","../src/apiPaths.ts","../src/logger.ts","../src/client.ts"],"sourcesContent":["/**\n * Exception hierarchy for the mcpd SDK.\n *\n * This module provides a structured exception hierarchy to help users handle\n * different error scenarios appropriately.\n */\n\nimport type { ErrorModel } from \"./types\";\n\n/**\n * Base exception for all mcpd SDK errors.\n *\n * This exception wraps all errors that occur during interaction with the mcpd daemon,\n * including network failures, authentication errors, server errors, and tool execution\n * failures. The original exception is preserved via the cause property for debugging.\n */\nexport class McpdError extends Error {\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = \"McpdError\";\n this.cause = cause;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when unable to connect to the mcpd daemon.\n *\n * This typically indicates that:\n * - The mcpd daemon is not running\n * - The endpoint URL is incorrect\n * - Network connectivity issues\n * - Firewall blocking the connection\n */\nexport class ConnectionError extends McpdError {\n constructor(message: string, cause?: Error) {\n super(message, cause);\n this.name = \"ConnectionError\";\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when authentication with the mcpd daemon fails.\n *\n * This indicates that:\n * - The API key is invalid or expired\n * - The API key is missing but required\n * - The authentication method is not supported\n */\nexport class AuthenticationError extends McpdError {\n constructor(message: string, cause?: Error) {\n super(message, cause);\n this.name = \"AuthenticationError\";\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when a specified MCP server doesn't exist.\n *\n * This error occurs when trying to access a server that:\n * - Is not configured in the mcpd daemon\n * - Has been removed or renamed\n * - Is temporarily unavailable\n */\nexport class ServerNotFoundError extends McpdError {\n public readonly serverName: string | undefined;\n\n constructor(message: string, serverName?: string, cause?: Error) {\n super(message, cause);\n this.name = \"ServerNotFoundError\";\n this.serverName = serverName;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when a specified MCP server is not healthy.\n *\n * This indicates that the server exists but is currently unhealthy:\n * - The server is down or unreachable\n * - Timeout occurred while checking health\n * - No health data is available for the server\n */\nexport class ServerUnhealthyError extends McpdError {\n public readonly serverName: string;\n public readonly healthStatus: string;\n\n constructor(\n message: string,\n serverName: string,\n healthStatus: string,\n cause?: Error,\n ) {\n super(message, cause);\n this.name = \"ServerUnhealthyError\";\n this.serverName = serverName;\n this.healthStatus = healthStatus;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when a specified tool doesn't exist on a server.\n *\n * This error occurs when trying to call a tool that:\n * - Doesn't exist on the specified server\n * - Has been removed or renamed\n * - Is temporarily unavailable\n */\nexport class ToolNotFoundError extends McpdError {\n public readonly serverName: string | undefined;\n public readonly toolName: string | undefined;\n\n constructor(\n message: string,\n serverName?: string,\n toolName?: string,\n cause?: Error,\n ) {\n super(message, cause);\n this.name = \"ToolNotFoundError\";\n this.serverName = serverName;\n this.toolName = toolName;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when a tool execution fails on the server side.\n *\n * This indicates that the tool was found and called, but failed during execution:\n * - Invalid parameters provided\n * - Server-side error during tool execution\n * - Tool returned an error response\n * - Timeout during tool execution\n */\nexport class ToolExecutionError extends McpdError {\n public readonly serverName: string | undefined;\n public readonly toolName: string | undefined;\n public readonly errorModel: ErrorModel | undefined;\n\n constructor(\n message: string,\n serverName?: string,\n toolName?: string,\n errorModel?: ErrorModel,\n cause?: Error,\n ) {\n super(message, cause);\n this.name = \"ToolExecutionError\";\n this.serverName = serverName;\n this.toolName = toolName;\n this.errorModel = errorModel;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when input validation fails.\n *\n * This occurs when:\n * - Required parameters are missing\n * - Parameter types don't match the schema\n * - Parameter values don't meet constraints\n */\nexport class ValidationError extends McpdError {\n public readonly validationErrors: string[];\n\n constructor(message: string, validationErrors?: string[], cause?: Error) {\n super(message, cause);\n this.name = \"ValidationError\";\n this.validationErrors = validationErrors || [];\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when an operation times out.\n *\n * This can occur during:\n * - Long-running tool executions\n * - Slow network connections\n * - Unresponsive mcpd daemon\n */\nexport class TimeoutError extends McpdError {\n public readonly operation: string | undefined;\n public readonly timeout: number | undefined;\n\n constructor(\n message: string,\n operation?: string,\n timeout?: number,\n cause?: Error,\n ) {\n super(message, cause);\n this.name = \"TimeoutError\";\n this.operation = operation;\n this.timeout = timeout;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n","/**\n * Type definitions for the mcpd SDK.\n */\n\nimport type { Logger } from \"./logger\";\n\n/**\n * Enumeration of possible MCP server health statuses.\n */\nexport enum HealthStatus {\n OK = \"ok\",\n TIMEOUT = \"timeout\",\n UNREACHABLE = \"unreachable\",\n UNKNOWN = \"unknown\",\n}\n\n/**\n * Helper functions for HealthStatus.\n */\nexport const HealthStatusHelpers = {\n /**\n * Check if the given health status is a transient error state.\n */\n isTransient(status: string): boolean {\n return status === HealthStatus.TIMEOUT || status === HealthStatus.UNKNOWN;\n },\n\n /**\n * Check if the given status string represents a healthy state.\n */\n isHealthy(status: string): boolean {\n return status === HealthStatus.OK;\n },\n};\n\n/**\n * Error detail from Huma API error responses.\n * Location and value are optional as the API doesn't always include them.\n */\nexport interface ErrorDetail {\n location?: string;\n message: string;\n value?: unknown;\n}\n\n/**\n * Huma API error model (RFC 7807 Problem Details).\n * Used for all API errors including HTTP errors and tool execution failures.\n */\nexport interface ErrorModel {\n $schema?: string;\n detail: string;\n errors?: ErrorDetail[];\n instance?: string;\n status: number;\n title: string;\n type: string;\n}\n\n/**\n * JSON Schema definition for tool parameters.\n */\nexport interface JsonSchema {\n type?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n properties?: Record<string, any>;\n required?: string[];\n additionalProperties?: boolean;\n items?: JsonSchema;\n description?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n}\n\n/**\n * Tool annotations for hints about tool behavior.\n */\nexport interface ToolAnnotations {\n title?: string;\n destructiveHint?: boolean;\n idempotentHint?: boolean;\n openWorldHint?: boolean;\n readOnlyHint?: boolean;\n}\n\n/**\n * MCP tool definition following the Model Context Protocol specification (2025-06-18).\n *\n * @see https://spec.modelcontextprotocol.io/specification/2025-06-18/server/tools/\n */\nexport interface Tool {\n /**\n * Unique identifier for the tool (required).\n */\n name: string;\n\n /**\n * Optional human-readable title for display.\n */\n title?: string;\n\n /**\n * Human-readable description of what the tool does (optional in MCP spec).\n *\n * Note: mcpd API currently requires this field, but MCP spec makes it optional.\n * This SDK follows the MCP spec to remain protocol-compliant.\n */\n description?: string;\n\n /**\n * JSON Schema defining the tool's input parameters (required in MCP spec).\n *\n * Note: mcpd API currently makes this optional, but MCP spec requires it.\n * This SDK follows the MCP spec to remain protocol-compliant.\n */\n inputSchema: JsonSchema;\n\n /**\n * Optional JSON Schema defining the tool's output structure.\n */\n outputSchema?: JsonSchema;\n\n /**\n * Optional hints about tool behavior (readonly, destructive, idempotent, etc.).\n */\n annotations?: ToolAnnotations;\n\n /**\n * Optional metadata for extensibility.\n */\n _meta?: Record<string, unknown>;\n}\n\n/**\n * Tools list response from the mcpd API.\n */\nexport interface Tools {\n $schema?: string;\n tools: Tool[];\n}\n\n/**\n * Server health information from the mcpd API.\n * Represents the health status of an MCP server.\n */\nexport interface ServerHealth {\n /**\n * Name of the server (required).\n */\n name: string;\n\n /**\n * Health status of the server (required).\n * Common values: 'ok', 'timeout', 'unreachable', 'unknown'\n */\n status: string;\n\n /**\n * Optional JSON Schema reference.\n */\n $schema?: string;\n\n /**\n * Timestamp of the last health check (ISO 8601 date-time).\n */\n lastChecked?: string;\n\n /**\n * Timestamp of the last successful health check (ISO 8601 date-time).\n */\n lastSuccessful?: string;\n\n /**\n * Latency of the health check (e.g., '2ms', '1.5s').\n */\n latency?: string;\n}\n\n/**\n * Tools response from the mcpd daemon.\n */\nexport interface ToolsResponse {\n tools?: Tool[];\n [serverName: string]: Tool[] | undefined;\n}\n\n/**\n * Health response from the mcpd API.\n * Contains health information for all tracked servers.\n */\nexport interface HealthResponse {\n $schema?: string;\n servers: ServerHealth[];\n}\n\n/**\n * Configuration options for the McpdClient.\n */\nexport interface McpdClientOptions {\n /**\n * The mcpd daemon API endpoint URL.\n */\n apiEndpoint: string;\n\n /**\n * Optional API key for authentication.\n */\n apiKey?: string;\n\n /**\n * TTL in seconds for caching server health checks.\n */\n healthCacheTtl?: number;\n\n /**\n * Request timeout in milliseconds.\n */\n timeout?: number;\n\n /**\n * Optional custom logger for SDK warnings and errors.\n *\n * If not provided, uses default logger (disabled by default).\n * Logging can be enabled by setting the MCPD_LOG_LEVEL environment variable.\n *\n * Supports partial implementations - any omitted methods fall back to the\n * default logger, which respects MCPD_LOG_LEVEL.\n *\n * NOTE: It is recommended that you only enable logging in non-MCP-server contexts.\n * MCP servers using stdio transport for JSON-RPC communication should avoid enabling logging\n * to avoid contaminating stdout/stderr.\n *\n * @example\n * ```typescript\n * // Use default logger (controlled by MCPD_LOG_LEVEL env var).\n * const client = new McpdClient({ apiEndpoint: \"http://localhost:8090\" });\n *\n * // Inject full custom logger.\n * const client = new McpdClient({\n * apiEndpoint: \"http://localhost:8090\",\n * logger: myCustomLogger,\n * });\n *\n * // Partial logger: custom warn/error, default (MCPD_LOG_LEVEL-aware) for others.\n * const client = new McpdClient({\n * apiEndpoint: \"http://localhost:8090\",\n * logger: {\n * warn: (msg) => myLogger.warn(`[mcpd] ${msg}`),\n * error: (msg) => myLogger.error(`[mcpd] ${msg}`),\n * // trace, debug, info use default logger (respects MCPD_LOG_LEVEL)\n * },\n * });\n *\n * // Disable logging: ensure MCPD_LOG_LEVEL is unset or set to 'off' (default).\n * const client = new McpdClient({ apiEndpoint: \"http://localhost:8090\" });\n *\n * // Override MCPD_LOG_LEVEL (disable even if env var is set).\n * const client = new McpdClient({\n * apiEndpoint: \"http://localhost:8090\",\n * logger: {\n * trace: () => {},\n * debug: () => {},\n * info: () => {},\n * warn: () => {},\n * error: () => {},\n * },\n * });\n * ```\n */\n logger?: Partial<Logger>;\n}\n\n/**\n * Tool format types for cross-framework compatibility.\n *\n * @remarks\n * Output format for agent tools.\n * - 'array': Returns array of functions (default, for LangChain)\n * - 'object': Returns object keyed by tool name (for Vercel AI SDK)\n * - 'map': Returns Map keyed by tool name\n */\nexport type AgentToolsFormat = \"array\" | \"object\" | \"map\";\n\n/**\n * Base options shared across all agent tools configurations.\n */\nexport interface BaseAgentToolsOptions {\n /**\n * List of server names to include. If not specified, or empty, should include all servers.\n */\n servers?: string[];\n\n /**\n * List of tool names to filter by.\n *\n * @remarks\n * Supports both:\n * - Raw tool names: 'get_current_time' (matches tool across all servers)\n * - Server-prefixed names: 'time__get_current_time' (server + TOOL_SEPARATOR + tool)\n * If not specified, returns all tools from selected servers.\n *\n * @example ['add', 'multiply']\n * @example ['time__get_current_time', 'math__add']\n */\n tools?: string[];\n\n /**\n * When true, clears the agent tools cache and fetches fresh tool schemas from servers.\n * When false or undefined, returns cached functions if available.\n *\n * @defaultValue false\n */\n refreshCache?: boolean;\n}\n\n/**\n * Options for getAgentTools with array format (default).\n * Returns an array of agent functions.\n */\nexport interface ArrayAgentToolsOptions extends BaseAgentToolsOptions {\n format?: \"array\";\n}\n\n/**\n * Options for getAgentTools with object format.\n * Returns an object keyed by tool name.\n */\nexport interface ObjectAgentToolsOptions extends BaseAgentToolsOptions {\n format: \"object\";\n}\n\n/**\n * Options for getAgentTools with map format.\n * Returns a Map keyed by tool name.\n */\nexport interface MapAgentToolsOptions extends BaseAgentToolsOptions {\n format: \"map\";\n}\n\n/**\n * Options for generating agent tools.\n * Discriminated union based on the format field.\n */\nexport type AgentToolsOptions =\n | ArrayAgentToolsOptions\n | ObjectAgentToolsOptions\n | MapAgentToolsOptions;\n\n/**\n * Function signature for performing tool calls.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type PerformCallFn = (\n serverName: string,\n toolName: string,\n args?: Record<string, unknown>,\n) => Promise<unknown>;\n\n/**\n * Function signature for getting tools from a server.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type GetToolsFn = (serverName: string) => Promise<Tool[]>;\n\n/**\n * Function signature for getting prompt templates from a server.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type GetPromptsFn = (serverName: string) => Promise<Prompt[]>;\n\n/**\n * Function signature for generating a prompt from a template.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type GeneratePromptFn = (\n serverName: string,\n promptName: string,\n args?: Record<string, string>,\n) => Promise<GeneratePromptResponseBody>;\n\n/**\n * Function signature for getting resources from a server.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type GetResourcesFn = (serverName: string) => Promise<Resource[]>;\n\n/**\n * Function signature for getting resource templates from a server.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type GetResourceTemplatesFn = (\n serverName: string,\n) => Promise<ResourceTemplate[]>;\n\n/**\n * Function signature for reading resource content from a server.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type ReadResourceFn = (\n serverName: string,\n uri: string,\n) => Promise<ResourceContent[]>;\n\n/**\n * MCP resource definition.\n */\nexport interface Resource {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n _meta?: Record<string, unknown>;\n}\n\n/**\n * Resources list response from the mcpd API.\n */\nexport interface Resources {\n $schema?: string;\n resources: Resource[];\n nextCursor?: string;\n}\n\n/**\n * Prompt argument definition.\n */\nexport interface PromptArgument {\n name: string;\n description?: string;\n required?: boolean;\n}\n\n/**\n * MCP prompt definition.\n */\nexport interface Prompt {\n name: string;\n description?: string;\n arguments?: PromptArgument[];\n _meta?: Record<string, unknown>;\n}\n\n/**\n * Prompts list response from the mcpd API.\n */\nexport interface Prompts {\n $schema?: string;\n prompts: Prompt[];\n nextCursor?: string;\n}\n\n/**\n * Prompt message in a generated prompt.\n */\nexport interface PromptMessage {\n role: string;\n content: unknown;\n}\n\n/**\n * Generated prompt response from the mcpd API.\n */\nexport interface GeneratePromptResponseBody {\n $schema?: string;\n description?: string;\n messages: PromptMessage[];\n}\n\n/**\n * Resource content response from the mcpd API.\n */\nexport interface ResourceContent {\n uri: string;\n text?: string;\n blob?: string;\n mimeType?: string;\n _meta?: Record<string, unknown>;\n}\n\n/**\n * MCP resource template definition.\n */\nexport interface ResourceTemplate {\n uriTemplate: string;\n name: string;\n description?: string;\n mimeType?: string;\n _meta?: Record<string, unknown>;\n}\n\n/**\n * Resource templates list response from the mcpd API.\n */\nexport interface ResourceTemplates {\n $schema?: string;\n templates: ResourceTemplate[];\n nextCursor?: string;\n}\n\n/**\n * Arguments for generating a prompt from a template.\n */\nexport interface PromptGenerateArguments {\n $schema?: string;\n arguments?: Record<string, string>;\n}\n","/**\n * Cache utilities for the mcpd SDK.\n */\n\nimport { LRUCache } from \"lru-cache\";\n\n/**\n * Options for creating a TTL cache.\n */\nexport interface CacheOptions {\n /**\n * Maximum number of items to store in the cache.\n */\n max?: number;\n\n /**\n * TTL in milliseconds for cached items.\n */\n ttl?: number;\n}\n\n/**\n * Creates a new LRU cache with TTL support.\n *\n * @param options - Cache configuration options\n * @returns A configured LRU cache instance\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type, @typescript-eslint/no-explicit-any\nexport function createCache<K extends {} = string, V extends {} = any>(\n options: CacheOptions = {},\n): LRUCache<K, V> {\n return new LRUCache<K, V>({\n max: options.max ?? 100,\n ttl: options.ttl ?? 10000, // Default 10 seconds\n updateAgeOnGet: false,\n updateAgeOnHas: false,\n });\n}\n","/**\n * Dynamic tool invocation for mcpd client.\n *\n * This module provides the ServersNamespace, Server, and ToolsNamespace classes\n * that enable natural JavaScript syntax for calling MCP tools, such as:\n * client.servers.time.tools.get_current_time(args)\n *\n * The dynamic calling system uses JavaScript's Proxy to create\n * a fluent interface that resolves server and tool names at runtime.\n *\n * Naming convention:\n * - *Namespace classes use Proxy for dynamic property access\n * - Server is a concrete class representing one MCP server\n */\n\nimport { ToolNotFoundError } from \"./errors\";\nimport type {\n Tool,\n Prompt,\n Resource,\n ResourceTemplate,\n ResourceContent,\n GeneratePromptResponseBody,\n PerformCallFn,\n GetToolsFn,\n GetPromptsFn,\n GeneratePromptFn,\n GetResourcesFn,\n GetResourceTemplatesFn,\n ReadResourceFn,\n} from \"./types\";\n\n/**\n * Namespace for accessing MCP servers via proxy.\n *\n * This class provides the `client.servers.*` namespace, allowing you to access\n * servers and their tools with natural JavaScript syntax.\n *\n * @example\n * ```typescript\n * const client = new McpdClient({ apiEndpoint: 'http://localhost:8090' });\n *\n * // Access tools through the servers namespace\n * const result = await client.servers.time.tools.get_current_time({ timezone: \"UTC\" });\n *\n * // Check if a tool exists\n * if (await client.servers.time.hasTool(\"get_current_time\")) {\n * // ...\n * }\n * ```\n */\nexport class ServersNamespace {\n [serverName: string]: Server;\n\n #performCall: PerformCallFn;\n #getTools: GetToolsFn;\n #generatePrompt: GeneratePromptFn;\n #getPrompts: GetPromptsFn;\n #getResources: GetResourcesFn;\n #getResourceTemplates: GetResourceTemplatesFn;\n #readResource: ReadResourceFn;\n\n /**\n * Initialize the ServersNamespace with injected functions.\n *\n * @param options - Configuration object\n * @param options.performCall - Function to execute tool calls\n * @param options.getTools - Function to get tool schemas\n * @param options.generatePrompt - Function to generate prompts\n * @param options.getPrompts - Function to get prompt schemas\n * @param options.getResources - Function to get resources\n * @param options.getResourceTemplates - Function to get resource templates\n * @param options.readResource - Function to read resource content\n */\n constructor({\n performCall,\n getTools,\n generatePrompt,\n getPrompts,\n getResources,\n getResourceTemplates,\n readResource,\n }: {\n performCall: PerformCallFn;\n getTools: GetToolsFn;\n generatePrompt: GeneratePromptFn;\n getPrompts: GetPromptsFn;\n getResources: GetResourcesFn;\n getResourceTemplates: GetResourceTemplatesFn;\n readResource: ReadResourceFn;\n }) {\n this.#performCall = performCall;\n this.#getTools = getTools;\n this.#generatePrompt = generatePrompt;\n this.#getPrompts = getPrompts;\n this.#getResources = getResources;\n this.#getResourceTemplates = getResourceTemplates;\n this.#readResource = readResource;\n\n // Return a Proxy to intercept property access\n return new Proxy(this, {\n get: (target, serverName: string | symbol) => {\n if (typeof serverName !== \"string\") {\n return undefined;\n }\n return new Server(\n target.#performCall,\n target.#getTools,\n target.#generatePrompt,\n target.#getPrompts,\n target.#getResources,\n target.#getResourceTemplates,\n target.#readResource,\n serverName,\n );\n },\n });\n }\n}\n\n/**\n * Represents a specific MCP server, providing access to its tools and operations.\n *\n * This class represents a specific MCP server and provides access to its tools\n * through the `.tools` namespace, as well as server-level operations like listing tools.\n *\n * @example\n * ```typescript\n * // Server is created when you access a server:\n * const timeServer = client.servers.time; // Returns Server(...)\n *\n * // List available tools\n * const tools = await timeServer.getTools();\n *\n * // Call tools through the .tools namespace:\n * await timeServer.tools.get_current_time({ timezone: \"UTC\" })\n * ```\n */\nexport class Server {\n readonly tools: ToolsNamespace;\n readonly prompts: PromptsNamespace;\n\n #performCall: PerformCallFn;\n #getTools: GetToolsFn;\n #generatePrompt: GeneratePromptFn;\n #getPrompts: GetPromptsFn;\n #getResources: GetResourcesFn;\n #getResourceTemplates: GetResourceTemplatesFn;\n #readResource: ReadResourceFn;\n #serverName: string;\n\n /**\n * Initialize a Server for a specific server.\n *\n * @param performCall - Function to execute tool calls\n * @param getTools - Function to get tool schemas\n * @param generatePrompt - Function to generate prompts\n * @param getPrompts - Function to get prompt schemas\n * @param getResources - Function to get resources\n * @param getResourceTemplates - Function to get resource templates\n * @param readResource - Function to read resource content\n * @param serverName - The name of the MCP server\n */\n constructor(\n performCall: PerformCallFn,\n getTools: GetToolsFn,\n generatePrompt: GeneratePromptFn,\n getPrompts: GetPromptsFn,\n getResources: GetResourcesFn,\n getResourceTemplates: GetResourceTemplatesFn,\n readResource: ReadResourceFn,\n serverName: string,\n ) {\n this.#performCall = performCall;\n this.#getTools = getTools;\n this.#generatePrompt = generatePrompt;\n this.#getPrompts = getPrompts;\n this.#getResources = getResources;\n this.#getResourceTemplates = getResourceTemplates;\n this.#readResource = readResource;\n this.#serverName = serverName;\n\n // Create the tools namespace as a real property.\n this.tools = new ToolsNamespace(\n this.#performCall,\n this.#getTools,\n this.#serverName,\n );\n\n // Create the prompts namespace as a real property.\n this.prompts = new PromptsNamespace(\n this.#generatePrompt,\n this.#getPrompts,\n this.#serverName,\n );\n }\n\n /**\n * Get all tools available on this server.\n *\n * @returns Array of tool schemas\n * @throws {ServerNotFoundError} If the server doesn't exist\n * @throws {ServerUnhealthyError} If the server is unhealthy\n *\n * @example\n * ```typescript\n * const tools = await client.servers.time.getTools();\n * for (const tool of tools) {\n * console.log(`${tool.name}: ${tool.description}`);\n * }\n * ```\n */\n async getTools(): Promise<Tool[]> {\n return this.#getTools(this.#serverName);\n }\n\n /**\n * Check if a tool exists on this server.\n *\n * The tool name must match exactly as returned by the server.\n *\n * This method is designed as a safe boolean predicate - it catches all errors\n * (ServerNotFoundError, ServerUnhealthyError, ConnectionError, etc.) and returns\n * false rather than throwing. This makes it safe to use in conditional checks\n * without requiring error handling.\n *\n * @param toolName - The exact name of the tool to check\n * @returns True if the tool exists, false otherwise (including on errors)\n *\n * @example\n * ```typescript\n * if (await client.servers.time.hasTool('get_current_time')) {\n * const result = await client.servers.time.callTool('get_current_time', { timezone: 'UTC' });\n * }\n * ```\n */\n async hasTool(toolName: string): Promise<boolean> {\n try {\n const tools = await this.#getTools(this.#serverName);\n return tools.some((t) => t.name === toolName);\n } catch {\n // Return false on any error to provide a safe boolean predicate.\n return false;\n }\n }\n\n /**\n * Call a tool by name with the given arguments.\n *\n * This method is useful for programmatic tool invocation when the tool name\n * is in a variable. The tool name must match exactly as returned by the server.\n *\n * @param toolName - The exact name of the tool to call\n * @param args - The arguments to pass to the tool\n * @returns The tool's response\n * @throws {ToolNotFoundError} If the tool doesn't exist on the server\n *\n * @example\n * ```typescript\n * // Call with explicit method (useful for dynamic tool names):\n * const toolName = 'get_current_time';\n * await client.servers.time.callTool(toolName, { timezone: 'UTC' });\n *\n * // Or with dynamic server name:\n * const serverName = 'time';\n * await client.servers[serverName].callTool(toolName, { timezone: 'UTC' });\n * ```\n */\n async callTool(\n toolName: string,\n args?: Record<string, unknown>,\n ): Promise<unknown> {\n // Check if the tool exists (exact match only)\n const tools = await this.#getTools(this.#serverName);\n const tool = tools.find((t) => t.name === toolName);\n\n if (!tool) {\n throw new ToolNotFoundError(\n `Tool '${toolName}' not found on server '${this.#serverName}'. ` +\n `Use client.servers.${this.#serverName}.getTools() to see available tools.`,\n this.#serverName,\n toolName,\n );\n }\n\n // Perform the tool call\n return this.#performCall(this.#serverName, toolName, args);\n }\n\n /**\n * Get all prompts available on this server.\n *\n * Note: This method is marked `async` for consistency with other server methods,\n * even though it doesn't directly await. This maintains a uniform async interface\n * and allows for future enhancements without breaking the API contract.\n *\n * @returns Array of prompt schemas\n * @throws {ServerNotFoundError} If the server doesn't exist\n * @throws {ServerUnhealthyError} If the server is unhealthy\n *\n * @example\n * ```typescript\n * const prompts = await client.servers.github.getPrompts();\n * for (const prompt of prompts) {\n * console.log(`${prompt.name}: ${prompt.description}`);\n * }\n * ```\n */\n async getPrompts(): Promise<Prompt[]> {\n return this.#getPrompts(this.#serverName);\n }\n\n /**\n * Check if a prompt exists on this server.\n *\n * The prompt name must match exactly as returned by the server.\n *\n * This method is designed as a safe boolean predicate - it catches all errors\n * (ServerNotFoundError, ServerUnhealthyError, ConnectionError, etc.) and returns\n * false rather than throwing. This makes it safe to use in conditional checks\n * without requiring error handling.\n *\n * @param promptName - The exact name of the prompt to check\n * @returns True if the prompt exists, false otherwise (including on errors)\n *\n * @example\n * ```typescript\n * if (await client.servers.github.hasPrompt('create_pr')) {\n * const result = await client.servers.github.generatePrompt('create_pr', { title: 'Fix bug' });\n * }\n * ```\n */\n async hasPrompt(promptName: string): Promise<boolean> {\n try {\n const prompts = await this.#getPrompts(this.#serverName);\n return prompts.some((p) => p.name === promptName);\n } catch {\n // Return false on any error to provide a safe boolean predicate.\n return false;\n }\n }\n\n /**\n * Generate a prompt by name with the given arguments.\n *\n * This method is useful for programmatic prompt generation when the prompt name\n * is in a variable. The prompt name must match exactly as returned by the server.\n *\n * @param promptName - The exact name of the prompt to generate\n * @param args - The arguments to pass to the prompt template\n * @returns The generated prompt response\n * @throws {ToolNotFoundError} If the prompt doesn't exist on the server\n *\n * @example\n * ```typescript\n * // Call with explicit method (useful for dynamic prompt names):\n * const promptName = 'create_pr';\n * await client.servers.github.generatePrompt(promptName, { title: 'Fix bug' });\n *\n * // Or with dynamic server name:\n * const serverName = 'github';\n * await client.servers[serverName].generatePrompt(promptName, { title: 'Fix bug' });\n * ```\n */\n async generatePrompt(\n promptName: string,\n args?: Record<string, string>,\n ): Promise<GeneratePromptResponseBody> {\n // Check if the prompt exists (exact match only).\n const prompts = await this.#getPrompts(this.#serverName);\n const prompt = prompts.find((p) => p.name === promptName);\n\n if (!prompt) {\n throw new ToolNotFoundError(\n `Prompt '${promptName}' not found on server '${this.#serverName}'. ` +\n `Use client.servers.${this.#serverName}.getPrompts() to see available prompts.`,\n this.#serverName,\n promptName,\n );\n }\n\n // Generate the prompt.\n return this.#generatePrompt(this.#serverName, promptName, args);\n }\n\n /**\n * Get all resources available on this server.\n *\n * Note: This method is marked `async` for consistency with other server methods,\n * even though it doesn't directly await. This maintains a uniform async interface\n * and allows for future enhancements without breaking the API contract.\n *\n * @returns Array of resource schemas with original names\n * @throws {ServerNotFoundError} If the server doesn't exist\n * @throws {ServerUnhealthyError} If the server is unhealthy\n *\n * @example\n * ```typescript\n * const resources = await client.servers.github.getResources();\n * for (const resource of resources) {\n * console.log(`${resource.name}: ${resource.uri}`);\n * }\n * ```\n */\n async getResources(): Promise<Resource[]> {\n return this.#getResources(this.#serverName);\n }\n\n /**\n * Get all resource templates available on this server.\n *\n * Note: This method is marked `async` for consistency with other server methods,\n * even though it doesn't directly await. This maintains a uniform async interface\n * and allows for future enhancements without breaking the API contract.\n *\n * @returns Array of resource template schemas with original names\n * @throws {ServerNotFoundError} If the server doesn't exist\n * @throws {ServerUnhealthyError} If the server is unhealthy\n *\n * @example\n * ```typescript\n * const templates = await client.servers.github.getResourceTemplates();\n * for (const template of templates) {\n * console.log(`${template.name}: ${template.uriTemplate}`);\n * }\n * ```\n */\n async getResourceTemplates(): Promise<ResourceTemplate[]> {\n return this.#getResourceTemplates(this.#serverName);\n }\n\n /**\n * Check if a resource exists on this server.\n *\n * The resource URI must match exactly as returned by the server.\n *\n * This method is designed as a safe boolean predicate - it catches all errors\n * (ServerNotFoundError, ServerUnhealthyError, ConnectionError, etc.) and returns\n * false rather than throwing. This makes it safe to use in conditional checks\n * without requiring error handling.\n *\n * @param uri - The exact URI of the resource to check\n * @returns True if the resource exists, false otherwise (including on errors)\n *\n * @example\n * ```typescript\n * if (await client.servers.github.hasResource('file:///repo/README.md')) {\n * const content = await client.servers.github.readResource('file:///repo/README.md');\n * }\n * ```\n */\n async hasResource(uri: string): Promise<boolean> {\n try {\n const resources = await this.#getResources(this.#serverName);\n return resources.some((r) => r.uri === uri);\n } catch {\n // Return false on any error to provide a safe boolean predicate.\n return false;\n }\n }\n\n /**\n * Read resource content by URI from this server.\n *\n * @param uri - The resource URI\n * @returns Array of resource contents (text or blob)\n * @throws {ServerNotFoundError} If the server doesn't exist\n * @throws {ServerUnhealthyError} If the server is unhealthy\n *\n * @example\n * ```typescript\n * const contents = await client.servers.github.readResource('file:///repo/README.md');\n * for (const content of contents) {\n * if (content.text) {\n * console.log(content.text);\n * } else if (content.blob) {\n * console.log('Binary content:', content.blob.substring(0, 50) + '...');\n * }\n * }\n * ```\n */\n async readResource(uri: string): Promise<ResourceContent[]> {\n return this.#readResource(this.#serverName, uri);\n }\n}\n\n/**\n * Namespace for accessing tools on a specific MCP server via proxy.\n *\n * This class provides the `.tools` namespace for a server, allowing you to call\n * tools as if they were methods. All tool names must match exactly as returned\n * by the MCP server.\n *\n * NOTE: Use `client.servers.foo.callTool()` and `client.servers.foo.hasTool()`\n * instead of putting them in the `.tools` namespace to avoid collisions with\n * actual tools named \"callTool\" or \"hasTool\".\n *\n * @example\n * ```typescript\n * // Call tools via .tools namespace with static names\n * const result = await client.servers.time.tools.get_current_time({ timezone: \"UTC\" });\n * ```\n */\nexport class ToolsNamespace {\n [toolName: string]: (args?: Record<string, unknown>) => Promise<unknown>;\n\n #performCall: PerformCallFn;\n #getTools: GetToolsFn;\n #serverName: string;\n\n /**\n * Initialize a ToolsNamespace for a specific server.\n *\n * @param performCall - Function to execute tool calls\n * @param getTools - Function to get tool schemas\n * @param serverName - The name of the MCP server\n */\n constructor(\n performCall: PerformCallFn,\n getTools: GetToolsFn,\n serverName: string,\n ) {\n this.#performCall = performCall;\n this.#getTools = getTools;\n this.#serverName = serverName;\n\n // Return a Proxy to intercept method calls\n return new Proxy(this, {\n get: (target, prop: string | symbol) => {\n if (typeof prop !== \"string\") {\n return undefined;\n }\n\n // Return a function that will call the tool with exact name matching\n return async (args?: Record<string, unknown>) => {\n const toolName = prop;\n\n // Check if the tool exists (exact match only)\n const tools = await target.#getTools(target.#serverName);\n const tool = tools.find((t) => t.name === toolName);\n\n if (!tool) {\n throw new ToolNotFoundError(\n `Tool '${toolName}' not found on server '${target.#serverName}'. ` +\n `Use client.servers.${target.#serverName}.getTools() to see available tools.`,\n target.#serverName,\n toolName,\n );\n }\n\n // Perform the tool call\n return target.#performCall(target.#serverName, toolName, args);\n };\n },\n });\n }\n}\n\n/**\n * Namespace for accessing prompts on a specific MCP server via proxy.\n *\n * This class provides the `.prompts` namespace for a server, allowing you to generate\n * prompts as if they were methods. All prompt names must match exactly as returned\n * by the MCP server.\n *\n * NOTE: Use `client.servers.foo.generatePrompt()` and `client.servers.foo.hasPrompt()`\n * instead of putting them in the `.prompts` namespace to avoid collisions with\n * actual prompts named \"generatePrompt\" or \"hasPrompt\".\n *\n * @example\n * ```typescript\n * // Generate prompts via .prompts namespace with static names\n * const result = await client.servers.github.prompts.create_pr({\n * title: \"Fix bug\",\n * description: \"Fixed auth issue\"\n * });\n * ```\n */\nexport class PromptsNamespace {\n [promptName: string]: (\n args?: Record<string, string>,\n ) => Promise<GeneratePromptResponseBody>;\n\n #generatePrompt: GeneratePromptFn;\n #getPrompts: GetPromptsFn;\n #serverName: string;\n\n /**\n * Initialize a PromptsNamespace for a specific server.\n *\n * @param generatePrompt - Function to generate prompts\n * @param getPrompts - Function to get prompt schemas\n * @param serverName - The name of the MCP server\n */\n constructor(\n generatePrompt: GeneratePromptFn,\n getPrompts: GetPromptsFn,\n serverName: string,\n ) {\n this.#generatePrompt = generatePrompt;\n this.#getPrompts = getPrompts;\n this.#serverName = serverName;\n\n // Return a Proxy to intercept method calls.\n return new Proxy(this, {\n get: (target, prop: string | symbol) => {\n if (typeof prop !== \"string\") {\n return undefined;\n }\n\n // Return a function that will generate the prompt with exact name matching.\n return async (args?: Record<string, string>) => {\n const promptName = prop;\n\n // Check if the prompt exists (exact match only).\n const prompt = await target.#getPromptByName(promptName);\n\n if (!prompt) {\n throw new ToolNotFoundError(\n `Prompt '${promptName}' not found on server '${target.#serverName}'. ` +\n `Use client.servers.${target.#serverName}.getPrompts() to see available prompts.`,\n target.#serverName,\n promptName,\n );\n }\n\n // Generate the prompt.\n return target.#generatePrompt(target.#serverName, promptName, args);\n };\n },\n });\n }\n\n /**\n * Helper method to find a prompt by name on this server.\n *\n * @param promptName - The exact name of the prompt to find\n * @returns The prompt if found, undefined otherwise\n * @internal\n */\n async #getPromptByName(promptName: string): Promise<Prompt | undefined> {\n const prompts = await this.#getPrompts(this.#serverName);\n return prompts.find((p) => p.name === promptName);\n }\n}\n","/**\n * JSON Schema to JavaScript type conversion and validation utilities.\n *\n * This module provides the TypeConverter class that handles conversion between\n * JSON Schema type definitions and JavaScript runtime type information. It supports\n * all standard JSON Schema types including complex constructs like unions (anyOf)\n * and provides runtime validation of values against their schemas.\n *\n * Used primarily by the FunctionBuilder for parameter validation and generating\n * human-readable type descriptions for dynamically generated functions.\n */\n\nimport type { JsonSchema } from \"../types\";\n\n/**\n * Maps JSON Schema types to JavaScript/TypeScript types.\n */\nexport class TypeConverter {\n /**\n * Convert JSON schema types to JavaScript type names.\n *\n * Maps JSON Schema types to their JavaScript equivalents:\n * - \"string\" → \"string\"\n * - \"integer\" → \"number\"\n * - \"number\" → \"number\"\n * - \"boolean\" → \"boolean\"\n * - \"array\" → \"array\"\n * - \"object\" → \"object\"\n * - \"null\" → \"null\"\n * - unknown types → \"any\"\n */\n static jsonTypeToJavaScriptType(\n jsonType: string,\n schemaDef: JsonSchema,\n ): string {\n switch (jsonType) {\n case \"string\":\n if (schemaDef.enum && Array.isArray(schemaDef.enum)) {\n // For enums, we'll use string but note the allowed values\n return \"string\";\n }\n return \"string\";\n case \"number\":\n case \"integer\":\n return \"number\";\n case \"boolean\":\n return \"boolean\";\n case \"array\":\n return \"array\";\n case \"object\":\n return \"object\";\n case \"null\":\n return \"null\";\n default:\n return \"any\";\n }\n }\n\n /**\n * Parse a schema definition and return the appropriate JavaScript type name.\n */\n static parseSchemaType(schemaDef: JsonSchema): string {\n if (schemaDef.anyOf && Array.isArray(schemaDef.anyOf)) {\n // For unions, we'll use the first type or 'any' if complex\n const firstType = schemaDef.anyOf[0];\n if (firstType && typeof firstType === \"object\" && firstType.type) {\n return this.jsonTypeToJavaScriptType(firstType.type, firstType);\n }\n return \"any\";\n }\n\n if (schemaDef.type) {\n return this.jsonTypeToJavaScriptType(schemaDef.type, schemaDef);\n }\n\n return \"any\";\n }\n\n /**\n * Get a human-readable description of the expected type.\n */\n static getTypeDescription(schemaDef: JsonSchema): string {\n const baseType = this.parseSchemaType(schemaDef);\n\n if (schemaDef.enum && Array.isArray(schemaDef.enum)) {\n return `one of: ${schemaDef.enum.map((v) => JSON.stringify(v)).join(\", \")}`;\n }\n\n if (schemaDef.type === \"array\" && schemaDef.items) {\n const itemType = this.parseSchemaType(schemaDef.items);\n return `array of ${itemType}`;\n }\n\n return baseType;\n }\n\n /**\n * Validate a value against a JSON schema type.\n * Returns true if valid, false otherwise.\n */\n static validateValue(value: unknown, schemaDef: JsonSchema): boolean {\n if (value === null || value === undefined) {\n // Null/undefined handling depends on whether the schema allows null\n return (\n schemaDef.type === \"null\" ||\n (schemaDef.anyOf?.some((s: JsonSchema) => s.type === \"null\") ?? false)\n );\n }\n\n if (schemaDef.enum && Array.isArray(schemaDef.enum)) {\n return schemaDef.enum.includes(value);\n }\n\n if (schemaDef.anyOf && Array.isArray(schemaDef.anyOf)) {\n return schemaDef.anyOf.some((subSchema) =>\n this.validateValue(value, subSchema),\n );\n }\n\n if (!schemaDef.type) {\n return true; // No type constraint\n }\n\n switch (schemaDef.type) {\n case \"string\":\n return typeof value === \"string\";\n case \"number\":\n return typeof value === \"number\" && isFinite(value);\n case \"integer\":\n return typeof value === \"number\" && Number.isInteger(value);\n case \"boolean\":\n return typeof value === \"boolean\";\n case \"array\":\n if (!Array.isArray(value)) return false;\n if (schemaDef.items) {\n return value.every((item) =>\n this.validateValue(item, schemaDef.items!),\n );\n }\n return true;\n case \"object\":\n return (\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n );\n case \"null\":\n return value === null;\n default:\n return true; // Unknown type, allow anything\n }\n }\n}\n","/**\n * Function generation from MCP tool schemas.\n *\n * This module provides the FunctionBuilder class that dynamically generates\n * callable JavaScript functions from MCP tool JSON Schema definitions. These\n * functions can be used with AI agent frameworks and include proper parameter\n * validation and comprehensive metadata.\n *\n * The generated functions are self-contained and cached for performance.\n */\n\nimport { z } from \"zod\";\nimport { McpdError, ValidationError } from \"./errors\";\nimport type { Tool, PerformCallFn } from \"./types\";\nimport { TypeConverter } from \"./utils/typeConverter\";\n\n/**\n * Interface for generated agent functions with metadata.\n * Compatible with both LangChain JS and Vercel AI SDK without conversion.\n */\nexport interface AgentFunction {\n (...args: unknown[]): Promise<unknown>;\n\n // Universal properties\n name: string;\n description: string;\n\n // LangChain JS compatibility properties\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema: z.ZodSchema<any>; // Zod schema for LangChain\n invoke: (args: unknown) => Promise<unknown>; // Primary method for LangChain\n lc_namespace: string[]; // Required namespace for LangChain\n returnDirect: boolean; // LangChain execution flag\n\n // Vercel AI SDK compatibility properties\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n inputSchema: z.ZodSchema<any>; // Zod schema for Vercel AI SDK\n execute: (args: unknown) => Promise<unknown>; // Primary method for Vercel AI SDK\n\n // Internal properties\n _schema: Tool;\n _serverName: string;\n _toolName: string;\n}\n\n/**\n * Builds callable JavaScript functions from MCP tool JSON schemas.\n *\n * This class generates self-contained functions that can be used with AI agent\n * frameworks. The generated functions include parameter validation and\n * comprehensive metadata based on the tool's JSON Schema definition.\n *\n * The generated functions are cached for performance, with cache invalidation\n * controlled by the owning McpdClient via clearCache().\n */\nexport class FunctionBuilder {\n #performCall: PerformCallFn;\n #functionCache: Map<string, AgentFunction> = new Map();\n\n /**\n * Initialize a FunctionBuilder with an injected function.\n *\n * @param performCall - Function to execute tool calls\n */\n constructor(performCall: PerformCallFn) {\n this.#performCall = performCall;\n }\n\n /**\n * Convert JSON schema to Zod schema.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #jsonSchemaToZod(jsonSchema: any): z.ZodSchema<any> {\n if (!jsonSchema || typeof jsonSchema !== \"object\") {\n return z.object({}); // Return empty object for undefined/null schemas\n }\n\n switch (jsonSchema.type) {\n case \"string\":\n return z.string();\n case \"number\":\n return z.number();\n case \"integer\":\n return z.number().int();\n case \"boolean\":\n return z.boolean();\n case \"array\":\n return z.array(\n jsonSchema.items ? this.#jsonSchemaToZod(jsonSchema.items) : z.any(),\n );\n case \"object\":\n // Handle object schemas that may or may not have properties\n if (jsonSchema.properties) {\n const propertyKeys = Object.keys(jsonSchema.properties);\n if (propertyKeys.length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const shape: Record<string, z.ZodSchema<any>> = {};\n const required = new Set(jsonSchema.required || []);\n\n for (const [key, value] of Object.entries(jsonSchema.properties)) {\n let schema = this.#jsonSchemaToZod(value);\n if (!required.has(key)) {\n // Use .nullable().optional() for OpenAI structured outputs compatibility\n schema = schema.nullable().optional();\n }\n shape[key] = schema;\n }\n\n return z.object(shape);\n }\n }\n // Return empty object for objects without properties or with empty properties\n return z.object({});\n default:\n // If no type is specified, check if it has properties\n if (jsonSchema.properties) {\n const propertyKeys = Object.keys(jsonSchema.properties);\n if (propertyKeys.length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const shape: Record<string, z.ZodSchema<any>> = {};\n const required = new Set(jsonSchema.required || []);\n\n for (const [key, value] of Object.entries(jsonSchema.properties)) {\n let schema = this.#jsonSchemaToZod(value);\n if (!required.has(key)) {\n // Use .nullable().optional() for OpenAI structured outputs compatibility\n schema = schema.nullable().optional();\n }\n shape[key] = schema;\n }\n\n return z.object(shape);\n }\n }\n // Default to empty object\n return z.object({});\n }\n }\n\n /**\n * Convert a string into a safe JavaScript identifier.\n *\n * This method sanitizes arbitrary strings (like server names or tool names) to create\n * valid JavaScript identifiers that can be used as function names.\n * It replaces non-word characters and handles edge cases like leading digits.\n *\n * @param name - The string to convert into a safe identifier\n * @returns A string that is a valid JavaScript identifier\n */\n private safeName(name: string): string {\n // Replace non-word characters and leading digits\n return name.replace(/\\W|^(?=\\d)/g, \"_\");\n }\n\n /**\n * Generate a unique function name from server and tool names.\n *\n * This method creates a qualified function name by combining the server name\n * and tool name with a double underscore separator. Both names are sanitized\n * using safeName() to ensure the result is a valid JavaScript identifier.\n *\n * @param serverName - The name of the MCP server hosting the tool\n * @param schemaName - The name of the tool from the schema definition\n * @returns A qualified function name in the format \"{safe_server}__{safe_tool}\"\n */\n private functionName(serverName: string, schemaName: string): string {\n return `${this.safeName(serverName)}__${this.safeName(schemaName)}`;\n }\n\n /**\n * Create a callable JavaScript function from an MCP tool's JSON Schema definition.\n *\n * This method generates a self-contained, callable function that validates parameters\n * and executes the corresponding MCP tool. The function includes proper parameter\n * validation and comprehensive metadata based on the tool's JSON Schema.\n *\n * Generated functions are cached for performance. If a function for the same\n * server/tool combination already exists in the cache, it returns the cached function.\n *\n * @param schema - The MCP tool's JSON Schema definition\n * @param serverName - The name of the MCP server hosting this tool\n * @returns A callable JavaScript function with metadata\n */\n createFunctionFromSchema(schema: Tool, serverName: string): AgentFunction {\n const cacheKey = `${serverName}__${schema.name}`;\n\n // Return cached function if it exists\n if (this.#functionCache.has(cacheKey)) {\n return this.#functionCache.get(cacheKey)!;\n }\n\n try {\n const generatedFunction = this.buildFunction(schema, serverName);\n this.#functionCache.set(cacheKey, generatedFunction);\n return generatedFunction;\n } catch (error) {\n throw new McpdError(\n `Error creating function ${cacheKey}: ${(error as Error).message}`,\n error as Error,\n );\n }\n }\n\n /**\n * Build the actual function from the schema.\n *\n * @param schema - The tool schema\n * @param serverName - The server name\n * @returns The generated function with metadata\n */\n private buildFunction(schema: Tool, serverName: string): AgentFunction {\n const inputSchema = schema.inputSchema || {};\n const properties = inputSchema.properties || {};\n const required = new Set(inputSchema.required || []);\n\n // Create the function implementation\n const implementation = async (...args: unknown[]): Promise<unknown> => {\n // Handle both positional and named arguments\n let params: Record<string, unknown> = {};\n\n if (\n args.length === 1 &&\n typeof args[0] === \"object\" &&\n args[0] !== null &&\n !Array.isArray(args[0])\n ) {\n // Single object argument (named parameters)\n params = args[0] as Record<string, unknown>;\n } else {\n // Positional arguments - map to schema properties in order\n const propertyNames = Object.keys(properties);\n for (let i = 0; i < args.length && i < propertyNames.length; i++) {\n const propertyName = propertyNames[i];\n if (propertyName) {\n params[propertyName] = args[i];\n }\n }\n }\n\n // Validate required parameters\n const missingParams: string[] = [];\n for (const paramName of required) {\n if (\n !(paramName in params) ||\n params[paramName] === null ||\n params[paramName] === undefined\n ) {\n missingParams.push(paramName);\n }\n }\n\n if (missingParams.length > 0) {\n throw new ValidationError(\n `Missing required parameters: ${missingParams.join(\", \")}`,\n missingParams,\n );\n }\n\n // Validate parameter types\n const validationErrors: string[] = [];\n for (const [paramName, paramValue] of Object.entries(params)) {\n const paramSchema = properties[paramName];\n if (paramValue !== null && paramValue !== undefined && paramSchema) {\n if (!TypeConverter.validateValue(paramValue, paramSchema)) {\n const expectedType = TypeConverter.getTypeDescription(paramSchema);\n validationErrors.push(\n `Parameter '${paramName}' should be ${expectedType}, got ${typeof paramValue}`,\n );\n }\n }\n }\n\n if (validationErrors.length > 0) {\n throw new ValidationError(\n `Parameter validation failed: ${validationErrors.join(\"; \")}`,\n validationErrors,\n );\n }\n\n // Filter out null/undefined values\n const cleanParams: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(params)) {\n if (value !== null && value !== undefined) {\n cleanParams[key] = value;\n }\n }\n\n // Make the API call\n return this.#performCall(serverName, schema.name, cleanParams);\n };\n\n // Create execution methods for both frameworks\n const invoke = async (args: unknown): Promise<unknown> => {\n return implementation(args);\n };\n\n const execute = async (args: unknown): Promise<unknown> => {\n return implementation(args);\n };\n\n // Convert JSON schema to Zod schema for both frameworks\n const zodSchema = this.#jsonSchemaToZod(inputSchema);\n\n // Add metadata to the function\n const qualifiedName = this.functionName(serverName, schema.name);\n const docstring = this.createDocstring(schema);\n\n // Cast to AgentFunction and add metadata\n const agentFunction = implementation as AgentFunction;\n\n // Use Object.defineProperty for read-only 'name' property\n Object.defineProperty(agentFunction, \"name\", {\n value: qualifiedName,\n writable: false,\n enumerable: true,\n configurable: true,\n });\n\n // Universal properties\n agentFunction.description =\n schema.description ||\n docstring.split(\"\\n\")[0] ||\n \"No description provided\";\n\n // LangChain JS compatibility properties\n agentFunction.schema = zodSchema;\n agentFunction.invoke = invoke;\n agentFunction.lc_namespace = [\"mcpd\", \"tools\"];\n agentFunction.returnDirect = false;\n\n // Vercel AI SDK compatibility properties\n agentFunction.inputSchema = zodSchema; // Use Zod schema for Vercel AI SDK compatibility\n agentFunction.execute = execute;\n\n // Internal properties\n agentFunction._schema = schema;\n agentFunction._serverName = serverName;\n agentFunction._toolName = schema.name;\n\n return agentFunction;\n }\n\n /**\n * Generate a comprehensive docstring for the dynamically created function.\n *\n * This method builds a properly formatted docstring that includes the\n * tool's description, parameter documentation with optional/required status,\n * return value information, and exception documentation.\n *\n * @param schema - The MCP tool's JSON Schema definition\n * @returns A multi-line string containing the complete docstring text\n */\n private createDocstring(schema: Tool): string {\n const description = schema.description || \"No description provided\";\n const inputSchema = schema.inputSchema || {};\n const properties = inputSchema.properties || {};\n const required = new Set(inputSchema.required || []);\n\n const docstringParts = [description];\n\n if (Object.keys(properties).length > 0) {\n docstringParts.push(\"\");\n docstringParts.push(\"Parameters:\");\n\n for (const [paramName, paramInfo] of Object.entries(properties)) {\n const isRequired = required.has(paramName);\n const paramDesc = paramInfo.description || \"No description provided\";\n const paramType = TypeConverter.getTypeDescription(paramInfo);\n const requiredText = isRequired ? \"\" : \" (optional)\";\n docstringParts.push(\n ` ${paramName} (${paramType}): ${paramDesc}${requiredText}`,\n );\n }\n }\n\n docstringParts.push(\"\");\n docstringParts.push(\"Returns:\");\n docstringParts.push(\" Promise<any>: Function execution result\");\n docstringParts.push(\"\");\n docstringParts.push(\"Throws:\");\n docstringParts.push(\n \" ValidationError: If required parameters are missing or invalid\",\n );\n docstringParts.push(\" McpdError: If the API call fails\");\n\n return docstringParts.join(\"\\n\");\n }\n\n /**\n * Clear the function cache.\n *\n * This method clears all cached generated functions, forcing them to be\n * regenerated on the next call to createFunctionFromSchema().\n */\n clearCache(): void {\n this.#functionCache.clear();\n }\n\n /**\n * Get the current cache size.\n *\n * @returns The number of functions currently cached\n */\n getCacheSize(): number {\n return this.#functionCache.size;\n }\n\n /**\n * Get all cached functions.\n *\n * @returns Array of all cached agent functions, or empty array if cache is empty\n */\n getCachedFunctions(): AgentFunction[] {\n return Array.from(this.#functionCache.values());\n }\n}\n","/**\n * Centralized API path constants for mcpd daemon endpoints.\n */\n\nconst API_BASE = \"/api/v1\";\n\nconst SERVERS_BASE = `${API_BASE}/servers`;\nconst HEALTH_SERVERS_BASE = `${API_BASE}/health/servers`;\n\nexport const API_PATHS = {\n // Server management\n SERVERS: SERVERS_BASE,\n\n // Tools\n SERVER_TOOLS: (serverName: string) =>\n `${SERVERS_BASE}/${encodeURIComponent(serverName)}/tools`,\n TOOL_CALL: (serverName: string, toolName: string) =>\n `${SERVERS_BASE}/${encodeURIComponent(serverName)}/tools/${encodeURIComponent(toolName)}`,\n\n // Prompts\n SERVER_PROMPTS: (serverName: string, cursor?: string) => {\n const base = `${SERVERS_BASE}/${encodeURIComponent(serverName)}/prompts`;\n return cursor ? `${base}?cursor=${encodeURIComponent(cursor)}` : base;\n },\n PROMPT_GET_GENERATED: (serverName: string, promptName: string) =>\n `${SERVERS_BASE}/${encodeURIComponent(serverName)}/prompts/${encodeURIComponent(promptName)}`,\n\n // Resources\n SERVER_RESOURCES: (serverName: string, cursor?: string) => {\n const base = `${SERVERS_BASE}/${encodeURIComponent(serverName)}/resources`;\n return cursor ? `${base}?cursor=${encodeURIComponent(cursor)}` : base;\n },\n SERVER_RESOURCE_TEMPLATES: (serverName: string, cursor?: string) => {\n const base = `${SERVERS_BASE}/${encodeURIComponent(serverName)}/resources/templates`;\n return cursor ? `${base}?cursor=${encodeURIComponent(cursor)}` : base;\n },\n RESOURCE_CONTENT: (serverName: string, uri: string) =>\n `${SERVERS_BASE}/${encodeURIComponent(serverName)}/resources/content?uri=${encodeURIComponent(uri)}`,\n\n // Health\n HEALTH_ALL: HEALTH_SERVERS_BASE,\n HEALTH_SERVER: (serverName: string) =>\n `${HEALTH_SERVERS_BASE}/${encodeURIComponent(serverName)}`,\n} as const;\n","/**\n * Internal logging infrastructure for the mcpd SDK.\n *\n * This module provides a logging shim controlled by the MCPD_LOG_LEVEL environment\n * variable.\n *\n * Logging is disabled by default.\n *\n * NOTE: It is recommended that you only enable MCPD_LOG_LEVEL in non-MCP-server contexts.\n * MCP servers using stdio transport for JSON-RPC communication should avoid enabling logging\n * to avoid contaminating stdout/stderr.\n */\n\n/**\n * Valid {@link LogLevel} values for MCPD_LOG_LEVEL environment variable.\n */\nexport const LogLevels = {\n TRACE: \"trace\" as const,\n DEBUG: \"debug\" as const,\n INFO: \"info\" as const,\n WARN: \"warn\" as const,\n ERROR: \"error\" as const,\n OFF: \"off\" as const,\n};\n\n/**\n * Log level type.\n */\nexport type LogLevel = (typeof LogLevels)[keyof typeof LogLevels];\n\n/**\n * Logger interface defining the SDK's logging contract.\n *\n * Each method accepts a message and optional arguments for string formatting.\n * A full Logger implementation provides all methods.\n */\nexport interface Logger {\n /**\n * Log a trace-level message (most verbose).\n *\n * @param args - Message and optional formatting arguments.\n */\n trace(...args: unknown[]): void;\n\n /**\n * Log a debug-level message.\n *\n * @param args - Message and optional formatting arguments.\n */\n debug(...args: unknown[]): void;\n\n /**\n * Log an info-level message.\n *\n * @param args - Message and optional formatting arguments.\n */\n info(...args: unknown[]): void;\n\n /**\n * Log a warning-level message.\n *\n * @param args - Message and optional formatting arguments.\n */\n warn(...args: unknown[]): void;\n\n /**\n * Log an error-level message.\n *\n * @param args - Message and optional formatting arguments.\n */\n error(...args: unknown[]): void;\n}\n\n// Numeric ranks for log levels (lower = more verbose).\nconst ranks: Record<LogLevel, number> = {\n trace: 5,\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n off: 1000,\n};\n\n// Attempts to resolve log level from a (case insensitive) environment variable value.\n// Defaults to \"off\" if unrecognized.\nfunction resolve(raw: string | undefined): LogLevel {\n const candidate = raw?.toLowerCase() as LogLevel | undefined;\n return candidate && candidate in ranks ? candidate : LogLevels.OFF;\n}\n\n// Lazily resolve the level at call time to support testing.\nfunction getLevel(): LogLevel {\n return resolve(\n typeof process !== \"undefined\" ? process.env.MCPD_LOG_LEVEL : undefined,\n );\n}\n\n// Default logger implementation using console methods.\nfunction defaultLogger(): Logger {\n return {\n trace: (...args) => {\n const lvl = getLevel();\n if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.trace)\n console.trace(...args);\n },\n debug: (...args) => {\n const lvl = getLevel();\n if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.debug)\n console.debug(...args);\n },\n info: (...args) => {\n const lvl = getLevel();\n if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.info)\n console.info(...args);\n },\n warn: (...args) => {\n const lvl = getLevel();\n if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.warn)\n console.warn(...args);\n },\n error: (...args) => {\n const lvl = getLevel();\n if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.error)\n console.error(...args);\n },\n };\n}\n\n/**\n * Create a logger, optionally using a custom implementation.\n *\n * This function allows SDK users to inject their own logger implementation.\n * Supports partial implementations - any omitted methods will fall back to the\n * default logger, which respects the MCPD_LOG_LEVEL environment variable.\n *\n * @param impl - Custom Logger implementation or partial implementation.\n * If not provided, uses default logger controlled by MCPD_LOG_LEVEL.\n * If partially provided, custom methods are used and omitted methods\n * fall back to default logger (which respects MCPD_LOG_LEVEL).\n * @returns A Logger instance with all methods implemented.\n *\n * @example\n * ```typescript\n * // Use default logger (controlled by MCPD_LOG_LEVEL).\n * const logger = createLogger();\n *\n * // Partial logger: custom warn/error, default (MCPD_LOG_LEVEL-aware) for others.\n * const logger = createLogger({\n * warn: (msg) => myCustomLogger.warning(msg),\n * error: (msg) => myCustomLogger.error(msg),\n * // trace, debug, info fall back to default logger (respects MCPD_LOG_LEVEL)\n * });\n * ```\n */\nexport function createLogger(impl?: Partial<Logger>): Logger {\n const base = defaultLogger();\n return {\n trace: impl?.trace ?? base.trace,\n debug: impl?.debug ?? base.debug,\n info: impl?.info ?? base.info,\n warn: impl?.warn ?? base.warn,\n error: impl?.error ?? base.error,\n };\n}\n","/**\n * mcpd client for MCP server management and tool execution.\n *\n * This module provides the main McpdClient class that interfaces with the mcpd\n * daemon to manage interactions with MCP servers and execute tools. It offers\n * multiple interaction patterns including direct API calls, dynamic calling\n * syntax, and agent-ready function generation.\n *\n * The client handles authentication, error management, and provides a unified\n * interface for working with multiple MCP servers through the mcpd daemon.\n */\n\nimport { LRUCache } from \"lru-cache\";\nimport {\n McpdError,\n ConnectionError,\n AuthenticationError,\n ServerNotFoundError,\n ServerUnhealthyError,\n ToolExecutionError,\n TimeoutError,\n} from \"./errors\";\nimport {\n HealthStatusHelpers,\n McpdClientOptions,\n ServerHealth,\n Tool,\n ToolsResponse,\n HealthResponse,\n ErrorModel,\n AgentToolsOptions,\n ArrayAgentToolsOptions,\n ObjectAgentToolsOptions,\n MapAgentToolsOptions,\n Prompt,\n Prompts,\n GeneratePromptResponseBody,\n PromptGenerateArguments,\n Resource,\n Resources,\n ResourceTemplate,\n ResourceTemplates,\n ResourceContent,\n} from \"./types\";\nimport { createCache } from \"./utils/cache\";\nimport { ServersNamespace } from \"./dynamicCaller\";\nimport { FunctionBuilder, type AgentFunction } from \"./functionBuilder\";\nimport { API_PATHS } from \"./apiPaths\";\nimport { createLogger, type Logger } from \"./logger\";\n\n/**\n * Default timeout for API requests to mcpd, in seconds.\n */\nconst REQUEST_TIMEOUT_SECONDS = 30;\n\n/**\n * Default TTL for server health cache entries, in seconds.\n *\n * @remarks\n * Used to avoid excessive health check requests while keeping data reasonably fresh.\n */\nconst SERVER_HEALTH_CACHE_TTL_SECONDS = 10;\n\n/**\n * Maximum number of server health entries to cache.\n * Prevents unbounded memory growth while allowing legitimate large-scale monitoring.\n */\nconst SERVER_HEALTH_CACHE_MAXSIZE = 100;\n\n/**\n * Separator used between server name and tool name in qualified tool names.\n * Format: `{serverName}{TOOL_SEPARATOR}{toolName}`\n * Example: \"time__get_current_time\" where \"time\" is server and \"get_current_time\" is tool.\n */\nconst TOOL_SEPARATOR = \"__\";\n\n/**\n * Type alias for agent functions in array format.\n * @internal\n */\ntype AgentFunctionsArray = AgentFunction[];\n\n/**\n * Type alias for agent functions in object format (keyed by function name).\n * @internal\n */\ntype AgentFunctionsRecord = Record<string, AgentFunction>;\n\n/**\n * Type alias for agent functions in Map format (keyed by function name).\n * @internal\n */\ntype AgentFunctionsMap = Map<string, AgentFunction>;\n\n/**\n * Client for interacting with MCP (Model Context Protocol) servers through an mcpd daemon.\n *\n * The McpdClient provides a high-level interface to discover, inspect, and invoke tools\n * exposed by MCP servers running behind an mcpd daemon proxy/gateway.\n *\n * Thread Safety:\n * This client is safe to use from multiple async contexts. The internal health\n * check cache is protected by the LRUCache implementation.\n *\n * @example\n * ```typescript\n * import { McpdClient } from '@mozilla-ai/mcpd';\n *\n * // Initialize client\n * const client = new McpdClient({\n * apiEndpoint: 'http://localhost:8090',\n * apiKey: 'optional-key',\n * healthCacheTtl: 10,\n * });\n *\n * // List available servers\n * const servers = await client.listServers();\n * console.log(servers); // ['time', 'fetch', 'git']\n *\n * // Invoke a tool dynamically\n * const result = await client.servers.time.get_current_time({ timezone: 'UTC' });\n * console.log(result); // { time: '2024-01-15T10:30:00Z' }\n * ```\n */\nexport class McpdClient {\n readonly #endpoint: string;\n readonly #apiKey: string | undefined;\n readonly #timeout: number;\n readonly #serverHealthCache: LRUCache<string, ServerHealth | Error>;\n readonly #functionBuilder: FunctionBuilder;\n readonly #logger: Logger;\n readonly #cacheableExceptions = new Set([\n ServerNotFoundError,\n ServerUnhealthyError,\n AuthenticationError,\n ]);\n\n /**\n * Namespace for accessing MCP servers and their tools.\n */\n public readonly servers: ServersNamespace;\n\n /**\n * Initialize a new McpdClient instance.\n *\n * @param options - Configuration options for the client\n */\n constructor(options: McpdClientOptions) {\n // Helper for time conversion.\n const toMs = (s: number) => s * 1000; // seconds to milliseconds\n\n // Remove trailing slash from endpoint.\n this.#endpoint = options.apiEndpoint.replace(/\\/$/, \"\");\n this.#apiKey = options.apiKey;\n this.#timeout = options.timeout ?? toMs(REQUEST_TIMEOUT_SECONDS);\n\n // Setup health cache.\n const healthCacheTtlMs = toMs(\n options.healthCacheTtl ?? SERVER_HEALTH_CACHE_TTL_SECONDS,\n );\n this.#serverHealthCache = createCache({\n max: SERVER_HEALTH_CACHE_MAXSIZE,\n ttl: healthCacheTtlMs,\n });\n\n // Setup logger (the default logger uses MCPD_LOG_LEVEL).\n this.#logger = createLogger(options.logger);\n\n // Initialize servers namespace and function builder with injected functions.\n this.servers = new ServersNamespace({\n performCall: this.#performCall.bind(this),\n getTools: this.#getToolsByServer.bind(this),\n generatePrompt: this.#generatePromptInternal.bind(this),\n getPrompts: this.#getPromptsByServer.bind(this),\n getResources: this.#getResourcesByServer.bind(this),\n getResourceTemplates: this.#getResourceTemplatesByServer.bind(this),\n readResource: this.#readResourceByServer.bind(this),\n });\n this.#functionBuilder = new FunctionBuilder(this.#performCall.bind(this));\n }\n\n /**\n * Make an HTTP request to the mcpd daemon.\n *\n * @param path - The API path (e.g., '/servers', '/servers/{server_name}/tools')\n * @param options - Request options\n *\n * @returns The JSON response from the daemon\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #request<T = unknown>(\n path: string,\n options: RequestInit = {},\n ): Promise<T> {\n const url = `${this.#endpoint}${path}`;\n\n // Setup request headers\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...((options.headers as Record<string, string>) || {}),\n };\n\n // Add authentication if configured\n if (this.#apiKey) {\n headers[\"Authorization\"] = `Bearer ${this.#apiKey}`;\n }\n\n // Setup timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.#timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Handle non-2xx responses with ErrorModel parsing\n if (!response.ok) {\n const body = await response.text();\n let errorModel: ErrorModel | null = null;\n\n try {\n errorModel = JSON.parse(body) as ErrorModel;\n } catch {\n // Response body is not valid JSON - fall through to fallback error handling below.\n errorModel = null;\n }\n\n if (errorModel && errorModel.detail) {\n const errorDetails = errorModel.errors\n ?.map((e) => `${e.location}: ${e.message}`)\n .join(\"; \");\n const fullMessage = errorDetails\n ? `${errorModel.detail} - ${errorDetails}`\n : errorModel.detail;\n\n // Handle authentication errors\n if (response.status === 401 || response.status === 403) {\n throw new AuthenticationError(fullMessage);\n }\n\n // Handle other errors with proper message\n throw new McpdError(\n `${errorModel.title || \"Request failed\"}: ${fullMessage}`,\n );\n }\n\n // Fallback if ErrorModel parsing failed\n if (response.status === 401 || response.status === 403) {\n throw new AuthenticationError(\n `Authentication failed: ${response.status} ${response.statusText}`,\n );\n }\n\n throw new McpdError(\n `Request failed: ${response.status} ${response.statusText} - ${body}`,\n );\n }\n\n // Parse JSON response\n try {\n return (await response.json()) as T;\n } catch (error) {\n throw new McpdError(\"Failed to parse JSON response\", error as Error);\n }\n } catch (error) {\n clearTimeout(timeoutId);\n\n // Handle timeout\n if ((error as Error).name === \"AbortError\") {\n throw new TimeoutError(\n `Request timed out after ${this.#timeout}ms`,\n path,\n this.#timeout,\n );\n }\n\n // Handle connection errors\n if (error instanceof TypeError && error.message.includes(\"fetch\")) {\n throw new ConnectionError(\n `Cannot connect to mcpd daemon at ${this.#endpoint}. Is it running?`,\n error,\n );\n }\n\n // Re-throw our errors as-is\n if (error instanceof McpdError) {\n throw error;\n }\n\n // Wrap unknown errors\n throw new McpdError(\n `Request failed: ${(error as Error).message}`,\n error as Error,\n );\n }\n }\n\n /**\n * Get a list of all configured MCP servers.\n *\n * @returns Array of server names\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @example\n * ```typescript\n * const servers = await client.listServers();\n * console.log(servers); // ['time', 'fetch', 'git']\n * ```\n */\n async listServers(): Promise<string[]> {\n return await this.#request<string[]>(API_PATHS.SERVERS);\n }\n\n /**\n * Get tool schemas for a server.\n *\n * @privateRemarks\n * Used by dependency injection for ServersNamespace and internally for getAgentTools.\n *\n * @param serverName - Server name to get tools for\n *\n * @returns Tool schemas for the specified server\n *\n * @throws {ServerNotFoundError} If the specified server doesn't exist\n * @throws {ServerUnhealthyError} If the server is not healthy\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #getToolsByServer(serverName: string): Promise<Tool[]> {\n // Check server health first\n await this.#ensureServerHealthy(serverName);\n\n const path = API_PATHS.SERVER_TOOLS(serverName);\n const response = await this.#request<ToolsResponse>(path);\n\n if (!response.tools) {\n throw new ServerNotFoundError(\n `Server '${serverName}' not found`,\n serverName,\n );\n }\n\n return response.tools;\n }\n\n /**\n * Get prompt schemas for a server.\n *\n * @privateRemarks\n * Used internally for getPromptSchemas.\n *\n * @param serverName - Server name to get prompts for\n * @param cursor - Cursor for pagination\n *\n * @returns Prompt schemas for the specified server\n *\n * @throws {ServerNotFoundError} If the specified server doesn't exist\n * @throws {ServerUnhealthyError} If the server is not healthy\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #getPromptsByServer(\n serverName: string,\n cursor?: string,\n ): Promise<Prompt[]> {\n try {\n // Check server health first.\n await this.#ensureServerHealthy(serverName);\n\n const path = API_PATHS.SERVER_PROMPTS(serverName, cursor);\n const response = await this.#request<Prompts>(path);\n return response.prompts || [];\n } catch (error) {\n // Handle 501 Not Implemented - server doesn't support prompts.\n if (\n error instanceof McpdError &&\n error.message.includes(\"501\") &&\n error.message.includes(\"Not Implemented\")\n ) {\n return [];\n }\n\n throw error;\n }\n }\n\n /**\n * Generate a prompt on a server.\n *\n * @privateRemarks\n * Used internally by:\n * - PromptsNamespace (via dependency injection)\n * - Server.generatePrompt() (via dependency injection)\n *\n * @param serverName - The name of the server\n * @param promptName - The exact name of the prompt\n * @param args - The prompt arguments\n *\n * @returns The generated prompt response\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #generatePromptInternal(\n serverName: string,\n promptName: string,\n args?: Record<string, string>,\n ): Promise<GeneratePromptResponseBody> {\n // Check server health first.\n await this.#ensureServerHealthy(serverName);\n\n const path = API_PATHS.PROMPT_GET_GENERATED(serverName, promptName);\n const requestBody: PromptGenerateArguments = {\n arguments: args || {},\n };\n\n const response = await this.#request<GeneratePromptResponseBody>(path, {\n method: \"POST\",\n body: JSON.stringify(requestBody),\n });\n\n return response;\n }\n\n /**\n * Get resource schemas for a server.\n *\n * @privateRemarks\n * Used internally for getResources and by dependency injection for ServersNamespace.\n *\n * @param serverName - Server name to get resources for\n * @param cursor - Cursor for pagination\n *\n * @returns Resource schemas for the specified server\n *\n * @throws {ServerNotFoundError} If the specified server doesn't exist\n * @throws {ServerUnhealthyError} If the server is not healthy\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #getResourcesByServer(\n serverName: string,\n cursor?: string,\n ): Promise<Resource[]> {\n try {\n // Check server health first.\n await this.#ensureServerHealthy(serverName);\n\n const path = API_PATHS.SERVER_RESOURCES(serverName, cursor);\n const response = await this.#request<Resources>(path);\n return response.resources || [];\n } catch (error) {\n // Handle 501 Not Implemented - server doesn't support resources.\n if (\n error instanceof McpdError &&\n error.message.includes(\"501\") &&\n error.message.includes(\"Not Implemented\")\n ) {\n return [];\n }\n\n throw error;\n }\n }\n\n /**\n * Get resource template schemas for a server.\n *\n * @privateRemarks\n * Used internally for getResourceTemplates and by dependency injection for ServersNamespace.\n *\n * @param serverName - Server name to get resource templates for\n * @param cursor - Cursor for pagination\n *\n * @returns Resource template schemas for the specified server\n *\n * @throws {ServerNotFoundError} If the specified server doesn't exist\n * @throws {ServerUnhealthyError} If the server is not healthy\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #getResourceTemplatesByServer(\n serverName: string,\n cursor?: string,\n ): Promise<ResourceTemplate[]> {\n try {\n // Check server health first.\n await this.#ensureServerHealthy(serverName);\n\n const path = API_PATHS.SERVER_RESOURCE_TEMPLATES(serverName, cursor);\n const response = await this.#request<ResourceTemplates>(path);\n return response.templates || [];\n } catch (error) {\n // Handle 501 Not Implemented - server doesn't support resource templates.\n if (\n error instanceof McpdError &&\n error.message.includes(\"501\") &&\n error.message.includes(\"Not Implemented\")\n ) {\n return [];\n }\n\n throw error;\n }\n }\n\n /**\n * Read resource content from a server.\n *\n * @privateRemarks\n * Used by dependency injection for ServersNamespace.\n *\n * @param serverName - Server name to read resource from\n * @param uri - The resource URI\n *\n * @returns Array of resource contents (text or blob)\n *\n * @throws {ServerNotFoundError} If the specified server doesn't exist\n * @throws {ServerUnhealthyError} If the server is not healthy\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #readResourceByServer(\n serverName: string,\n uri: string,\n ): Promise<ResourceContent[]> {\n // Check server health first.\n await this.#ensureServerHealthy(serverName);\n\n const path = API_PATHS.RESOURCE_CONTENT(serverName, uri);\n const response = await this.#request<ResourceContent[]>(path);\n return response || [];\n }\n\n /**\n * Get health information for one or all servers.\n *\n * @param serverName - Server name to get health for, or undefined for all servers\n *\n * @returns Health information for the specified server or all servers\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @example\n * ```typescript\n * // Get health for all servers\n * const allHealth = await client.getServerHealth();\n * console.log(allHealth); // { time: { status: 'ok' }, fetch: { status: 'ok' } }\n *\n * // Get health for a specific server\n * const timeHealth = await client.getServerHealth('time');\n * console.log(timeHealth); // { status: 'ok' }\n * ```\n */\n async getServerHealth(): Promise<Record<string, ServerHealth>>;\n async getServerHealth(serverName: string): Promise<ServerHealth>;\n async getServerHealth(\n serverName?: string,\n ): Promise<ServerHealth | Record<string, ServerHealth>> {\n if (serverName) {\n // Check cache first\n const cacheKey = `health:${serverName}`;\n const cached = this.#serverHealthCache.get(cacheKey);\n\n if (cached !== undefined) {\n if (cached instanceof Error) {\n throw cached;\n }\n return cached;\n }\n\n try {\n const path = API_PATHS.HEALTH_SERVER(serverName);\n const health = await this.#request<ServerHealth>(path);\n\n // Cache successful result\n this.#serverHealthCache.set(cacheKey, health);\n\n return health;\n } catch (error) {\n // Cache certain error types\n if (error instanceof Error) {\n for (const errorType of this.#cacheableExceptions) {\n if (error instanceof errorType) {\n this.#serverHealthCache.set(cacheKey, error);\n break;\n }\n }\n }\n throw error;\n }\n } else {\n const response = await this.#request<HealthResponse>(\n API_PATHS.HEALTH_ALL,\n );\n // Transform array response into Record<string, ServerHealth>\n const healthMap: Record<string, ServerHealth> = {};\n for (const server of response.servers) {\n healthMap[server.name] = server;\n // Cache individual server health for subsequent calls\n const cacheKey = `health:${server.name}`;\n this.#serverHealthCache.set(cacheKey, server);\n }\n return healthMap;\n }\n }\n\n /**\n * Check if a specific server is healthy.\n *\n * @param serverName - The name of the server to check\n *\n * @returns True if the server is healthy, false otherwise\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @example\n * ```typescript\n * if (await client.isServerHealthy('time')) {\n * const time = await client.servers.time.get_current_time();\n * }\n * ```\n */\n async isServerHealthy(serverName: string): Promise<boolean> {\n try {\n const health = await this.getServerHealth(serverName);\n return HealthStatusHelpers.isHealthy(health.status);\n } catch (error) {\n if (error instanceof ServerNotFoundError) {\n return false;\n }\n throw error;\n }\n }\n\n /**\n * Ensure a server is healthy before performing an operation.\n *\n * @param serverName - The name of the server to check\n *\n * @throws {ServerNotFoundError} If the server doesn't exist\n * @throws {ServerUnhealthyError} If the server is not healthy\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n */\n async #ensureServerHealthy(serverName: string): Promise<void> {\n const health = await this.getServerHealth(serverName);\n\n if (!health) {\n throw new ServerNotFoundError(\n `Server '${serverName}' not found`,\n serverName,\n );\n }\n\n if (!HealthStatusHelpers.isHealthy(health.status)) {\n throw new ServerUnhealthyError(\n `Server '${serverName}' is not healthy: ${health.status}`,\n serverName,\n health.status,\n );\n }\n }\n\n /**\n * Get list of healthy servers.\n *\n * @remarks\n * If logging is enabled, warnings are logged for servers that do not exist or are unhealthy.\n *\n * @param servers - List of server names to use for health checking.\n * If not provided, or empty, checks health for all servers.\n *\n * @returns List of server names with 'ok' health status.\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n */\n async #getHealthyServers(servers?: string[]): Promise<string[]> {\n const serverNames = servers?.length ? servers : await this.listServers();\n const healthMap = await this.getServerHealth();\n\n return serverNames.filter((name) => {\n const health = healthMap[name];\n\n if (!health) {\n this.#logger.warn(`Skipping non-existent server '${name}'`);\n return false;\n }\n\n if (!HealthStatusHelpers.isHealthy(health.status)) {\n this.#logger.warn(\n `Skipping unhealthy server '${name}' with status '${health.status}'`,\n );\n return false;\n }\n\n return true;\n });\n }\n\n /**\n * Perform a tool call on a server.\n *\n * @privateRemarks\n * Used internally by:\n * - ToolsNamespace (via dependency injection)\n * - FunctionBuilder (via dependency injection)\n *\n * @param serverName - The name of the server\n * @param toolName - The exact name of the tool\n * @param args - The tool arguments\n *\n * @returns The tool's response\n *\n * @throws {ToolExecutionError} If the tool execution fails\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #performCall(\n serverName: string,\n toolName: string,\n args?: Record<string, unknown>,\n ): Promise<unknown> {\n const path = API_PATHS.TOOL_CALL(serverName, toolName);\n\n try {\n const response = await this.#request<unknown>(path, {\n method: \"POST\",\n body: JSON.stringify(args || {}),\n });\n\n // The mcpd API returns tool results as JSON strings that need parsing\n if (typeof response === \"string\") {\n try {\n return JSON.parse(response);\n } catch {\n // If not valid JSON, return string as-is\n return response;\n }\n }\n\n // Return the response as-is (already parsed or not a string)\n return response;\n } catch (error) {\n if (error instanceof McpdError) {\n throw error;\n }\n\n throw new ToolExecutionError(\n `Failed to execute tool '${toolName}' on server '${serverName}': ${(error as Error).message}`,\n serverName,\n toolName,\n undefined,\n error as Error,\n );\n }\n }\n\n /**\n * Clear the cached agent tools functions.\n * This should be called when the tool schemas might have changed.\n */\n clearAgentToolsCache(): void {\n this.#functionBuilder.clearCache();\n }\n\n /**\n * Clear the server health cache.\n * This forces fresh health checks on the next getServerHealth() or isServerHealthy() call.\n */\n clearServerHealthCache(): void {\n this.#serverHealthCache.clear();\n }\n\n /**\n * Fetch and cache callable functions from all healthy servers.\n *\n * This method queries all healthy servers and creates self-contained, callable functions\n * that can be passed to AI agent frameworks. Each function includes its schema\n * as metadata and handles the MCP communication internally.\n *\n * Unhealthy servers are automatically filtered out and skipped (with optional warnings\n * when logging is enabled) to ensure the method returns quickly without waiting for timeouts.\n *\n * Tool fetches from multiple servers are executed concurrently for optimal performance.\n * Functions are cached indefinitely until explicitly cleared.\n *\n * @returns Array of callable functions with metadata from all healthy servers.\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #agentTools(): Promise<AgentFunction[]> {\n // Return cached functions if available.\n const cachedFunctions = this.#functionBuilder.getCachedFunctions();\n if (cachedFunctions.length > 0) {\n return cachedFunctions;\n }\n\n // Get all healthy servers.\n const healthyServers = await this.#getHealthyServers();\n\n // Fetch tools from all healthy servers in parallel.\n const results = await Promise.allSettled(\n healthyServers.map(async (serverName) => ({\n serverName,\n tools: await this.#getToolsByServer(serverName),\n })),\n );\n\n // Build functions from tool schemas.\n const agentTools: AgentFunction[] = results\n .filter((result) => result.status === \"fulfilled\")\n .flatMap((result) => {\n const { serverName, tools } = result.value;\n return tools.map((toolSchema) =>\n this.#functionBuilder.createFunctionFromSchema(\n toolSchema,\n serverName,\n ),\n );\n });\n\n return agentTools;\n }\n\n /**\n * Generate callable functions for use with AI agent frameworks.\n *\n * This method queries servers to create and cache self-contained, callable functions\n * that can be passed to AI agent frameworks. Each function includes its schema\n * as metadata and handles the MCP communication internally.\n *\n * @remarks\n * This method automatically filters out unhealthy servers by checking their health status before fetching tools.\n * Unhealthy servers are skipped (with optional warnings when logging is enabled) to ensure the\n * method returns quickly without waiting for timeouts on failed servers.\n *\n * Tool fetches from multiple servers are executed concurrently for optimal performance.\n *\n * Generated functions are cached for performance. Once cached, subsequent calls return\n * the cached functions immediately without refetching schemas, regardless of filter parameters.\n * Use {@link clearAgentToolsCache()} to clear the cache, or set refreshCache to true\n * to force regeneration when tool schemas have changed.\n *\n * @param options - Options for output format, server/tool filtering, and cache control\n *\n * @returns Functions in the requested format (array, object, or map).\n * Only includes tools from healthy servers.\n *\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If requests to the daemon time out\n * @throws {AuthenticationError} If API key authentication fails\n * @throws {McpdError} If unable to retrieve health status, server list, or generate functions\n *\n * @example\n * ```typescript\n * // Get all tools from all servers (default array format)\n * const tools = await client.getAgentTools();\n * console.log(`Generated ${tools.length} callable tools`);\n *\n * // Get tools from specific servers\n * const tools = await client.getAgentTools({ servers: ['time', 'fetch'] });\n *\n * // Force refresh from cache\n * const freshTools = await client.getAgentTools({ refreshCache: true });\n *\n * // Use with LangChain JS (array format)\n * const langchainTools = await client.getAgentTools({ format: 'array' });\n * const agent = await createOpenAIToolsAgent({ llm, tools: langchainTools, prompt });\n *\n * // Use with Vercel AI SDK (object format) from specific servers\n * const vercelTools = await client.getAgentTools({\n * servers: ['time'],\n * format: 'object'\n * });\n * const result = await generateText({ model, tools: vercelTools, prompt });\n * ```\n */\n async getAgentTools(\n options?: ArrayAgentToolsOptions,\n ): Promise<AgentFunction[]>;\n async getAgentTools(\n options: ObjectAgentToolsOptions,\n ): Promise<Record<string, AgentFunction>>;\n async getAgentTools(\n options: MapAgentToolsOptions,\n ): Promise<Map<string, AgentFunction>>;\n async getAgentTools(\n options: AgentToolsOptions = {},\n ): Promise<\n AgentFunction[] | Record<string, AgentFunction> | Map<string, AgentFunction>\n > {\n const { servers, tools, format = \"array\", refreshCache = false } = options;\n\n // Clear cache and fetch fresh if requested.\n if (refreshCache) this.#functionBuilder.clearCache();\n\n // Fetch or retrieve cached functions from all healthy servers.\n const allTools = await this.#agentTools();\n\n // Filter results based on servers and tools parameters.\n const filteredTools = allTools\n .filter((tool) => !servers || servers.includes(tool._serverName))\n .filter((tool) => !tools || this.#matchesToolFilter(tool, tools));\n\n // Format output as requested.\n const formatters: {\n array: (t: AgentFunctionsArray) => AgentFunctionsArray;\n object: (t: AgentFunctionsArray) => AgentFunctionsRecord;\n map: (t: AgentFunctionsArray) => AgentFunctionsMap;\n } = {\n array: (t) => t,\n object: (t) => Object.fromEntries(t.map((tool) => [tool.name, tool])),\n map: (t) => new Map(t.map((tool) => [tool.name, tool])),\n };\n\n return formatters[format](filteredTools);\n }\n\n /**\n * Check if a tool matches the tool filter.\n *\n * Supports two formats:\n * - Raw tool name: \"get_current_time\" (matches across all servers)\n * - Server-prefixed: \"time__get_current_time\" (matches specific server + tool)\n *\n * @remarks\n * When a filter contains \"__\", it's first checked as server-prefixed (exact match).\n * If that fails, it's checked as a raw tool name. This handles tools whose names\n * contain \"__\" (e.g., \"my__special__tool\").\n *\n * @param tool The tool to match.\n * @param tools List of tool names to match against.\n *\n * @returns True if a match is found in tools, based on the predicate.\n *\n * @internal\n */\n #matchesToolFilter(tool: AgentFunction, tools: string[]): boolean {\n return tools.some((filterItem) => {\n if (filterItem.indexOf(TOOL_SEPARATOR) === -1) {\n // Match against raw tool name\n return filterItem === tool._toolName;\n }\n\n // Try prefixed match first, then fall back to raw match\n return filterItem === tool.name || filterItem === tool._toolName;\n });\n }\n}\n"],"names":["HealthStatus"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/errors.ts","../src/types.ts","../src/utils/cache.ts","../src/dynamicCaller.ts","../src/utils/typeConverter.ts","../src/functionBuilder.ts","../src/apiPaths.ts","../src/logger.ts","../src/client.ts"],"sourcesContent":["/**\n * Exception hierarchy for the mcpd SDK.\n *\n * This module provides a structured exception hierarchy to help users handle\n * different error scenarios appropriately.\n */\n\nimport type { ErrorModel } from \"./types\";\n\n/**\n * Pipeline flow constant for request processing failures.\n */\nexport const PIPELINE_FLOW_REQUEST = \"request\" as const;\n\n/**\n * Pipeline flow constant for response processing failures.\n */\nexport const PIPELINE_FLOW_RESPONSE = \"response\" as const;\n\n/**\n * Pipeline flow indicating where in the pipeline the failure occurred.\n */\nexport type PipelineFlow =\n | typeof PIPELINE_FLOW_REQUEST\n | typeof PIPELINE_FLOW_RESPONSE;\n\n/**\n * Base exception for all mcpd SDK errors.\n *\n * This exception wraps all errors that occur during interaction with the mcpd daemon,\n * including network failures, authentication errors, server errors, and tool execution\n * failures. The original exception is preserved via the cause property for debugging.\n */\nexport class McpdError extends Error {\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = \"McpdError\";\n this.cause = cause;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when unable to connect to the mcpd daemon.\n *\n * This typically indicates that:\n * - The mcpd daemon is not running\n * - The endpoint URL is incorrect\n * - Network connectivity issues\n * - Firewall blocking the connection\n */\nexport class ConnectionError extends McpdError {\n constructor(message: string, cause?: Error) {\n super(message, cause);\n this.name = \"ConnectionError\";\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when authentication with the mcpd daemon fails.\n *\n * This indicates that:\n * - The API key is invalid or expired\n * - The API key is missing but required\n * - The authentication method is not supported\n */\nexport class AuthenticationError extends McpdError {\n constructor(message: string, cause?: Error) {\n super(message, cause);\n this.name = \"AuthenticationError\";\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when a specified MCP server doesn't exist.\n *\n * This error occurs when trying to access a server that:\n * - Is not configured in the mcpd daemon\n * - Has been removed or renamed\n * - Is temporarily unavailable\n */\nexport class ServerNotFoundError extends McpdError {\n public readonly serverName: string | undefined;\n\n constructor(message: string, serverName?: string, cause?: Error) {\n super(message, cause);\n this.name = \"ServerNotFoundError\";\n this.serverName = serverName;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when a specified MCP server is not healthy.\n *\n * This indicates that the server exists but is currently unhealthy:\n * - The server is down or unreachable\n * - Timeout occurred while checking health\n * - No health data is available for the server\n */\nexport class ServerUnhealthyError extends McpdError {\n public readonly serverName: string;\n public readonly healthStatus: string;\n\n constructor(\n message: string,\n serverName: string,\n healthStatus: string,\n cause?: Error,\n ) {\n super(message, cause);\n this.name = \"ServerUnhealthyError\";\n this.serverName = serverName;\n this.healthStatus = healthStatus;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when a specified tool doesn't exist on a server.\n *\n * This error occurs when trying to call a tool that:\n * - Doesn't exist on the specified server\n * - Has been removed or renamed\n * - Is temporarily unavailable\n */\nexport class ToolNotFoundError extends McpdError {\n public readonly serverName: string | undefined;\n public readonly toolName: string | undefined;\n\n constructor(\n message: string,\n serverName?: string,\n toolName?: string,\n cause?: Error,\n ) {\n super(message, cause);\n this.name = \"ToolNotFoundError\";\n this.serverName = serverName;\n this.toolName = toolName;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when a tool execution fails on the server side.\n *\n * This indicates that the tool was found and called, but failed during execution:\n * - Invalid parameters provided\n * - Server-side error during tool execution\n * - Tool returned an error response\n * - Timeout during tool execution\n */\nexport class ToolExecutionError extends McpdError {\n public readonly serverName: string | undefined;\n public readonly toolName: string | undefined;\n public readonly errorModel: ErrorModel | undefined;\n\n constructor(\n message: string,\n serverName?: string,\n toolName?: string,\n errorModel?: ErrorModel,\n cause?: Error,\n ) {\n super(message, cause);\n this.name = \"ToolExecutionError\";\n this.serverName = serverName;\n this.toolName = toolName;\n this.errorModel = errorModel;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when input validation fails.\n *\n * This occurs when:\n * - Required parameters are missing\n * - Parameter types don't match the schema\n * - Parameter values don't meet constraints\n */\nexport class ValidationError extends McpdError {\n public readonly validationErrors: string[];\n\n constructor(message: string, validationErrors?: string[], cause?: Error) {\n super(message, cause);\n this.name = \"ValidationError\";\n this.validationErrors = validationErrors || [];\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when an operation times out.\n *\n * This can occur during:\n * - Long-running tool executions\n * - Slow network connections\n * - Unresponsive mcpd daemon\n */\nexport class TimeoutError extends McpdError {\n public readonly operation: string | undefined;\n public readonly timeout: number | undefined;\n\n constructor(\n message: string,\n operation?: string,\n timeout?: number,\n cause?: Error,\n ) {\n super(message, cause);\n this.name = \"TimeoutError\";\n this.operation = operation;\n this.timeout = timeout;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Raised when required pipeline processing fails.\n *\n * This indicates that required processing failed in the mcpd pipeline.\n * The error occurs when a required plugin (such as authentication, validation,\n * audit logging, monitoring, or response transformation) fails during request\n * or response processing.\n *\n * Pipeline Flow Distinction:\n * - **response-pipeline-failure**: The upstream request was processed (the tool\n * was called), but results cannot be returned due to a required response\n * processing step failure. Note: This does not indicate whether the tool\n * itself succeeded or failed - only that the response cannot be delivered.\n *\n * - **request-pipeline-failure**: The request was rejected before reaching the\n * upstream server due to a required request processing step failure (such as\n * authentication, authorization, validation, or rate limiting plugin failure).\n *\n * This typically indicates a problem with a plugin or an external system\n * that a plugin depends on (e.g., audit service, authentication provider).\n * Retrying is unlikely to help as this usually indicates a configuration\n * or dependency problem rather than a transient failure.\n *\n * @example\n * ```typescript\n * import { McpdClient, PipelineError } from '@mozilla-ai/mcpd';\n *\n * const client = new McpdClient({ apiEndpoint: 'http://localhost:8090' });\n *\n * try {\n * const result = await client.servers.time.tools.get_current_time();\n * } catch (error) {\n * if (error instanceof PipelineError) {\n * console.log(`Pipeline failure: ${error.message}`);\n * console.log(`Flow: ${error.pipelineFlow}`);\n *\n * if (error.pipelineFlow === 'response') {\n * console.log('Tool was called but results cannot be delivered');\n * } else {\n * console.log('Request was rejected by pipeline');\n * console.log('Check authentication, authorization, or rate limiting');\n * }\n * }\n * }\n * ```\n *\n * @remarks\n * This exception indicates a problem with a plugin or its dependencies, not\n * with your request or the tool itself.\n */\nexport class PipelineError extends McpdError {\n public readonly serverName: string | undefined;\n public readonly operation: string | undefined;\n public readonly pipelineFlow: PipelineFlow | undefined;\n\n constructor(\n message: string,\n serverName?: string,\n operation?: string,\n pipelineFlow?: PipelineFlow,\n cause?: Error,\n ) {\n super(message, cause);\n this.name = \"PipelineError\";\n this.serverName = serverName;\n this.operation = operation;\n this.pipelineFlow = pipelineFlow;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n","/**\n * Type definitions for the mcpd SDK.\n */\n\nimport type { Logger } from \"./logger\";\n\n/**\n * Enumeration of possible MCP server health statuses.\n */\nexport enum HealthStatus {\n OK = \"ok\",\n TIMEOUT = \"timeout\",\n UNREACHABLE = \"unreachable\",\n UNKNOWN = \"unknown\",\n}\n\n/**\n * Helper functions for HealthStatus.\n */\nexport const HealthStatusHelpers = {\n /**\n * Check if the given health status is a transient error state.\n */\n isTransient(status: string): boolean {\n return status === HealthStatus.TIMEOUT || status === HealthStatus.UNKNOWN;\n },\n\n /**\n * Check if the given status string represents a healthy state.\n */\n isHealthy(status: string): boolean {\n return status === HealthStatus.OK;\n },\n};\n\n/**\n * Error detail from Huma API error responses.\n * Location and value are optional as the API doesn't always include them.\n */\nexport interface ErrorDetail {\n location?: string;\n message: string;\n value?: unknown;\n}\n\n/**\n * Huma API error model (RFC 7807 Problem Details).\n * Used for all API errors including HTTP errors and tool execution failures.\n */\nexport interface ErrorModel {\n $schema?: string;\n detail: string;\n errors?: ErrorDetail[];\n instance?: string;\n status: number;\n title: string;\n type: string;\n}\n\n/**\n * JSON Schema definition for tool parameters.\n */\nexport interface JsonSchema {\n type?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n properties?: Record<string, any>;\n required?: string[];\n additionalProperties?: boolean;\n items?: JsonSchema;\n description?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n}\n\n/**\n * Tool annotations for hints about tool behavior.\n */\nexport interface ToolAnnotations {\n title?: string;\n destructiveHint?: boolean;\n idempotentHint?: boolean;\n openWorldHint?: boolean;\n readOnlyHint?: boolean;\n}\n\n/**\n * MCP tool definition following the Model Context Protocol specification (2025-06-18).\n *\n * @see https://spec.modelcontextprotocol.io/specification/2025-06-18/server/tools/\n */\nexport interface Tool {\n /**\n * Unique identifier for the tool (required).\n */\n name: string;\n\n /**\n * Optional human-readable title for display.\n */\n title?: string;\n\n /**\n * Human-readable description of what the tool does (optional in MCP spec).\n *\n * Note: mcpd API currently requires this field, but MCP spec makes it optional.\n * This SDK follows the MCP spec to remain protocol-compliant.\n */\n description?: string;\n\n /**\n * JSON Schema defining the tool's input parameters (required in MCP spec).\n *\n * Note: mcpd API currently makes this optional, but MCP spec requires it.\n * This SDK follows the MCP spec to remain protocol-compliant.\n */\n inputSchema: JsonSchema;\n\n /**\n * Optional JSON Schema defining the tool's output structure.\n */\n outputSchema?: JsonSchema;\n\n /**\n * Optional hints about tool behavior (readonly, destructive, idempotent, etc.).\n */\n annotations?: ToolAnnotations;\n\n /**\n * Optional metadata for extensibility.\n */\n _meta?: Record<string, unknown>;\n}\n\n/**\n * Tools list response from the mcpd API.\n */\nexport interface Tools {\n $schema?: string;\n tools: Tool[];\n}\n\n/**\n * Server health information from the mcpd API.\n * Represents the health status of an MCP server.\n */\nexport interface ServerHealth {\n /**\n * Name of the server (required).\n */\n name: string;\n\n /**\n * Health status of the server (required).\n * Common values: 'ok', 'timeout', 'unreachable', 'unknown'\n */\n status: string;\n\n /**\n * Optional JSON Schema reference.\n */\n $schema?: string;\n\n /**\n * Timestamp of the last health check (ISO 8601 date-time).\n */\n lastChecked?: string;\n\n /**\n * Timestamp of the last successful health check (ISO 8601 date-time).\n */\n lastSuccessful?: string;\n\n /**\n * Latency of the health check (e.g., '2ms', '1.5s').\n */\n latency?: string;\n}\n\n/**\n * Tools response from the mcpd daemon.\n */\nexport interface ToolsResponse {\n tools?: Tool[];\n [serverName: string]: Tool[] | undefined;\n}\n\n/**\n * Health response from the mcpd API.\n * Contains health information for all tracked servers.\n */\nexport interface HealthResponse {\n $schema?: string;\n servers: ServerHealth[];\n}\n\n/**\n * Configuration options for the McpdClient.\n */\nexport interface McpdClientOptions {\n /**\n * The mcpd daemon API endpoint URL.\n */\n apiEndpoint: string;\n\n /**\n * Optional API key for authentication.\n */\n apiKey?: string;\n\n /**\n * TTL in seconds for caching server health checks.\n */\n healthCacheTtl?: number;\n\n /**\n * Request timeout in milliseconds.\n */\n timeout?: number;\n\n /**\n * Optional custom logger for SDK warnings and errors.\n *\n * If not provided, uses default logger (disabled by default).\n * Logging can be enabled by setting the MCPD_LOG_LEVEL environment variable.\n *\n * Supports partial implementations - any omitted methods fall back to the\n * default logger, which respects MCPD_LOG_LEVEL.\n *\n * NOTE: It is recommended that you only enable logging in non-MCP-server contexts.\n * MCP servers using stdio transport for JSON-RPC communication should avoid enabling logging\n * to avoid contaminating stdout/stderr.\n *\n * @example\n * ```typescript\n * // Use default logger (controlled by MCPD_LOG_LEVEL env var).\n * const client = new McpdClient({ apiEndpoint: \"http://localhost:8090\" });\n *\n * // Inject full custom logger.\n * const client = new McpdClient({\n * apiEndpoint: \"http://localhost:8090\",\n * logger: myCustomLogger,\n * });\n *\n * // Partial logger: custom warn/error, default (MCPD_LOG_LEVEL-aware) for others.\n * const client = new McpdClient({\n * apiEndpoint: \"http://localhost:8090\",\n * logger: {\n * warn: (msg) => myLogger.warn(`[mcpd] ${msg}`),\n * error: (msg) => myLogger.error(`[mcpd] ${msg}`),\n * // trace, debug, info use default logger (respects MCPD_LOG_LEVEL)\n * },\n * });\n *\n * // Disable logging: ensure MCPD_LOG_LEVEL is unset or set to 'off' (default).\n * const client = new McpdClient({ apiEndpoint: \"http://localhost:8090\" });\n *\n * // Override MCPD_LOG_LEVEL (disable even if env var is set).\n * const client = new McpdClient({\n * apiEndpoint: \"http://localhost:8090\",\n * logger: {\n * trace: () => {},\n * debug: () => {},\n * info: () => {},\n * warn: () => {},\n * error: () => {},\n * },\n * });\n * ```\n */\n logger?: Partial<Logger>;\n}\n\n/**\n * Tool format types for cross-framework compatibility.\n *\n * @remarks\n * Output format for agent tools.\n * - 'array': Returns array of functions (default, for LangChain)\n * - 'object': Returns object keyed by tool name (for Vercel AI SDK)\n * - 'map': Returns Map keyed by tool name\n */\nexport type AgentToolsFormat = \"array\" | \"object\" | \"map\";\n\n/**\n * Base options shared across all agent tools configurations.\n */\nexport interface BaseAgentToolsOptions {\n /**\n * List of server names to include. If not specified, or empty, should include all servers.\n */\n servers?: string[];\n\n /**\n * List of tool names to filter by.\n *\n * @remarks\n * Supports both:\n * - Raw tool names: 'get_current_time' (matches tool across all servers)\n * - Server-prefixed names: 'time__get_current_time' (server + TOOL_SEPARATOR + tool)\n * If not specified, returns all tools from selected servers.\n *\n * @example ['add', 'multiply']\n * @example ['time__get_current_time', 'math__add']\n */\n tools?: string[];\n\n /**\n * When true, clears the agent tools cache and fetches fresh tool schemas from servers.\n * When false or undefined, returns cached functions if available.\n *\n * @defaultValue false\n */\n refreshCache?: boolean;\n}\n\n/**\n * Options for getAgentTools with array format (default).\n * Returns an array of agent functions.\n */\nexport interface ArrayAgentToolsOptions extends BaseAgentToolsOptions {\n format?: \"array\";\n}\n\n/**\n * Options for getAgentTools with object format.\n * Returns an object keyed by tool name.\n */\nexport interface ObjectAgentToolsOptions extends BaseAgentToolsOptions {\n format: \"object\";\n}\n\n/**\n * Options for getAgentTools with map format.\n * Returns a Map keyed by tool name.\n */\nexport interface MapAgentToolsOptions extends BaseAgentToolsOptions {\n format: \"map\";\n}\n\n/**\n * Options for generating agent tools.\n * Discriminated union based on the format field.\n */\nexport type AgentToolsOptions =\n | ArrayAgentToolsOptions\n | ObjectAgentToolsOptions\n | MapAgentToolsOptions;\n\n/**\n * Function signature for performing tool calls.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type PerformCallFn = (\n serverName: string,\n toolName: string,\n args?: Record<string, unknown>,\n) => Promise<unknown>;\n\n/**\n * Function signature for getting tools from a server.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type GetToolsFn = (serverName: string) => Promise<Tool[]>;\n\n/**\n * Function signature for getting prompt templates from a server.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type GetPromptsFn = (serverName: string) => Promise<Prompt[]>;\n\n/**\n * Function signature for generating a prompt from a template.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type GeneratePromptFn = (\n serverName: string,\n promptName: string,\n args?: Record<string, string>,\n) => Promise<GeneratePromptResponseBody>;\n\n/**\n * Function signature for getting resources from a server.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type GetResourcesFn = (serverName: string) => Promise<Resource[]>;\n\n/**\n * Function signature for getting resource templates from a server.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type GetResourceTemplatesFn = (\n serverName: string,\n) => Promise<ResourceTemplate[]>;\n\n/**\n * Function signature for reading resource content from a server.\n * This is injected into proxy classes via dependency injection.\n * @internal\n */\nexport type ReadResourceFn = (\n serverName: string,\n uri: string,\n) => Promise<ResourceContent[]>;\n\n/**\n * MCP resource definition.\n */\nexport interface Resource {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n _meta?: Record<string, unknown>;\n}\n\n/**\n * Resources list response from the mcpd API.\n */\nexport interface Resources {\n $schema?: string;\n resources: Resource[];\n nextCursor?: string;\n}\n\n/**\n * Prompt argument definition.\n */\nexport interface PromptArgument {\n name: string;\n description?: string;\n required?: boolean;\n}\n\n/**\n * MCP prompt definition.\n */\nexport interface Prompt {\n name: string;\n description?: string;\n arguments?: PromptArgument[];\n _meta?: Record<string, unknown>;\n}\n\n/**\n * Prompts list response from the mcpd API.\n */\nexport interface Prompts {\n $schema?: string;\n prompts: Prompt[];\n nextCursor?: string;\n}\n\n/**\n * Prompt message in a generated prompt.\n */\nexport interface PromptMessage {\n role: string;\n content: unknown;\n}\n\n/**\n * Generated prompt response from the mcpd API.\n */\nexport interface GeneratePromptResponseBody {\n $schema?: string;\n description?: string;\n messages: PromptMessage[];\n}\n\n/**\n * Resource content response from the mcpd API.\n */\nexport interface ResourceContent {\n uri: string;\n text?: string;\n blob?: string;\n mimeType?: string;\n _meta?: Record<string, unknown>;\n}\n\n/**\n * MCP resource template definition.\n */\nexport interface ResourceTemplate {\n uriTemplate: string;\n name: string;\n description?: string;\n mimeType?: string;\n _meta?: Record<string, unknown>;\n}\n\n/**\n * Resource templates list response from the mcpd API.\n */\nexport interface ResourceTemplates {\n $schema?: string;\n templates: ResourceTemplate[];\n nextCursor?: string;\n}\n\n/**\n * Arguments for generating a prompt from a template.\n */\nexport interface PromptGenerateArguments {\n $schema?: string;\n arguments?: Record<string, string>;\n}\n","/**\n * Cache utilities for the mcpd SDK.\n */\n\nimport { LRUCache } from \"lru-cache\";\n\n/**\n * Options for creating a TTL cache.\n */\nexport interface CacheOptions {\n /**\n * Maximum number of items to store in the cache.\n */\n max?: number;\n\n /**\n * TTL in milliseconds for cached items.\n */\n ttl?: number;\n}\n\n/**\n * Creates a new LRU cache with TTL support.\n *\n * @param options - Cache configuration options\n * @returns A configured LRU cache instance\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type, @typescript-eslint/no-explicit-any\nexport function createCache<K extends {} = string, V extends {} = any>(\n options: CacheOptions = {},\n): LRUCache<K, V> {\n return new LRUCache<K, V>({\n max: options.max ?? 100,\n ttl: options.ttl ?? 10000, // Default 10 seconds\n updateAgeOnGet: false,\n updateAgeOnHas: false,\n });\n}\n","/**\n * Dynamic tool invocation for mcpd client.\n *\n * This module provides the ServersNamespace, Server, and ToolsNamespace classes\n * that enable natural JavaScript syntax for calling MCP tools, such as:\n * client.servers.time.tools.get_current_time(args)\n *\n * The dynamic calling system uses JavaScript's Proxy to create\n * a fluent interface that resolves server and tool names at runtime.\n *\n * Naming convention:\n * - *Namespace classes use Proxy for dynamic property access\n * - Server is a concrete class representing one MCP server\n */\n\nimport { ToolNotFoundError } from \"./errors\";\nimport type {\n Tool,\n Prompt,\n Resource,\n ResourceTemplate,\n ResourceContent,\n GeneratePromptResponseBody,\n PerformCallFn,\n GetToolsFn,\n GetPromptsFn,\n GeneratePromptFn,\n GetResourcesFn,\n GetResourceTemplatesFn,\n ReadResourceFn,\n} from \"./types\";\n\n/**\n * Namespace for accessing MCP servers via proxy.\n *\n * This class provides the `client.servers.*` namespace, allowing you to access\n * servers and their tools with natural JavaScript syntax.\n *\n * @example\n * ```typescript\n * const client = new McpdClient({ apiEndpoint: 'http://localhost:8090' });\n *\n * // Access tools through the servers namespace\n * const result = await client.servers.time.tools.get_current_time({ timezone: \"UTC\" });\n *\n * // Check if a tool exists\n * if (await client.servers.time.hasTool(\"get_current_time\")) {\n * // ...\n * }\n * ```\n */\nexport class ServersNamespace {\n [serverName: string]: Server;\n\n #performCall: PerformCallFn;\n #getTools: GetToolsFn;\n #generatePrompt: GeneratePromptFn;\n #getPrompts: GetPromptsFn;\n #getResources: GetResourcesFn;\n #getResourceTemplates: GetResourceTemplatesFn;\n #readResource: ReadResourceFn;\n\n /**\n * Initialize the ServersNamespace with injected functions.\n *\n * @param options - Configuration object\n * @param options.performCall - Function to execute tool calls\n * @param options.getTools - Function to get tool schemas\n * @param options.generatePrompt - Function to generate prompts\n * @param options.getPrompts - Function to get prompt schemas\n * @param options.getResources - Function to get resources\n * @param options.getResourceTemplates - Function to get resource templates\n * @param options.readResource - Function to read resource content\n */\n constructor({\n performCall,\n getTools,\n generatePrompt,\n getPrompts,\n getResources,\n getResourceTemplates,\n readResource,\n }: {\n performCall: PerformCallFn;\n getTools: GetToolsFn;\n generatePrompt: GeneratePromptFn;\n getPrompts: GetPromptsFn;\n getResources: GetResourcesFn;\n getResourceTemplates: GetResourceTemplatesFn;\n readResource: ReadResourceFn;\n }) {\n this.#performCall = performCall;\n this.#getTools = getTools;\n this.#generatePrompt = generatePrompt;\n this.#getPrompts = getPrompts;\n this.#getResources = getResources;\n this.#getResourceTemplates = getResourceTemplates;\n this.#readResource = readResource;\n\n // Return a Proxy to intercept property access\n return new Proxy(this, {\n get: (target, serverName: string | symbol) => {\n if (typeof serverName !== \"string\") {\n return undefined;\n }\n return new Server(\n target.#performCall,\n target.#getTools,\n target.#generatePrompt,\n target.#getPrompts,\n target.#getResources,\n target.#getResourceTemplates,\n target.#readResource,\n serverName,\n );\n },\n });\n }\n}\n\n/**\n * Represents a specific MCP server, providing access to its tools and operations.\n *\n * This class represents a specific MCP server and provides access to its tools\n * through the `.tools` namespace, as well as server-level operations like listing tools.\n *\n * @example\n * ```typescript\n * // Server is created when you access a server:\n * const timeServer = client.servers.time; // Returns Server(...)\n *\n * // List available tools\n * const tools = await timeServer.getTools();\n *\n * // Call tools through the .tools namespace:\n * await timeServer.tools.get_current_time({ timezone: \"UTC\" })\n * ```\n */\nexport class Server {\n readonly tools: ToolsNamespace;\n readonly prompts: PromptsNamespace;\n\n #performCall: PerformCallFn;\n #getTools: GetToolsFn;\n #generatePrompt: GeneratePromptFn;\n #getPrompts: GetPromptsFn;\n #getResources: GetResourcesFn;\n #getResourceTemplates: GetResourceTemplatesFn;\n #readResource: ReadResourceFn;\n #serverName: string;\n\n /**\n * Initialize a Server for a specific server.\n *\n * @param performCall - Function to execute tool calls\n * @param getTools - Function to get tool schemas\n * @param generatePrompt - Function to generate prompts\n * @param getPrompts - Function to get prompt schemas\n * @param getResources - Function to get resources\n * @param getResourceTemplates - Function to get resource templates\n * @param readResource - Function to read resource content\n * @param serverName - The name of the MCP server\n */\n constructor(\n performCall: PerformCallFn,\n getTools: GetToolsFn,\n generatePrompt: GeneratePromptFn,\n getPrompts: GetPromptsFn,\n getResources: GetResourcesFn,\n getResourceTemplates: GetResourceTemplatesFn,\n readResource: ReadResourceFn,\n serverName: string,\n ) {\n this.#performCall = performCall;\n this.#getTools = getTools;\n this.#generatePrompt = generatePrompt;\n this.#getPrompts = getPrompts;\n this.#getResources = getResources;\n this.#getResourceTemplates = getResourceTemplates;\n this.#readResource = readResource;\n this.#serverName = serverName;\n\n // Create the tools namespace as a real property.\n this.tools = new ToolsNamespace(\n this.#performCall,\n this.#getTools,\n this.#serverName,\n );\n\n // Create the prompts namespace as a real property.\n this.prompts = new PromptsNamespace(\n this.#generatePrompt,\n this.#getPrompts,\n this.#serverName,\n );\n }\n\n /**\n * Get all tools available on this server.\n *\n * @returns Array of tool schemas\n * @throws {ServerNotFoundError} If the server doesn't exist\n * @throws {ServerUnhealthyError} If the server is unhealthy\n *\n * @example\n * ```typescript\n * const tools = await client.servers.time.getTools();\n * for (const tool of tools) {\n * console.log(`${tool.name}: ${tool.description}`);\n * }\n * ```\n */\n async getTools(): Promise<Tool[]> {\n return this.#getTools(this.#serverName);\n }\n\n /**\n * Check if a tool exists on this server.\n *\n * The tool name must match exactly as returned by the server.\n *\n * This method is designed as a safe boolean predicate - it catches all errors\n * (ServerNotFoundError, ServerUnhealthyError, ConnectionError, etc.) and returns\n * false rather than throwing. This makes it safe to use in conditional checks\n * without requiring error handling.\n *\n * @param toolName - The exact name of the tool to check\n * @returns True if the tool exists, false otherwise (including on errors)\n *\n * @example\n * ```typescript\n * if (await client.servers.time.hasTool('get_current_time')) {\n * const result = await client.servers.time.callTool('get_current_time', { timezone: 'UTC' });\n * }\n * ```\n */\n async hasTool(toolName: string): Promise<boolean> {\n try {\n const tools = await this.#getTools(this.#serverName);\n return tools.some((t) => t.name === toolName);\n } catch {\n // Return false on any error to provide a safe boolean predicate.\n return false;\n }\n }\n\n /**\n * Call a tool by name with the given arguments.\n *\n * This method is useful for programmatic tool invocation when the tool name\n * is in a variable. The tool name must match exactly as returned by the server.\n *\n * @param toolName - The exact name of the tool to call\n * @param args - The arguments to pass to the tool\n * @returns The tool's response\n * @throws {ToolNotFoundError} If the tool doesn't exist on the server\n *\n * @example\n * ```typescript\n * // Call with explicit method (useful for dynamic tool names):\n * const toolName = 'get_current_time';\n * await client.servers.time.callTool(toolName, { timezone: 'UTC' });\n *\n * // Or with dynamic server name:\n * const serverName = 'time';\n * await client.servers[serverName].callTool(toolName, { timezone: 'UTC' });\n * ```\n */\n async callTool(\n toolName: string,\n args?: Record<string, unknown>,\n ): Promise<unknown> {\n // Check if the tool exists (exact match only)\n const tools = await this.#getTools(this.#serverName);\n const tool = tools.find((t) => t.name === toolName);\n\n if (!tool) {\n throw new ToolNotFoundError(\n `Tool '${toolName}' not found on server '${this.#serverName}'. ` +\n `Use client.servers.${this.#serverName}.getTools() to see available tools.`,\n this.#serverName,\n toolName,\n );\n }\n\n // Perform the tool call\n return this.#performCall(this.#serverName, toolName, args);\n }\n\n /**\n * Get all prompts available on this server.\n *\n * Note: This method is marked `async` for consistency with other server methods,\n * even though it doesn't directly await. This maintains a uniform async interface\n * and allows for future enhancements without breaking the API contract.\n *\n * @returns Array of prompt schemas\n * @throws {ServerNotFoundError} If the server doesn't exist\n * @throws {ServerUnhealthyError} If the server is unhealthy\n *\n * @example\n * ```typescript\n * const prompts = await client.servers.github.getPrompts();\n * for (const prompt of prompts) {\n * console.log(`${prompt.name}: ${prompt.description}`);\n * }\n * ```\n */\n async getPrompts(): Promise<Prompt[]> {\n return this.#getPrompts(this.#serverName);\n }\n\n /**\n * Check if a prompt exists on this server.\n *\n * The prompt name must match exactly as returned by the server.\n *\n * This method is designed as a safe boolean predicate - it catches all errors\n * (ServerNotFoundError, ServerUnhealthyError, ConnectionError, etc.) and returns\n * false rather than throwing. This makes it safe to use in conditional checks\n * without requiring error handling.\n *\n * @param promptName - The exact name of the prompt to check\n * @returns True if the prompt exists, false otherwise (including on errors)\n *\n * @example\n * ```typescript\n * if (await client.servers.github.hasPrompt('create_pr')) {\n * const result = await client.servers.github.generatePrompt('create_pr', { title: 'Fix bug' });\n * }\n * ```\n */\n async hasPrompt(promptName: string): Promise<boolean> {\n try {\n const prompts = await this.#getPrompts(this.#serverName);\n return prompts.some((p) => p.name === promptName);\n } catch {\n // Return false on any error to provide a safe boolean predicate.\n return false;\n }\n }\n\n /**\n * Generate a prompt by name with the given arguments.\n *\n * This method is useful for programmatic prompt generation when the prompt name\n * is in a variable. The prompt name must match exactly as returned by the server.\n *\n * @param promptName - The exact name of the prompt to generate\n * @param args - The arguments to pass to the prompt template\n * @returns The generated prompt response\n * @throws {ToolNotFoundError} If the prompt doesn't exist on the server\n *\n * @example\n * ```typescript\n * // Call with explicit method (useful for dynamic prompt names):\n * const promptName = 'create_pr';\n * await client.servers.github.generatePrompt(promptName, { title: 'Fix bug' });\n *\n * // Or with dynamic server name:\n * const serverName = 'github';\n * await client.servers[serverName].generatePrompt(promptName, { title: 'Fix bug' });\n * ```\n */\n async generatePrompt(\n promptName: string,\n args?: Record<string, string>,\n ): Promise<GeneratePromptResponseBody> {\n // Check if the prompt exists (exact match only).\n const prompts = await this.#getPrompts(this.#serverName);\n const prompt = prompts.find((p) => p.name === promptName);\n\n if (!prompt) {\n throw new ToolNotFoundError(\n `Prompt '${promptName}' not found on server '${this.#serverName}'. ` +\n `Use client.servers.${this.#serverName}.getPrompts() to see available prompts.`,\n this.#serverName,\n promptName,\n );\n }\n\n // Generate the prompt.\n return this.#generatePrompt(this.#serverName, promptName, args);\n }\n\n /**\n * Get all resources available on this server.\n *\n * Note: This method is marked `async` for consistency with other server methods,\n * even though it doesn't directly await. This maintains a uniform async interface\n * and allows for future enhancements without breaking the API contract.\n *\n * @returns Array of resource schemas with original names\n * @throws {ServerNotFoundError} If the server doesn't exist\n * @throws {ServerUnhealthyError} If the server is unhealthy\n *\n * @example\n * ```typescript\n * const resources = await client.servers.github.getResources();\n * for (const resource of resources) {\n * console.log(`${resource.name}: ${resource.uri}`);\n * }\n * ```\n */\n async getResources(): Promise<Resource[]> {\n return this.#getResources(this.#serverName);\n }\n\n /**\n * Get all resource templates available on this server.\n *\n * Note: This method is marked `async` for consistency with other server methods,\n * even though it doesn't directly await. This maintains a uniform async interface\n * and allows for future enhancements without breaking the API contract.\n *\n * @returns Array of resource template schemas with original names\n * @throws {ServerNotFoundError} If the server doesn't exist\n * @throws {ServerUnhealthyError} If the server is unhealthy\n *\n * @example\n * ```typescript\n * const templates = await client.servers.github.getResourceTemplates();\n * for (const template of templates) {\n * console.log(`${template.name}: ${template.uriTemplate}`);\n * }\n * ```\n */\n async getResourceTemplates(): Promise<ResourceTemplate[]> {\n return this.#getResourceTemplates(this.#serverName);\n }\n\n /**\n * Check if a resource exists on this server.\n *\n * The resource URI must match exactly as returned by the server.\n *\n * This method is designed as a safe boolean predicate - it catches all errors\n * (ServerNotFoundError, ServerUnhealthyError, ConnectionError, etc.) and returns\n * false rather than throwing. This makes it safe to use in conditional checks\n * without requiring error handling.\n *\n * @param uri - The exact URI of the resource to check\n * @returns True if the resource exists, false otherwise (including on errors)\n *\n * @example\n * ```typescript\n * if (await client.servers.github.hasResource('file:///repo/README.md')) {\n * const content = await client.servers.github.readResource('file:///repo/README.md');\n * }\n * ```\n */\n async hasResource(uri: string): Promise<boolean> {\n try {\n const resources = await this.#getResources(this.#serverName);\n return resources.some((r) => r.uri === uri);\n } catch {\n // Return false on any error to provide a safe boolean predicate.\n return false;\n }\n }\n\n /**\n * Read resource content by URI from this server.\n *\n * @param uri - The resource URI\n * @returns Array of resource contents (text or blob)\n * @throws {ServerNotFoundError} If the server doesn't exist\n * @throws {ServerUnhealthyError} If the server is unhealthy\n *\n * @example\n * ```typescript\n * const contents = await client.servers.github.readResource('file:///repo/README.md');\n * for (const content of contents) {\n * if (content.text) {\n * console.log(content.text);\n * } else if (content.blob) {\n * console.log('Binary content:', content.blob.substring(0, 50) + '...');\n * }\n * }\n * ```\n */\n async readResource(uri: string): Promise<ResourceContent[]> {\n return this.#readResource(this.#serverName, uri);\n }\n}\n\n/**\n * Namespace for accessing tools on a specific MCP server via proxy.\n *\n * This class provides the `.tools` namespace for a server, allowing you to call\n * tools as if they were methods. All tool names must match exactly as returned\n * by the MCP server.\n *\n * NOTE: Use `client.servers.foo.callTool()` and `client.servers.foo.hasTool()`\n * instead of putting them in the `.tools` namespace to avoid collisions with\n * actual tools named \"callTool\" or \"hasTool\".\n *\n * @example\n * ```typescript\n * // Call tools via .tools namespace with static names\n * const result = await client.servers.time.tools.get_current_time({ timezone: \"UTC\" });\n * ```\n */\nexport class ToolsNamespace {\n [toolName: string]: (args?: Record<string, unknown>) => Promise<unknown>;\n\n #performCall: PerformCallFn;\n #getTools: GetToolsFn;\n #serverName: string;\n\n /**\n * Initialize a ToolsNamespace for a specific server.\n *\n * @param performCall - Function to execute tool calls\n * @param getTools - Function to get tool schemas\n * @param serverName - The name of the MCP server\n */\n constructor(\n performCall: PerformCallFn,\n getTools: GetToolsFn,\n serverName: string,\n ) {\n this.#performCall = performCall;\n this.#getTools = getTools;\n this.#serverName = serverName;\n\n // Return a Proxy to intercept method calls\n return new Proxy(this, {\n get: (target, prop: string | symbol) => {\n if (typeof prop !== \"string\") {\n return undefined;\n }\n\n // Return a function that will call the tool with exact name matching\n return async (args?: Record<string, unknown>) => {\n const toolName = prop;\n\n // Check if the tool exists (exact match only)\n const tools = await target.#getTools(target.#serverName);\n const tool = tools.find((t) => t.name === toolName);\n\n if (!tool) {\n throw new ToolNotFoundError(\n `Tool '${toolName}' not found on server '${target.#serverName}'. ` +\n `Use client.servers.${target.#serverName}.getTools() to see available tools.`,\n target.#serverName,\n toolName,\n );\n }\n\n // Perform the tool call\n return target.#performCall(target.#serverName, toolName, args);\n };\n },\n });\n }\n}\n\n/**\n * Namespace for accessing prompts on a specific MCP server via proxy.\n *\n * This class provides the `.prompts` namespace for a server, allowing you to generate\n * prompts as if they were methods. All prompt names must match exactly as returned\n * by the MCP server.\n *\n * NOTE: Use `client.servers.foo.generatePrompt()` and `client.servers.foo.hasPrompt()`\n * instead of putting them in the `.prompts` namespace to avoid collisions with\n * actual prompts named \"generatePrompt\" or \"hasPrompt\".\n *\n * @example\n * ```typescript\n * // Generate prompts via .prompts namespace with static names\n * const result = await client.servers.github.prompts.create_pr({\n * title: \"Fix bug\",\n * description: \"Fixed auth issue\"\n * });\n * ```\n */\nexport class PromptsNamespace {\n [promptName: string]: (\n args?: Record<string, string>,\n ) => Promise<GeneratePromptResponseBody>;\n\n #generatePrompt: GeneratePromptFn;\n #getPrompts: GetPromptsFn;\n #serverName: string;\n\n /**\n * Initialize a PromptsNamespace for a specific server.\n *\n * @param generatePrompt - Function to generate prompts\n * @param getPrompts - Function to get prompt schemas\n * @param serverName - The name of the MCP server\n */\n constructor(\n generatePrompt: GeneratePromptFn,\n getPrompts: GetPromptsFn,\n serverName: string,\n ) {\n this.#generatePrompt = generatePrompt;\n this.#getPrompts = getPrompts;\n this.#serverName = serverName;\n\n // Return a Proxy to intercept method calls.\n return new Proxy(this, {\n get: (target, prop: string | symbol) => {\n if (typeof prop !== \"string\") {\n return undefined;\n }\n\n // Return a function that will generate the prompt with exact name matching.\n return async (args?: Record<string, string>) => {\n const promptName = prop;\n\n // Check if the prompt exists (exact match only).\n const prompt = await target.#getPromptByName(promptName);\n\n if (!prompt) {\n throw new ToolNotFoundError(\n `Prompt '${promptName}' not found on server '${target.#serverName}'. ` +\n `Use client.servers.${target.#serverName}.getPrompts() to see available prompts.`,\n target.#serverName,\n promptName,\n );\n }\n\n // Generate the prompt.\n return target.#generatePrompt(target.#serverName, promptName, args);\n };\n },\n });\n }\n\n /**\n * Helper method to find a prompt by name on this server.\n *\n * @param promptName - The exact name of the prompt to find\n * @returns The prompt if found, undefined otherwise\n * @internal\n */\n async #getPromptByName(promptName: string): Promise<Prompt | undefined> {\n const prompts = await this.#getPrompts(this.#serverName);\n return prompts.find((p) => p.name === promptName);\n }\n}\n","/**\n * JSON Schema to JavaScript type conversion and validation utilities.\n *\n * This module provides the TypeConverter class that handles conversion between\n * JSON Schema type definitions and JavaScript runtime type information. It supports\n * all standard JSON Schema types including complex constructs like unions (anyOf)\n * and provides runtime validation of values against their schemas.\n *\n * Used primarily by the FunctionBuilder for parameter validation and generating\n * human-readable type descriptions for dynamically generated functions.\n */\n\nimport type { JsonSchema } from \"../types\";\n\n/**\n * Maps JSON Schema types to JavaScript/TypeScript types.\n */\nexport class TypeConverter {\n /**\n * Convert JSON schema types to JavaScript type names.\n *\n * Maps JSON Schema types to their JavaScript equivalents:\n * - \"string\" → \"string\"\n * - \"integer\" → \"number\"\n * - \"number\" → \"number\"\n * - \"boolean\" → \"boolean\"\n * - \"array\" → \"array\"\n * - \"object\" → \"object\"\n * - \"null\" → \"null\"\n * - unknown types → \"any\"\n */\n static jsonTypeToJavaScriptType(\n jsonType: string,\n schemaDef: JsonSchema,\n ): string {\n switch (jsonType) {\n case \"string\":\n if (schemaDef.enum && Array.isArray(schemaDef.enum)) {\n // For enums, we'll use string but note the allowed values\n return \"string\";\n }\n return \"string\";\n case \"number\":\n case \"integer\":\n return \"number\";\n case \"boolean\":\n return \"boolean\";\n case \"array\":\n return \"array\";\n case \"object\":\n return \"object\";\n case \"null\":\n return \"null\";\n default:\n return \"any\";\n }\n }\n\n /**\n * Parse a schema definition and return the appropriate JavaScript type name.\n */\n static parseSchemaType(schemaDef: JsonSchema): string {\n if (schemaDef.anyOf && Array.isArray(schemaDef.anyOf)) {\n // For unions, we'll use the first type or 'any' if complex\n const firstType = schemaDef.anyOf[0];\n if (firstType && typeof firstType === \"object\" && firstType.type) {\n return this.jsonTypeToJavaScriptType(firstType.type, firstType);\n }\n return \"any\";\n }\n\n if (schemaDef.type) {\n return this.jsonTypeToJavaScriptType(schemaDef.type, schemaDef);\n }\n\n return \"any\";\n }\n\n /**\n * Get a human-readable description of the expected type.\n */\n static getTypeDescription(schemaDef: JsonSchema): string {\n const baseType = this.parseSchemaType(schemaDef);\n\n if (schemaDef.enum && Array.isArray(schemaDef.enum)) {\n return `one of: ${schemaDef.enum.map((v) => JSON.stringify(v)).join(\", \")}`;\n }\n\n if (schemaDef.type === \"array\" && schemaDef.items) {\n const itemType = this.parseSchemaType(schemaDef.items);\n return `array of ${itemType}`;\n }\n\n return baseType;\n }\n\n /**\n * Validate a value against a JSON schema type.\n * Returns true if valid, false otherwise.\n */\n static validateValue(value: unknown, schemaDef: JsonSchema): boolean {\n if (value === null || value === undefined) {\n // Null/undefined handling depends on whether the schema allows null\n return (\n schemaDef.type === \"null\" ||\n (schemaDef.anyOf?.some((s: JsonSchema) => s.type === \"null\") ?? false)\n );\n }\n\n if (schemaDef.enum && Array.isArray(schemaDef.enum)) {\n return schemaDef.enum.includes(value);\n }\n\n if (schemaDef.anyOf && Array.isArray(schemaDef.anyOf)) {\n return schemaDef.anyOf.some((subSchema) =>\n this.validateValue(value, subSchema),\n );\n }\n\n if (!schemaDef.type) {\n return true; // No type constraint\n }\n\n switch (schemaDef.type) {\n case \"string\":\n return typeof value === \"string\";\n case \"number\":\n return typeof value === \"number\" && isFinite(value);\n case \"integer\":\n return typeof value === \"number\" && Number.isInteger(value);\n case \"boolean\":\n return typeof value === \"boolean\";\n case \"array\":\n if (!Array.isArray(value)) return false;\n if (schemaDef.items) {\n return value.every((item) =>\n this.validateValue(item, schemaDef.items!),\n );\n }\n return true;\n case \"object\":\n return (\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n );\n case \"null\":\n return value === null;\n default:\n return true; // Unknown type, allow anything\n }\n }\n}\n","/**\n * Function generation from MCP tool schemas.\n *\n * This module provides the FunctionBuilder class that dynamically generates\n * callable JavaScript functions from MCP tool JSON Schema definitions. These\n * functions can be used with AI agent frameworks and include proper parameter\n * validation and comprehensive metadata.\n *\n * The generated functions are self-contained and cached for performance.\n */\n\nimport { z } from \"zod\";\nimport { McpdError, ValidationError } from \"./errors\";\nimport type { Tool, PerformCallFn } from \"./types\";\nimport { TypeConverter } from \"./utils/typeConverter\";\n\n/**\n * Interface for generated agent functions with metadata.\n * Compatible with both LangChain JS and Vercel AI SDK without conversion.\n */\nexport interface AgentFunction {\n (...args: unknown[]): Promise<unknown>;\n\n // Universal properties\n name: string;\n description: string;\n\n // LangChain JS compatibility properties\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema: z.ZodSchema<any>; // Zod schema for LangChain\n invoke: (args: unknown) => Promise<unknown>; // Primary method for LangChain\n lc_namespace: string[]; // Required namespace for LangChain\n returnDirect: boolean; // LangChain execution flag\n\n // Vercel AI SDK compatibility properties\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n inputSchema: z.ZodSchema<any>; // Zod schema for Vercel AI SDK\n execute: (args: unknown) => Promise<unknown>; // Primary method for Vercel AI SDK\n\n // Internal properties\n _schema: Tool;\n _serverName: string;\n _toolName: string;\n}\n\n/**\n * Builds callable JavaScript functions from MCP tool JSON schemas.\n *\n * This class generates self-contained functions that can be used with AI agent\n * frameworks. The generated functions include parameter validation and\n * comprehensive metadata based on the tool's JSON Schema definition.\n *\n * The generated functions are cached for performance, with cache invalidation\n * controlled by the owning McpdClient via clearCache().\n */\nexport class FunctionBuilder {\n #performCall: PerformCallFn;\n #functionCache: Map<string, AgentFunction> = new Map();\n\n /**\n * Initialize a FunctionBuilder with an injected function.\n *\n * @param performCall - Function to execute tool calls\n */\n constructor(performCall: PerformCallFn) {\n this.#performCall = performCall;\n }\n\n /**\n * Convert JSON schema to Zod schema.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #jsonSchemaToZod(jsonSchema: any): z.ZodSchema<any> {\n if (!jsonSchema || typeof jsonSchema !== \"object\") {\n return z.object({}); // Return empty object for undefined/null schemas\n }\n\n switch (jsonSchema.type) {\n case \"string\":\n return z.string();\n case \"number\":\n return z.number();\n case \"integer\":\n return z.number().int();\n case \"boolean\":\n return z.boolean();\n case \"array\":\n return z.array(\n jsonSchema.items ? this.#jsonSchemaToZod(jsonSchema.items) : z.any(),\n );\n case \"object\":\n // Handle object schemas that may or may not have properties\n if (jsonSchema.properties) {\n const propertyKeys = Object.keys(jsonSchema.properties);\n if (propertyKeys.length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const shape: Record<string, z.ZodSchema<any>> = {};\n const required = new Set(jsonSchema.required || []);\n\n for (const [key, value] of Object.entries(jsonSchema.properties)) {\n let schema = this.#jsonSchemaToZod(value);\n if (!required.has(key)) {\n // Use .nullable().optional() for OpenAI structured outputs compatibility\n schema = schema.nullable().optional();\n }\n shape[key] = schema;\n }\n\n return z.object(shape);\n }\n }\n // Return empty object for objects without properties or with empty properties\n return z.object({});\n default:\n // If no type is specified, check if it has properties\n if (jsonSchema.properties) {\n const propertyKeys = Object.keys(jsonSchema.properties);\n if (propertyKeys.length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const shape: Record<string, z.ZodSchema<any>> = {};\n const required = new Set(jsonSchema.required || []);\n\n for (const [key, value] of Object.entries(jsonSchema.properties)) {\n let schema = this.#jsonSchemaToZod(value);\n if (!required.has(key)) {\n // Use .nullable().optional() for OpenAI structured outputs compatibility\n schema = schema.nullable().optional();\n }\n shape[key] = schema;\n }\n\n return z.object(shape);\n }\n }\n // Default to empty object\n return z.object({});\n }\n }\n\n /**\n * Convert a string into a safe JavaScript identifier.\n *\n * This method sanitizes arbitrary strings (like server names or tool names) to create\n * valid JavaScript identifiers that can be used as function names.\n * It replaces non-word characters and handles edge cases like leading digits.\n *\n * @param name - The string to convert into a safe identifier\n * @returns A string that is a valid JavaScript identifier\n */\n private safeName(name: string): string {\n // Replace non-word characters and leading digits\n return name.replace(/\\W|^(?=\\d)/g, \"_\");\n }\n\n /**\n * Generate a unique function name from server and tool names.\n *\n * This method creates a qualified function name by combining the server name\n * and tool name with a double underscore separator. Both names are sanitized\n * using safeName() to ensure the result is a valid JavaScript identifier.\n *\n * @param serverName - The name of the MCP server hosting the tool\n * @param schemaName - The name of the tool from the schema definition\n * @returns A qualified function name in the format \"{safe_server}__{safe_tool}\"\n */\n private functionName(serverName: string, schemaName: string): string {\n return `${this.safeName(serverName)}__${this.safeName(schemaName)}`;\n }\n\n /**\n * Create a callable JavaScript function from an MCP tool's JSON Schema definition.\n *\n * This method generates a self-contained, callable function that validates parameters\n * and executes the corresponding MCP tool. The function includes proper parameter\n * validation and comprehensive metadata based on the tool's JSON Schema.\n *\n * Generated functions are cached for performance. If a function for the same\n * server/tool combination already exists in the cache, it returns the cached function.\n *\n * @param schema - The MCP tool's JSON Schema definition\n * @param serverName - The name of the MCP server hosting this tool\n * @returns A callable JavaScript function with metadata\n */\n createFunctionFromSchema(schema: Tool, serverName: string): AgentFunction {\n const cacheKey = `${serverName}__${schema.name}`;\n\n // Return cached function if it exists\n if (this.#functionCache.has(cacheKey)) {\n return this.#functionCache.get(cacheKey)!;\n }\n\n try {\n const generatedFunction = this.buildFunction(schema, serverName);\n this.#functionCache.set(cacheKey, generatedFunction);\n return generatedFunction;\n } catch (error) {\n throw new McpdError(\n `Error creating function ${cacheKey}: ${(error as Error).message}`,\n error as Error,\n );\n }\n }\n\n /**\n * Build the actual function from the schema.\n *\n * @param schema - The tool schema\n * @param serverName - The server name\n * @returns The generated function with metadata\n */\n private buildFunction(schema: Tool, serverName: string): AgentFunction {\n const inputSchema = schema.inputSchema || {};\n const properties = inputSchema.properties || {};\n const required = new Set(inputSchema.required || []);\n\n // Create the function implementation\n const implementation = async (...args: unknown[]): Promise<unknown> => {\n // Handle both positional and named arguments\n let params: Record<string, unknown> = {};\n\n if (\n args.length === 1 &&\n typeof args[0] === \"object\" &&\n args[0] !== null &&\n !Array.isArray(args[0])\n ) {\n // Single object argument (named parameters)\n params = args[0] as Record<string, unknown>;\n } else {\n // Positional arguments - map to schema properties in order\n const propertyNames = Object.keys(properties);\n for (let i = 0; i < args.length && i < propertyNames.length; i++) {\n const propertyName = propertyNames[i];\n if (propertyName) {\n params[propertyName] = args[i];\n }\n }\n }\n\n // Validate required parameters\n const missingParams: string[] = [];\n for (const paramName of required) {\n if (\n !(paramName in params) ||\n params[paramName] === null ||\n params[paramName] === undefined\n ) {\n missingParams.push(paramName);\n }\n }\n\n if (missingParams.length > 0) {\n throw new ValidationError(\n `Missing required parameters: ${missingParams.join(\", \")}`,\n missingParams,\n );\n }\n\n // Validate parameter types\n const validationErrors: string[] = [];\n for (const [paramName, paramValue] of Object.entries(params)) {\n const paramSchema = properties[paramName];\n if (paramValue !== null && paramValue !== undefined && paramSchema) {\n if (!TypeConverter.validateValue(paramValue, paramSchema)) {\n const expectedType = TypeConverter.getTypeDescription(paramSchema);\n validationErrors.push(\n `Parameter '${paramName}' should be ${expectedType}, got ${typeof paramValue}`,\n );\n }\n }\n }\n\n if (validationErrors.length > 0) {\n throw new ValidationError(\n `Parameter validation failed: ${validationErrors.join(\"; \")}`,\n validationErrors,\n );\n }\n\n // Filter out null/undefined values\n const cleanParams: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(params)) {\n if (value !== null && value !== undefined) {\n cleanParams[key] = value;\n }\n }\n\n // Make the API call\n return this.#performCall(serverName, schema.name, cleanParams);\n };\n\n // Create execution methods for both frameworks\n const invoke = async (args: unknown): Promise<unknown> => {\n return implementation(args);\n };\n\n const execute = async (args: unknown): Promise<unknown> => {\n return implementation(args);\n };\n\n // Convert JSON schema to Zod schema for both frameworks\n const zodSchema = this.#jsonSchemaToZod(inputSchema);\n\n // Add metadata to the function\n const qualifiedName = this.functionName(serverName, schema.name);\n const docstring = this.createDocstring(schema);\n\n // Cast to AgentFunction and add metadata\n const agentFunction = implementation as AgentFunction;\n\n // Use Object.defineProperty for read-only 'name' property\n Object.defineProperty(agentFunction, \"name\", {\n value: qualifiedName,\n writable: false,\n enumerable: true,\n configurable: true,\n });\n\n // Universal properties\n agentFunction.description =\n schema.description ||\n docstring.split(\"\\n\")[0] ||\n \"No description provided\";\n\n // LangChain JS compatibility properties\n agentFunction.schema = zodSchema;\n agentFunction.invoke = invoke;\n agentFunction.lc_namespace = [\"mcpd\", \"tools\"];\n agentFunction.returnDirect = false;\n\n // Vercel AI SDK compatibility properties\n agentFunction.inputSchema = zodSchema; // Use Zod schema for Vercel AI SDK compatibility\n agentFunction.execute = execute;\n\n // Internal properties\n agentFunction._schema = schema;\n agentFunction._serverName = serverName;\n agentFunction._toolName = schema.name;\n\n return agentFunction;\n }\n\n /**\n * Generate a comprehensive docstring for the dynamically created function.\n *\n * This method builds a properly formatted docstring that includes the\n * tool's description, parameter documentation with optional/required status,\n * return value information, and exception documentation.\n *\n * @param schema - The MCP tool's JSON Schema definition\n * @returns A multi-line string containing the complete docstring text\n */\n private createDocstring(schema: Tool): string {\n const description = schema.description || \"No description provided\";\n const inputSchema = schema.inputSchema || {};\n const properties = inputSchema.properties || {};\n const required = new Set(inputSchema.required || []);\n\n const docstringParts = [description];\n\n if (Object.keys(properties).length > 0) {\n docstringParts.push(\"\");\n docstringParts.push(\"Parameters:\");\n\n for (const [paramName, paramInfo] of Object.entries(properties)) {\n const isRequired = required.has(paramName);\n const paramDesc = paramInfo.description || \"No description provided\";\n const paramType = TypeConverter.getTypeDescription(paramInfo);\n const requiredText = isRequired ? \"\" : \" (optional)\";\n docstringParts.push(\n ` ${paramName} (${paramType}): ${paramDesc}${requiredText}`,\n );\n }\n }\n\n docstringParts.push(\"\");\n docstringParts.push(\"Returns:\");\n docstringParts.push(\" Promise<any>: Function execution result\");\n docstringParts.push(\"\");\n docstringParts.push(\"Throws:\");\n docstringParts.push(\n \" ValidationError: If required parameters are missing or invalid\",\n );\n docstringParts.push(\" McpdError: If the API call fails\");\n\n return docstringParts.join(\"\\n\");\n }\n\n /**\n * Clear the function cache.\n *\n * This method clears all cached generated functions, forcing them to be\n * regenerated on the next call to createFunctionFromSchema().\n */\n clearCache(): void {\n this.#functionCache.clear();\n }\n\n /**\n * Get the current cache size.\n *\n * @returns The number of functions currently cached\n */\n getCacheSize(): number {\n return this.#functionCache.size;\n }\n\n /**\n * Get all cached functions.\n *\n * @returns Array of all cached agent functions, or empty array if cache is empty\n */\n getCachedFunctions(): AgentFunction[] {\n return Array.from(this.#functionCache.values());\n }\n}\n","/**\n * Centralized API path constants for mcpd daemon endpoints.\n */\n\nconst API_BASE = \"/api/v1\";\n\nconst SERVERS_BASE = `${API_BASE}/servers`;\nconst HEALTH_SERVERS_BASE = `${API_BASE}/health/servers`;\n\nexport const API_PATHS = {\n // Server management\n SERVERS: SERVERS_BASE,\n\n // Tools\n SERVER_TOOLS: (serverName: string) =>\n `${SERVERS_BASE}/${encodeURIComponent(serverName)}/tools`,\n TOOL_CALL: (serverName: string, toolName: string) =>\n `${SERVERS_BASE}/${encodeURIComponent(serverName)}/tools/${encodeURIComponent(toolName)}`,\n\n // Prompts\n SERVER_PROMPTS: (serverName: string, cursor?: string) => {\n const base = `${SERVERS_BASE}/${encodeURIComponent(serverName)}/prompts`;\n return cursor ? `${base}?cursor=${encodeURIComponent(cursor)}` : base;\n },\n PROMPT_GET_GENERATED: (serverName: string, promptName: string) =>\n `${SERVERS_BASE}/${encodeURIComponent(serverName)}/prompts/${encodeURIComponent(promptName)}`,\n\n // Resources\n SERVER_RESOURCES: (serverName: string, cursor?: string) => {\n const base = `${SERVERS_BASE}/${encodeURIComponent(serverName)}/resources`;\n return cursor ? `${base}?cursor=${encodeURIComponent(cursor)}` : base;\n },\n SERVER_RESOURCE_TEMPLATES: (serverName: string, cursor?: string) => {\n const base = `${SERVERS_BASE}/${encodeURIComponent(serverName)}/resources/templates`;\n return cursor ? `${base}?cursor=${encodeURIComponent(cursor)}` : base;\n },\n RESOURCE_CONTENT: (serverName: string, uri: string) =>\n `${SERVERS_BASE}/${encodeURIComponent(serverName)}/resources/content?uri=${encodeURIComponent(uri)}`,\n\n // Health\n HEALTH_ALL: HEALTH_SERVERS_BASE,\n HEALTH_SERVER: (serverName: string) =>\n `${HEALTH_SERVERS_BASE}/${encodeURIComponent(serverName)}`,\n} as const;\n","/**\n * Internal logging infrastructure for the mcpd SDK.\n *\n * This module provides a logging shim controlled by the MCPD_LOG_LEVEL environment\n * variable.\n *\n * Logging is disabled by default.\n *\n * NOTE: It is recommended that you only enable MCPD_LOG_LEVEL in non-MCP-server contexts.\n * MCP servers using stdio transport for JSON-RPC communication should avoid enabling logging\n * to avoid contaminating stdout/stderr.\n */\n\n/**\n * Valid {@link LogLevel} values for MCPD_LOG_LEVEL environment variable.\n */\nexport const LogLevels = {\n TRACE: \"trace\" as const,\n DEBUG: \"debug\" as const,\n INFO: \"info\" as const,\n WARN: \"warn\" as const,\n ERROR: \"error\" as const,\n OFF: \"off\" as const,\n};\n\n/**\n * Log level type.\n */\nexport type LogLevel = (typeof LogLevels)[keyof typeof LogLevels];\n\n/**\n * Logger interface defining the SDK's logging contract.\n *\n * Each method accepts a message and optional arguments for string formatting.\n * A full Logger implementation provides all methods.\n */\nexport interface Logger {\n /**\n * Log a trace-level message (most verbose).\n *\n * @param args - Message and optional formatting arguments.\n */\n trace(...args: unknown[]): void;\n\n /**\n * Log a debug-level message.\n *\n * @param args - Message and optional formatting arguments.\n */\n debug(...args: unknown[]): void;\n\n /**\n * Log an info-level message.\n *\n * @param args - Message and optional formatting arguments.\n */\n info(...args: unknown[]): void;\n\n /**\n * Log a warning-level message.\n *\n * @param args - Message and optional formatting arguments.\n */\n warn(...args: unknown[]): void;\n\n /**\n * Log an error-level message.\n *\n * @param args - Message and optional formatting arguments.\n */\n error(...args: unknown[]): void;\n}\n\n// Numeric ranks for log levels (lower = more verbose).\nconst ranks: Record<LogLevel, number> = {\n trace: 5,\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n off: 1000,\n};\n\n// Attempts to resolve log level from a (case insensitive) environment variable value.\n// Defaults to \"off\" if unrecognized.\nfunction resolve(raw: string | undefined): LogLevel {\n const candidate = raw?.toLowerCase() as LogLevel | undefined;\n return candidate && candidate in ranks ? candidate : LogLevels.OFF;\n}\n\n// Lazily resolve the level at call time to support testing.\nfunction getLevel(): LogLevel {\n return resolve(\n typeof process !== \"undefined\" ? process.env.MCPD_LOG_LEVEL : undefined,\n );\n}\n\n// Default logger implementation using console methods.\nfunction defaultLogger(): Logger {\n return {\n trace: (...args) => {\n const lvl = getLevel();\n if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.trace)\n console.trace(...args);\n },\n debug: (...args) => {\n const lvl = getLevel();\n if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.debug)\n console.debug(...args);\n },\n info: (...args) => {\n const lvl = getLevel();\n if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.info)\n console.info(...args);\n },\n warn: (...args) => {\n const lvl = getLevel();\n if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.warn)\n console.warn(...args);\n },\n error: (...args) => {\n const lvl = getLevel();\n if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.error)\n console.error(...args);\n },\n };\n}\n\n/**\n * Create a logger, optionally using a custom implementation.\n *\n * This function allows SDK users to inject their own logger implementation.\n * Supports partial implementations - any omitted methods will fall back to the\n * default logger, which respects the MCPD_LOG_LEVEL environment variable.\n *\n * @param impl - Custom Logger implementation or partial implementation.\n * If not provided, uses default logger controlled by MCPD_LOG_LEVEL.\n * If partially provided, custom methods are used and omitted methods\n * fall back to default logger (which respects MCPD_LOG_LEVEL).\n * @returns A Logger instance with all methods implemented.\n *\n * @example\n * ```typescript\n * // Use default logger (controlled by MCPD_LOG_LEVEL).\n * const logger = createLogger();\n *\n * // Partial logger: custom warn/error, default (MCPD_LOG_LEVEL-aware) for others.\n * const logger = createLogger({\n * warn: (msg) => myCustomLogger.warning(msg),\n * error: (msg) => myCustomLogger.error(msg),\n * // trace, debug, info fall back to default logger (respects MCPD_LOG_LEVEL)\n * });\n * ```\n */\nexport function createLogger(impl?: Partial<Logger>): Logger {\n const base = defaultLogger();\n return {\n trace: impl?.trace ?? base.trace,\n debug: impl?.debug ?? base.debug,\n info: impl?.info ?? base.info,\n warn: impl?.warn ?? base.warn,\n error: impl?.error ?? base.error,\n };\n}\n","/**\n * mcpd client for MCP server management and tool execution.\n *\n * This module provides the main McpdClient class that interfaces with the mcpd\n * daemon to manage interactions with MCP servers and execute tools. It offers\n * multiple interaction patterns including direct API calls, dynamic calling\n * syntax, and agent-ready function generation.\n *\n * The client handles authentication, error management, and provides a unified\n * interface for working with multiple MCP servers through the mcpd daemon.\n */\n\nimport { LRUCache } from \"lru-cache\";\nimport {\n McpdError,\n ConnectionError,\n AuthenticationError,\n ServerNotFoundError,\n ServerUnhealthyError,\n ToolExecutionError,\n TimeoutError,\n PipelineError,\n PIPELINE_FLOW_REQUEST,\n PIPELINE_FLOW_RESPONSE,\n type PipelineFlow,\n} from \"./errors\";\nimport {\n HealthStatusHelpers,\n McpdClientOptions,\n ServerHealth,\n Tool,\n ToolsResponse,\n HealthResponse,\n ErrorModel,\n AgentToolsOptions,\n ArrayAgentToolsOptions,\n ObjectAgentToolsOptions,\n MapAgentToolsOptions,\n Prompt,\n Prompts,\n GeneratePromptResponseBody,\n PromptGenerateArguments,\n Resource,\n Resources,\n ResourceTemplate,\n ResourceTemplates,\n ResourceContent,\n} from \"./types\";\nimport { createCache } from \"./utils/cache\";\nimport { ServersNamespace } from \"./dynamicCaller\";\nimport { FunctionBuilder, type AgentFunction } from \"./functionBuilder\";\nimport { API_PATHS } from \"./apiPaths\";\nimport { createLogger, type Logger } from \"./logger\";\n\n/**\n * Default timeout for API requests to mcpd, in seconds.\n */\nconst REQUEST_TIMEOUT_SECONDS = 30;\n\n/**\n * Default TTL for server health cache entries, in seconds.\n *\n * @remarks\n * Used to avoid excessive health check requests while keeping data reasonably fresh.\n */\nconst SERVER_HEALTH_CACHE_TTL_SECONDS = 10;\n\n/**\n * Maximum number of server health entries to cache.\n * Prevents unbounded memory growth while allowing legitimate large-scale monitoring.\n */\nconst SERVER_HEALTH_CACHE_MAXSIZE = 100;\n\n/**\n * Separator used between server name and tool name in qualified tool names.\n * Format: `{serverName}{TOOL_SEPARATOR}{toolName}`\n * Example: \"time__get_current_time\" where \"time\" is server and \"get_current_time\" is tool.\n */\nconst TOOL_SEPARATOR = \"__\";\n\n/**\n * Header name for mcpd pipeline error type.\n */\nconst MCPD_ERROR_TYPE_HEADER = \"Mcpd-Error-Type\";\n\n/**\n * Maps mcpd error type header values to pipeline flows.\n */\nconst PIPELINE_ERROR_FLOWS: Record<string, PipelineFlow> = {\n \"request-pipeline-failure\": PIPELINE_FLOW_REQUEST,\n \"response-pipeline-failure\": PIPELINE_FLOW_RESPONSE,\n};\n\n/**\n * Type alias for agent functions in array format.\n * @internal\n */\ntype AgentFunctionsArray = AgentFunction[];\n\n/**\n * Type alias for agent functions in object format (keyed by function name).\n * @internal\n */\ntype AgentFunctionsRecord = Record<string, AgentFunction>;\n\n/**\n * Type alias for agent functions in Map format (keyed by function name).\n * @internal\n */\ntype AgentFunctionsMap = Map<string, AgentFunction>;\n\n/**\n * Client for interacting with MCP (Model Context Protocol) servers through an mcpd daemon.\n *\n * The McpdClient provides a high-level interface to discover, inspect, and invoke tools\n * exposed by MCP servers running behind an mcpd daemon proxy/gateway.\n *\n * Thread Safety:\n * This client is safe to use from multiple async contexts. The internal health\n * check cache is protected by the LRUCache implementation.\n *\n * @example\n * ```typescript\n * import { McpdClient } from '@mozilla-ai/mcpd';\n *\n * // Initialize client\n * const client = new McpdClient({\n * apiEndpoint: 'http://localhost:8090',\n * apiKey: 'optional-key',\n * healthCacheTtl: 10,\n * });\n *\n * // List available servers\n * const servers = await client.listServers();\n * console.log(servers); // ['time', 'fetch', 'git']\n *\n * // Invoke a tool dynamically\n * const result = await client.servers.time.get_current_time({ timezone: 'UTC' });\n * console.log(result); // { time: '2024-01-15T10:30:00Z' }\n * ```\n */\nexport class McpdClient {\n readonly #endpoint: string;\n readonly #apiKey: string | undefined;\n readonly #timeout: number;\n readonly #serverHealthCache: LRUCache<string, ServerHealth | Error>;\n readonly #functionBuilder: FunctionBuilder;\n readonly #logger: Logger;\n readonly #cacheableExceptions = new Set([\n ServerNotFoundError,\n ServerUnhealthyError,\n AuthenticationError,\n ]);\n\n /**\n * Namespace for accessing MCP servers and their tools.\n */\n public readonly servers: ServersNamespace;\n\n /**\n * Initialize a new McpdClient instance.\n *\n * @param options - Configuration options for the client\n */\n constructor(options: McpdClientOptions) {\n // Helper for time conversion.\n const toMs = (s: number) => s * 1000; // seconds to milliseconds\n\n // Remove trailing slash from endpoint.\n this.#endpoint = options.apiEndpoint.replace(/\\/$/, \"\");\n this.#apiKey = options.apiKey;\n this.#timeout = options.timeout ?? toMs(REQUEST_TIMEOUT_SECONDS);\n\n // Setup health cache.\n const healthCacheTtlMs = toMs(\n options.healthCacheTtl ?? SERVER_HEALTH_CACHE_TTL_SECONDS,\n );\n this.#serverHealthCache = createCache({\n max: SERVER_HEALTH_CACHE_MAXSIZE,\n ttl: healthCacheTtlMs,\n });\n\n // Setup logger (the default logger uses MCPD_LOG_LEVEL).\n this.#logger = createLogger(options.logger);\n\n // Initialize servers namespace and function builder with injected functions.\n this.servers = new ServersNamespace({\n performCall: this.#performCall.bind(this),\n getTools: this.#getToolsByServer.bind(this),\n generatePrompt: this.#generatePromptInternal.bind(this),\n getPrompts: this.#getPromptsByServer.bind(this),\n getResources: this.#getResourcesByServer.bind(this),\n getResourceTemplates: this.#getResourceTemplatesByServer.bind(this),\n readResource: this.#readResourceByServer.bind(this),\n });\n this.#functionBuilder = new FunctionBuilder(this.#performCall.bind(this));\n }\n\n /**\n * Make an HTTP request to the mcpd daemon.\n *\n * @param path - The API path (e.g., '/servers', '/servers/{server_name}/tools')\n * @param options - Request options\n *\n * @returns The JSON response from the daemon\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #request<T = unknown>(\n path: string,\n options: RequestInit = {},\n ): Promise<T> {\n const url = `${this.#endpoint}${path}`;\n\n // Setup request headers\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...((options.headers as Record<string, string>) || {}),\n };\n\n // Add authentication if configured\n if (this.#apiKey) {\n headers[\"Authorization\"] = `Bearer ${this.#apiKey}`;\n }\n\n // Setup timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.#timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Handle non-2xx responses with ErrorModel parsing\n if (!response.ok) {\n const body = await response.text();\n let errorModel: ErrorModel | null = null;\n\n try {\n errorModel = JSON.parse(body) as ErrorModel;\n } catch {\n // Response body is not valid JSON - fall through to fallback error handling below.\n errorModel = null;\n }\n\n // Check for pipeline failure (500 with Mcpd-Error-Type header).\n if (response.status === 500) {\n const errorType = response.headers\n .get(MCPD_ERROR_TYPE_HEADER)\n ?.toLowerCase();\n\n const flow = errorType ? PIPELINE_ERROR_FLOWS[errorType] : undefined;\n\n if (flow) {\n const message = errorModel?.detail || body || \"Pipeline failure\";\n\n throw new PipelineError(\n message,\n undefined, // serverName - enriched by caller if available.\n undefined, // operation - enriched by caller if available.\n flow,\n );\n }\n }\n\n if (errorModel && errorModel.detail) {\n const errorDetails = errorModel.errors\n ?.map((e) => `${e.location}: ${e.message}`)\n .join(\"; \");\n const fullMessage = errorDetails\n ? `${errorModel.detail} - ${errorDetails}`\n : errorModel.detail;\n\n // Handle authentication errors\n if (response.status === 401 || response.status === 403) {\n throw new AuthenticationError(fullMessage);\n }\n\n // Handle other errors with proper message\n throw new McpdError(\n `${errorModel.title || \"Request failed\"}: ${fullMessage}`,\n );\n }\n\n // Fallback if ErrorModel parsing failed\n if (response.status === 401 || response.status === 403) {\n throw new AuthenticationError(\n `Authentication failed: ${response.status} ${response.statusText}`,\n );\n }\n\n throw new McpdError(\n `Request failed: ${response.status} ${response.statusText} - ${body}`,\n );\n }\n\n // Parse JSON response\n try {\n return (await response.json()) as T;\n } catch (error) {\n throw new McpdError(\"Failed to parse JSON response\", error as Error);\n }\n } catch (error) {\n clearTimeout(timeoutId);\n\n // Handle timeout\n if ((error as Error).name === \"AbortError\") {\n throw new TimeoutError(\n `Request timed out after ${this.#timeout}ms`,\n path,\n this.#timeout,\n );\n }\n\n // Handle connection errors\n if (error instanceof TypeError && error.message.includes(\"fetch\")) {\n throw new ConnectionError(\n `Cannot connect to mcpd daemon at ${this.#endpoint}. Is it running?`,\n error,\n );\n }\n\n // Re-throw our errors as-is\n if (error instanceof McpdError) {\n throw error;\n }\n\n // Wrap unknown errors\n throw new McpdError(\n `Request failed: ${(error as Error).message}`,\n error as Error,\n );\n }\n }\n\n /**\n * Get a list of all configured MCP servers.\n *\n * @returns Array of server names\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @example\n * ```typescript\n * const servers = await client.listServers();\n * console.log(servers); // ['time', 'fetch', 'git']\n * ```\n */\n async listServers(): Promise<string[]> {\n return await this.#request<string[]>(API_PATHS.SERVERS);\n }\n\n /**\n * Get tool schemas for a server.\n *\n * @privateRemarks\n * Used by dependency injection for ServersNamespace and internally for getAgentTools.\n *\n * @param serverName - Server name to get tools for\n *\n * @returns Tool schemas for the specified server\n *\n * @throws {ServerNotFoundError} If the specified server doesn't exist\n * @throws {ServerUnhealthyError} If the server is not healthy\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #getToolsByServer(serverName: string): Promise<Tool[]> {\n // Check server health first\n await this.#ensureServerHealthy(serverName);\n\n const path = API_PATHS.SERVER_TOOLS(serverName);\n const response = await this.#request<ToolsResponse>(path);\n\n if (!response.tools) {\n throw new ServerNotFoundError(\n `Server '${serverName}' not found`,\n serverName,\n );\n }\n\n return response.tools;\n }\n\n /**\n * Get prompt schemas for a server.\n *\n * @privateRemarks\n * Used internally for getPromptSchemas.\n *\n * @param serverName - Server name to get prompts for\n * @param cursor - Cursor for pagination\n *\n * @returns Prompt schemas for the specified server\n *\n * @throws {ServerNotFoundError} If the specified server doesn't exist\n * @throws {ServerUnhealthyError} If the server is not healthy\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #getPromptsByServer(\n serverName: string,\n cursor?: string,\n ): Promise<Prompt[]> {\n try {\n // Check server health first.\n await this.#ensureServerHealthy(serverName);\n\n const path = API_PATHS.SERVER_PROMPTS(serverName, cursor);\n const response = await this.#request<Prompts>(path);\n return response.prompts || [];\n } catch (error) {\n // Handle 501 Not Implemented - server doesn't support prompts.\n if (\n error instanceof McpdError &&\n error.message.includes(\"501\") &&\n error.message.includes(\"Not Implemented\")\n ) {\n return [];\n }\n\n throw error;\n }\n }\n\n /**\n * Generate a prompt on a server.\n *\n * @privateRemarks\n * Used internally by:\n * - PromptsNamespace (via dependency injection)\n * - Server.generatePrompt() (via dependency injection)\n *\n * @param serverName - The name of the server\n * @param promptName - The exact name of the prompt\n * @param args - The prompt arguments\n *\n * @returns The generated prompt response\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #generatePromptInternal(\n serverName: string,\n promptName: string,\n args?: Record<string, string>,\n ): Promise<GeneratePromptResponseBody> {\n // Check server health first.\n await this.#ensureServerHealthy(serverName);\n\n const path = API_PATHS.PROMPT_GET_GENERATED(serverName, promptName);\n const requestBody: PromptGenerateArguments = {\n arguments: args || {},\n };\n\n const response = await this.#request<GeneratePromptResponseBody>(path, {\n method: \"POST\",\n body: JSON.stringify(requestBody),\n });\n\n return response;\n }\n\n /**\n * Get resource schemas for a server.\n *\n * @privateRemarks\n * Used internally for getResources and by dependency injection for ServersNamespace.\n *\n * @param serverName - Server name to get resources for\n * @param cursor - Cursor for pagination\n *\n * @returns Resource schemas for the specified server\n *\n * @throws {ServerNotFoundError} If the specified server doesn't exist\n * @throws {ServerUnhealthyError} If the server is not healthy\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #getResourcesByServer(\n serverName: string,\n cursor?: string,\n ): Promise<Resource[]> {\n try {\n // Check server health first.\n await this.#ensureServerHealthy(serverName);\n\n const path = API_PATHS.SERVER_RESOURCES(serverName, cursor);\n const response = await this.#request<Resources>(path);\n return response.resources || [];\n } catch (error) {\n // Handle 501 Not Implemented - server doesn't support resources.\n if (\n error instanceof McpdError &&\n error.message.includes(\"501\") &&\n error.message.includes(\"Not Implemented\")\n ) {\n return [];\n }\n\n throw error;\n }\n }\n\n /**\n * Get resource template schemas for a server.\n *\n * @privateRemarks\n * Used internally for getResourceTemplates and by dependency injection for ServersNamespace.\n *\n * @param serverName - Server name to get resource templates for\n * @param cursor - Cursor for pagination\n *\n * @returns Resource template schemas for the specified server\n *\n * @throws {ServerNotFoundError} If the specified server doesn't exist\n * @throws {ServerUnhealthyError} If the server is not healthy\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #getResourceTemplatesByServer(\n serverName: string,\n cursor?: string,\n ): Promise<ResourceTemplate[]> {\n try {\n // Check server health first.\n await this.#ensureServerHealthy(serverName);\n\n const path = API_PATHS.SERVER_RESOURCE_TEMPLATES(serverName, cursor);\n const response = await this.#request<ResourceTemplates>(path);\n return response.templates || [];\n } catch (error) {\n // Handle 501 Not Implemented - server doesn't support resource templates.\n if (\n error instanceof McpdError &&\n error.message.includes(\"501\") &&\n error.message.includes(\"Not Implemented\")\n ) {\n return [];\n }\n\n throw error;\n }\n }\n\n /**\n * Read resource content from a server.\n *\n * @privateRemarks\n * Used by dependency injection for ServersNamespace.\n *\n * @param serverName - Server name to read resource from\n * @param uri - The resource URI\n *\n * @returns Array of resource contents (text or blob)\n *\n * @throws {ServerNotFoundError} If the specified server doesn't exist\n * @throws {ServerUnhealthyError} If the server is not healthy\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #readResourceByServer(\n serverName: string,\n uri: string,\n ): Promise<ResourceContent[]> {\n // Check server health first.\n await this.#ensureServerHealthy(serverName);\n\n const path = API_PATHS.RESOURCE_CONTENT(serverName, uri);\n const response = await this.#request<ResourceContent[]>(path);\n return response || [];\n }\n\n /**\n * Get health information for one or all servers.\n *\n * @param serverName - Server name to get health for, or undefined for all servers\n *\n * @returns Health information for the specified server or all servers\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @example\n * ```typescript\n * // Get health for all servers\n * const allHealth = await client.getServerHealth();\n * console.log(allHealth); // { time: { status: 'ok' }, fetch: { status: 'ok' } }\n *\n * // Get health for a specific server\n * const timeHealth = await client.getServerHealth('time');\n * console.log(timeHealth); // { status: 'ok' }\n * ```\n */\n async getServerHealth(): Promise<Record<string, ServerHealth>>;\n async getServerHealth(serverName: string): Promise<ServerHealth>;\n async getServerHealth(\n serverName?: string,\n ): Promise<ServerHealth | Record<string, ServerHealth>> {\n if (serverName) {\n // Check cache first\n const cacheKey = `health:${serverName}`;\n const cached = this.#serverHealthCache.get(cacheKey);\n\n if (cached !== undefined) {\n if (cached instanceof Error) {\n throw cached;\n }\n return cached;\n }\n\n try {\n const path = API_PATHS.HEALTH_SERVER(serverName);\n const health = await this.#request<ServerHealth>(path);\n\n // Cache successful result\n this.#serverHealthCache.set(cacheKey, health);\n\n return health;\n } catch (error) {\n // Cache certain error types\n if (error instanceof Error) {\n for (const errorType of this.#cacheableExceptions) {\n if (error instanceof errorType) {\n this.#serverHealthCache.set(cacheKey, error);\n break;\n }\n }\n }\n throw error;\n }\n } else {\n const response = await this.#request<HealthResponse>(\n API_PATHS.HEALTH_ALL,\n );\n // Transform array response into Record<string, ServerHealth>\n const healthMap: Record<string, ServerHealth> = {};\n for (const server of response.servers) {\n healthMap[server.name] = server;\n // Cache individual server health for subsequent calls\n const cacheKey = `health:${server.name}`;\n this.#serverHealthCache.set(cacheKey, server);\n }\n return healthMap;\n }\n }\n\n /**\n * Check if a specific server is healthy.\n *\n * @param serverName - The name of the server to check\n *\n * @returns True if the server is healthy, false otherwise\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @example\n * ```typescript\n * if (await client.isServerHealthy('time')) {\n * const time = await client.servers.time.get_current_time();\n * }\n * ```\n */\n async isServerHealthy(serverName: string): Promise<boolean> {\n try {\n const health = await this.getServerHealth(serverName);\n return HealthStatusHelpers.isHealthy(health.status);\n } catch (error) {\n if (error instanceof ServerNotFoundError) {\n return false;\n }\n throw error;\n }\n }\n\n /**\n * Ensure a server is healthy before performing an operation.\n *\n * @param serverName - The name of the server to check\n *\n * @throws {ServerNotFoundError} If the server doesn't exist\n * @throws {ServerUnhealthyError} If the server is not healthy\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n */\n async #ensureServerHealthy(serverName: string): Promise<void> {\n const health = await this.getServerHealth(serverName);\n\n if (!health) {\n throw new ServerNotFoundError(\n `Server '${serverName}' not found`,\n serverName,\n );\n }\n\n if (!HealthStatusHelpers.isHealthy(health.status)) {\n throw new ServerUnhealthyError(\n `Server '${serverName}' is not healthy: ${health.status}`,\n serverName,\n health.status,\n );\n }\n }\n\n /**\n * Get list of healthy servers.\n *\n * @remarks\n * If logging is enabled, warnings are logged for servers that do not exist or are unhealthy.\n *\n * @param servers - List of server names to use for health checking.\n * If not provided, or empty, checks health for all servers.\n *\n * @returns List of server names with 'ok' health status.\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n */\n async #getHealthyServers(servers?: string[]): Promise<string[]> {\n const serverNames = servers?.length ? servers : await this.listServers();\n const healthMap = await this.getServerHealth();\n\n return serverNames.filter((name) => {\n const health = healthMap[name];\n\n if (!health) {\n this.#logger.warn(`Skipping non-existent server '${name}'`);\n return false;\n }\n\n if (!HealthStatusHelpers.isHealthy(health.status)) {\n this.#logger.warn(\n `Skipping unhealthy server '${name}' with status '${health.status}'`,\n );\n return false;\n }\n\n return true;\n });\n }\n\n /**\n * Perform a tool call on a server.\n *\n * @privateRemarks\n * Used internally by:\n * - ToolsNamespace (via dependency injection)\n * - FunctionBuilder (via dependency injection)\n *\n * @param serverName - The name of the server\n * @param toolName - The exact name of the tool\n * @param args - The tool arguments\n *\n * @returns The tool's response\n *\n * @throws {ToolExecutionError} If the tool execution fails\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #performCall(\n serverName: string,\n toolName: string,\n args?: Record<string, unknown>,\n ): Promise<unknown> {\n const path = API_PATHS.TOOL_CALL(serverName, toolName);\n\n try {\n const response = await this.#request<unknown>(path, {\n method: \"POST\",\n body: JSON.stringify(args || {}),\n });\n\n // The mcpd API returns tool results as JSON strings that need parsing\n if (typeof response === \"string\") {\n try {\n return JSON.parse(response);\n } catch {\n // If not valid JSON, return string as-is\n return response;\n }\n }\n\n // Return the response as-is (already parsed or not a string)\n return response;\n } catch (error) {\n // Enrich PipelineError with server/tool context.\n if (error instanceof PipelineError) {\n throw new PipelineError(\n error.message,\n serverName,\n `${serverName}.${toolName}`,\n error.pipelineFlow,\n error.cause as Error | undefined,\n );\n }\n\n if (error instanceof McpdError) {\n throw error;\n }\n\n throw new ToolExecutionError(\n `Failed to execute tool '${toolName}' on server '${serverName}': ${(error as Error).message}`,\n serverName,\n toolName,\n undefined,\n error as Error,\n );\n }\n }\n\n /**\n * Clear the cached agent tools functions.\n * This should be called when the tool schemas might have changed.\n */\n clearAgentToolsCache(): void {\n this.#functionBuilder.clearCache();\n }\n\n /**\n * Clear the server health cache.\n * This forces fresh health checks on the next getServerHealth() or isServerHealthy() call.\n */\n clearServerHealthCache(): void {\n this.#serverHealthCache.clear();\n }\n\n /**\n * Fetch and cache callable functions from all healthy servers.\n *\n * This method queries all healthy servers and creates self-contained, callable functions\n * that can be passed to AI agent frameworks. Each function includes its schema\n * as metadata and handles the MCP communication internally.\n *\n * Unhealthy servers are automatically filtered out and skipped (with optional warnings\n * when logging is enabled) to ensure the method returns quickly without waiting for timeouts.\n *\n * Tool fetches from multiple servers are executed concurrently for optimal performance.\n * Functions are cached indefinitely until explicitly cleared.\n *\n * @returns Array of callable functions with metadata from all healthy servers.\n *\n * @throws {AuthenticationError} If API key was present and authentication fails\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If the request times out\n * @throws {McpdError} If the request fails\n *\n * @internal\n */\n async #agentTools(): Promise<AgentFunction[]> {\n // Return cached functions if available.\n const cachedFunctions = this.#functionBuilder.getCachedFunctions();\n if (cachedFunctions.length > 0) {\n return cachedFunctions;\n }\n\n // Get all healthy servers.\n const healthyServers = await this.#getHealthyServers();\n\n // Fetch tools from all healthy servers in parallel.\n const results = await Promise.allSettled(\n healthyServers.map(async (serverName) => ({\n serverName,\n tools: await this.#getToolsByServer(serverName),\n })),\n );\n\n // Build functions from tool schemas.\n const agentTools: AgentFunction[] = results\n .filter((result) => result.status === \"fulfilled\")\n .flatMap((result) => {\n const { serverName, tools } = result.value;\n return tools.map((toolSchema) =>\n this.#functionBuilder.createFunctionFromSchema(\n toolSchema,\n serverName,\n ),\n );\n });\n\n return agentTools;\n }\n\n /**\n * Generate callable functions for use with AI agent frameworks.\n *\n * This method queries servers to create and cache self-contained, callable functions\n * that can be passed to AI agent frameworks. Each function includes its schema\n * as metadata and handles the MCP communication internally.\n *\n * @remarks\n * This method automatically filters out unhealthy servers by checking their health status before fetching tools.\n * Unhealthy servers are skipped (with optional warnings when logging is enabled) to ensure the\n * method returns quickly without waiting for timeouts on failed servers.\n *\n * Tool fetches from multiple servers are executed concurrently for optimal performance.\n *\n * Generated functions are cached for performance. Once cached, subsequent calls return\n * the cached functions immediately without refetching schemas, regardless of filter parameters.\n * Use {@link clearAgentToolsCache()} to clear the cache, or set refreshCache to true\n * to force regeneration when tool schemas have changed.\n *\n * @param options - Options for output format, server/tool filtering, and cache control\n *\n * @returns Functions in the requested format (array, object, or map).\n * Only includes tools from healthy servers.\n *\n * @throws {ConnectionError} If unable to connect to the mcpd daemon\n * @throws {TimeoutError} If requests to the daemon time out\n * @throws {AuthenticationError} If API key authentication fails\n * @throws {McpdError} If unable to retrieve health status, server list, or generate functions\n *\n * @example\n * ```typescript\n * // Get all tools from all servers (default array format)\n * const tools = await client.getAgentTools();\n * console.log(`Generated ${tools.length} callable tools`);\n *\n * // Get tools from specific servers\n * const tools = await client.getAgentTools({ servers: ['time', 'fetch'] });\n *\n * // Force refresh from cache\n * const freshTools = await client.getAgentTools({ refreshCache: true });\n *\n * // Use with LangChain JS (array format)\n * const langchainTools = await client.getAgentTools({ format: 'array' });\n * const agent = await createOpenAIToolsAgent({ llm, tools: langchainTools, prompt });\n *\n * // Use with Vercel AI SDK (object format) from specific servers\n * const vercelTools = await client.getAgentTools({\n * servers: ['time'],\n * format: 'object'\n * });\n * const result = await generateText({ model, tools: vercelTools, prompt });\n * ```\n */\n async getAgentTools(\n options?: ArrayAgentToolsOptions,\n ): Promise<AgentFunction[]>;\n async getAgentTools(\n options: ObjectAgentToolsOptions,\n ): Promise<Record<string, AgentFunction>>;\n async getAgentTools(\n options: MapAgentToolsOptions,\n ): Promise<Map<string, AgentFunction>>;\n async getAgentTools(\n options: AgentToolsOptions = {},\n ): Promise<\n AgentFunction[] | Record<string, AgentFunction> | Map<string, AgentFunction>\n > {\n const { servers, tools, format = \"array\", refreshCache = false } = options;\n\n // Clear cache and fetch fresh if requested.\n if (refreshCache) this.#functionBuilder.clearCache();\n\n // Fetch or retrieve cached functions from all healthy servers.\n const allTools = await this.#agentTools();\n\n // Filter results based on servers and tools parameters.\n const filteredTools = allTools\n .filter((tool) => !servers || servers.includes(tool._serverName))\n .filter((tool) => !tools || this.#matchesToolFilter(tool, tools));\n\n // Format output as requested.\n const formatters: {\n array: (t: AgentFunctionsArray) => AgentFunctionsArray;\n object: (t: AgentFunctionsArray) => AgentFunctionsRecord;\n map: (t: AgentFunctionsArray) => AgentFunctionsMap;\n } = {\n array: (t) => t,\n object: (t) => Object.fromEntries(t.map((tool) => [tool.name, tool])),\n map: (t) => new Map(t.map((tool) => [tool.name, tool])),\n };\n\n return formatters[format](filteredTools);\n }\n\n /**\n * Check if a tool matches the tool filter.\n *\n * Supports two formats:\n * - Raw tool name: \"get_current_time\" (matches across all servers)\n * - Server-prefixed: \"time__get_current_time\" (matches specific server + tool)\n *\n * @remarks\n * When a filter contains \"__\", it's first checked as server-prefixed (exact match).\n * If that fails, it's checked as a raw tool name. This handles tools whose names\n * contain \"__\" (e.g., \"my__special__tool\").\n *\n * @param tool The tool to match.\n * @param tools List of tool names to match against.\n *\n * @returns True if a match is found in tools, based on the predicate.\n *\n * @internal\n */\n #matchesToolFilter(tool: AgentFunction, tools: string[]): boolean {\n return tools.some((filterItem) => {\n if (filterItem.indexOf(TOOL_SEPARATOR) === -1) {\n // Match against raw tool name\n return filterItem === tool._toolName;\n }\n\n // Try prefixed match first, then fall back to raw match\n return filterItem === tool.name || filterItem === tool._toolName;\n });\n }\n}\n"],"names":["HealthStatus"],"mappings":"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"}
|