{"version":3,"file":"index.cjs","names":["MastraBase","MastraError","RegisteredLogger"],"sources":["../../src/mcp/index.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport slugify from '@sindresorhus/slugify';\nimport type { ToolsInput } from '../agent';\nimport { MastraBase } from '../base';\nimport { MastraError } from '../error';\nimport { RegisteredLogger } from '../logger';\nimport type { Mastra } from '../mastra';\nimport type { RequestContext } from '../request-context';\nimport type { InternalCoreTool, MCPToolType } from '../tools';\nimport type {\n  MCPServerConfig,\n  MCPServerHonoSSEOptions,\n  MCPServerHTTPOptions,\n  MCPServerSSEOptions,\n  PackageInfo,\n  RemoteInfo,\n  Repository,\n  ServerDetailInfo,\n  ServerInfo,\n} from './types';\nexport * from './types';\nexport type { MCPToolType } from '../tools';\n\n/**\n * Abstract base class for MCP server implementations.\n * This provides a common interface and shared functionality for all MCP servers\n * that can be registered with Mastra, including handling of server metadata.\n */\nexport abstract class MCPServerBase<TId extends string = string> extends MastraBase {\n  /** Tracks if the server ID has been definitively set. */\n  private idWasSet = false;\n  /** The display name of the MCP server. */\n  public readonly name: string;\n  /** The semantic version of the MCP server. */\n  public readonly version: string;\n  /** Internal storage for the server's unique ID. */\n  private _id: TId;\n  /** A description of what the MCP server does. */\n  public readonly description?: string;\n  /** Optional instructions describing how to use the server and its features. */\n  public readonly instructions?: string;\n  /** Repository information for the server's source code. */\n  public readonly repository?: Repository;\n  /** The release date of this server version (ISO 8601 string). */\n  public readonly releaseDate: string;\n  /** Indicates if this version is the latest available. */\n  public readonly isLatest: boolean;\n  /** The canonical packaging format (e.g., \"npm\", \"docker\"), if applicable. */\n  public readonly packageCanonical?: MCPServerConfig['packageCanonical'];\n  /** Information about installable packages for this server. */\n  public readonly packages?: PackageInfo[];\n  /** Information about remote access points for this server. */\n  public readonly remotes?: RemoteInfo[];\n  /** The tools registered with and converted by this MCP server. */\n  public convertedTools: Record<string, InternalCoreTool>;\n  /** Reference to the Mastra instance if this server is registered with one. */\n  public mastra: Mastra | undefined;\n  /** Agents to be exposed as tools. */\n  protected readonly agents?: MCPServerConfig['agents'];\n  /** Workflows to be exposed as tools. */\n  protected readonly workflows?: MCPServerConfig['workflows'];\n  /** Original tools configuration for re-conversion when Mastra instance is registered. Mutable to support dynamic tool management. */\n  protected originalTools: ToolsInput;\n\n  /**\n   * Public getter for the server's unique ID.\n   * The ID is set at construction or by Mastra and is read-only afterwards.\n   */\n  public get id(): TId {\n    return this._id;\n  }\n\n  /**\n   * Gets a read-only view of the registered tools.\n   * @returns A readonly record of converted tools.\n   */\n  tools(): Readonly<Record<string, InternalCoreTool>> {\n    return this.convertedTools;\n  }\n\n  /**\n   * Sets the server's unique ID. This method is typically called by Mastra when\n   * registering the server, using the key provided in the Mastra configuration.\n   * It ensures the ID is set only once.\n   * If an ID was already provided in the MCPServerConfig, this method will be a no-op.\n   * @param id The unique ID to assign to the server.\n   */\n  setId(id: TId) {\n    if (this.idWasSet) {\n      return;\n    }\n    this._id = id;\n    this.idWasSet = true;\n  }\n\n  /**\n   * Abstract method to convert and validate tool definitions provided to the server.\n   * This method will also handle agents passed in the config.\n   * @param tools Tool definitions to convert.\n   * @param agents Agent definitions to convert to tools.\n   * @param workflows Workflow definitions to convert to tools.\n   * @returns A record of converted and validated tools.\n   */\n  public abstract convertTools(\n    tools: ToolsInput,\n    agents?: MCPServerConfig['agents'],\n    workflows?: MCPServerConfig['workflows'],\n  ): Record<string, InternalCoreTool>;\n\n  /**\n   * Internal method used by Mastra to register itself with the server.\n   * @param mastra The Mastra instance.\n   * @internal\n   */\n  __registerMastra(mastra: Mastra): void {\n    this.mastra = mastra;\n    // Re-convert tools now that we have the Mastra instance to populate MCP tools execute with mastra instance\n    this.convertedTools = this.convertTools(this.originalTools, this.agents, this.workflows);\n\n    // Auto-register tools with the Mastra instance\n    if (this.originalTools && typeof this.originalTools === 'object') {\n      Object.entries(this.originalTools).forEach(([key, tool]) => {\n        try {\n          // Only add tools that have an id property (ToolAction type)\n          if (tool && typeof tool === 'object' && 'id' in tool) {\n            // Use tool's intrinsic ID to avoid collisions across MCP servers\n            const toolKey = typeof (tool as any).id === 'string' ? (tool as any).id : key;\n            mastra.addTool(tool as any, toolKey);\n          }\n        } catch (error) {\n          // Tool might already be registered, that's okay\n          if (!(error instanceof MastraError) || error.id !== 'MASTRA_ADD_TOOL_DUPLICATE_KEY') {\n            throw error;\n          }\n        }\n      });\n    }\n\n    // Auto-register agents with the Mastra instance\n    if (this.agents && typeof this.agents === 'object') {\n      Object.entries(this.agents).forEach(([key, agent]) => {\n        try {\n          mastra.addAgent(agent, key);\n        } catch (error) {\n          // Agent might already be registered, that's okay\n          if (!(error instanceof MastraError) || error.id !== 'MASTRA_ADD_AGENT_DUPLICATE_KEY') {\n            throw error;\n          }\n        }\n      });\n    }\n\n    // Auto-register workflows with the Mastra instance\n    if (this.workflows && typeof this.workflows === 'object') {\n      Object.entries(this.workflows).forEach(([key, workflow]) => {\n        try {\n          mastra.addWorkflow(workflow, key);\n        } catch (error) {\n          // Workflow might already be registered, that's okay\n          if (!(error instanceof MastraError) || error.id !== 'MASTRA_ADD_WORKFLOW_DUPLICATE_KEY') {\n            throw error;\n          }\n        }\n      });\n    }\n  }\n\n  /**\n   * Constructor for the MCPServerBase.\n   * @param config Configuration options for the MCP server, including metadata.\n   */\n  constructor(config: MCPServerConfig<TId>) {\n    super({ component: RegisteredLogger.MCP_SERVER, name: config.name });\n    this.name = config.name;\n    this.version = config.version;\n\n    // If user does not provide an ID, we will use the key from the Mastra config, but if user does not pass MCPServer\n    // to Mastra, we will generate a random UUID as a backup.\n    if (config.id) {\n      this._id = slugify(config.id) as TId;\n      this.idWasSet = true;\n    } else {\n      this._id = (this.mastra?.generateId() || randomUUID()) as TId;\n    }\n\n    this.description = config.description;\n    this.instructions = config.instructions;\n    this.repository = config.repository;\n    this.releaseDate = config.releaseDate || new Date().toISOString();\n    this.isLatest = config.isLatest === undefined ? true : config.isLatest;\n    this.packageCanonical = config.packageCanonical;\n    this.packages = config.packages;\n    this.remotes = config.remotes;\n    this.agents = config.agents;\n    this.workflows = config.workflows;\n    this.originalTools = config.tools;\n    this.convertedTools = this.convertTools(config.tools, config.agents, config.workflows);\n  }\n\n  /**\n   * Start the MCP server using stdio transport\n   * This is typically used for Windsurf integration\n   */\n  public abstract startStdio(): Promise<void>;\n\n  /**\n   * Start the MCP server using SSE transport\n   * This is typically used for web integration\n   * @param options Options for the SSE transport\n   */\n  public abstract startSSE(options: MCPServerSSEOptions): Promise<void>;\n\n  /**\n   * Start the MCP server using Hono SSE transport\n   * Used for Hono servers\n   * @param options Options for the SSE transport\n   */\n  public abstract startHonoSSE(options: MCPServerHonoSSEOptions): Promise<Response | undefined>;\n\n  /**\n   * Start the MCP server using HTTP transport\n   * @param options Options for the HTTP transport\n   */\n  public abstract startHTTP(options: MCPServerHTTPOptions): Promise<void>;\n\n  /**\n   * Close the MCP server and all its connections\n   */\n  public abstract close(): Promise<void>;\n\n  /**\n   * Gets the basic information about the server, conforming to the MCP Registry 'Server' schema.\n   * This information is suitable for listing multiple servers.\n   * @returns ServerInfo object containing basic server metadata.\n   */\n  public abstract getServerInfo(): ServerInfo;\n\n  /**\n   * Gets detailed information about the server, conforming to the MCP Registry 'ServerDetail' schema.\n   * This includes all information from `getServerInfo` plus package and remote details.\n   * @returns ServerDetailInfo object containing comprehensive server metadata.\n   */\n  public abstract getServerDetail(): ServerDetailInfo;\n\n  /**\n   * Gets a list of tools provided by this MCP server, including their schemas.\n   * @returns An object containing an array of tool information.\n   */\n  public abstract getToolListInfo(requestContext?: RequestContext):\n    | {\n        tools: Array<{\n          name: string;\n          description?: string;\n          inputSchema: any;\n          outputSchema?: any;\n          toolType?: MCPToolType;\n          _meta?: Record<string, unknown>;\n        }>;\n      }\n    | Promise<{\n        tools: Array<{\n          name: string;\n          description?: string;\n          inputSchema: any;\n          outputSchema?: any;\n          toolType?: MCPToolType;\n          _meta?: Record<string, unknown>;\n        }>;\n      }>;\n\n  /**\n   * Gets information for a specific tool provided by this MCP server.\n   * @param toolId The ID/name of the tool to retrieve.\n   * @returns Tool information (name, description, inputSchema) or undefined if not found.\n   */\n  public abstract getToolInfo(toolId: string):\n    | {\n        name: string;\n        description?: string;\n        inputSchema: any;\n        outputSchema?: any;\n        toolType?: MCPToolType;\n        _meta?: Record<string, unknown>;\n      }\n    | undefined\n    | Promise<\n        | {\n            name: string;\n            description?: string;\n            inputSchema: any;\n            outputSchema?: any;\n            toolType?: MCPToolType;\n            _meta?: Record<string, unknown>;\n          }\n        | undefined\n      >;\n\n  /**\n   * Executes a specific tool provided by this MCP server.\n   * @param toolId The ID/name of the tool to execute.\n   * @param args The arguments to pass to the tool's execute function.\n   * @param executionContext Optional context for the tool execution (e.g., messages, toolCallId).\n   * @returns A promise that resolves to the result of the tool execution.\n   * @throws Error if the tool is not found, or if execution fails.\n   */\n  public abstract executeTool(\n    toolId: string,\n    args: any,\n    executionContext?: { messages?: any[]; toolCallId?: string; requestContext?: RequestContext },\n  ): Promise<any>;\n\n  /**\n   * Reads the content of a resource by URI.\n   * @param uri The resource URI to read (e.g. `ui://weather/dashboard`).\n   * @returns A promise resolving to the resource content.\n   */\n  public abstract readResource(\n    uri: string,\n  ): Promise<{ contents: Array<{ uri: string; text?: string; blob?: string }> }>;\n\n  /**\n   * Lists all resources available on this MCP server.\n   * @returns A promise resolving to the list of resources.\n   */\n  public abstract listResources(): Promise<{\n    resources: Array<{\n      uri: string;\n      name: string;\n      description?: string;\n      mimeType?: string;\n      _meta?: Record<string, unknown>;\n    }>;\n  }>;\n}\n"],"mappings":";;;;;;;;;;;;;;AA4BA,IAAsB,gBAAtB,cAAyEA,aAAAA,WAAW;;CAElF,WAAmB;;CAEnB;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;;;;;CAMA,IAAW,KAAU;EACnB,OAAO,KAAK;CACd;;;;;CAMA,QAAoD;EAClD,OAAO,KAAK;CACd;;;;;;;;CASA,MAAM,IAAS;EACb,IAAI,KAAK,UACP;EAEF,KAAK,MAAM;EACX,KAAK,WAAW;CAClB;;;;;;CAqBA,iBAAiB,QAAsB;EACrC,KAAK,SAAS;EAEd,KAAK,iBAAiB,KAAK,aAAa,KAAK,eAAe,KAAK,QAAQ,KAAK,SAAS;EAGvF,IAAI,KAAK,iBAAiB,OAAO,KAAK,kBAAkB,UACtD,OAAO,QAAQ,KAAK,aAAa,CAAC,CAAC,SAAS,CAAC,KAAK,UAAU;GAC1D,IAAI;IAEF,IAAI,QAAQ,OAAO,SAAS,YAAY,QAAQ,MAAM;KAEpD,MAAM,UAAU,OAAQ,KAAa,OAAO,WAAY,KAAa,KAAK;KAC1E,OAAO,QAAQ,MAAa,OAAO;IACrC;GACF,SAAS,OAAO;IAEd,IAAI,EAAE,iBAAiBC,cAAAA,gBAAgB,MAAM,OAAO,iCAClD,MAAM;GAEV;EACF,CAAC;EAIH,IAAI,KAAK,UAAU,OAAO,KAAK,WAAW,UACxC,OAAO,QAAQ,KAAK,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,WAAW;GACpD,IAAI;IACF,OAAO,SAAS,OAAO,GAAG;GAC5B,SAAS,OAAO;IAEd,IAAI,EAAE,iBAAiBA,cAAAA,gBAAgB,MAAM,OAAO,kCAClD,MAAM;GAEV;EACF,CAAC;EAIH,IAAI,KAAK,aAAa,OAAO,KAAK,cAAc,UAC9C,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,SAAS,CAAC,KAAK,cAAc;GAC1D,IAAI;IACF,OAAO,YAAY,UAAU,GAAG;GAClC,SAAS,OAAO;IAEd,IAAI,EAAE,iBAAiBA,cAAAA,gBAAgB,MAAM,OAAO,qCAClD,MAAM;GAEV;EACF,CAAC;CAEL;;;;;CAMA,YAAY,QAA8B;EACxC,MAAM;GAAE,WAAWC,eAAAA,iBAAiB;GAAY,MAAM,OAAO;EAAK,CAAC;EACnE,KAAK,OAAO,OAAO;EACnB,KAAK,UAAU,OAAO;EAItB,IAAI,OAAO,IAAI;GACb,KAAK,OAAA,GAAA,sBAAA,QAAA,CAAc,OAAO,EAAE;GAC5B,KAAK,WAAW;EAClB,OACE,KAAK,MAAO,KAAK,QAAQ,WAAW,MAAA,GAAA,OAAA,WAAA,CAAgB;EAGtD,KAAK,cAAc,OAAO;EAC1B,KAAK,eAAe,OAAO;EAC3B,KAAK,aAAa,OAAO;EACzB,KAAK,cAAc,OAAO,gCAAe,IAAI,KAAK,EAAA,CAAE,YAAY;EAChE,KAAK,WAAW,OAAO,aAAa,KAAA,IAAY,OAAO,OAAO;EAC9D,KAAK,mBAAmB,OAAO;EAC/B,KAAK,WAAW,OAAO;EACvB,KAAK,UAAU,OAAO;EACtB,KAAK,SAAS,OAAO;EACrB,KAAK,YAAY,OAAO;EACxB,KAAK,gBAAgB,OAAO;EAC5B,KAAK,iBAAiB,KAAK,aAAa,OAAO,OAAO,OAAO,QAAQ,OAAO,SAAS;CACvF;AAwIF"}