UNPKG

mcp-use

Version:

A utility library for integrating Model Context Protocol (MCP) with LangChain, Zod, and related tools. Provides helpers for schema conversion, event streaming, and SDK usage.

144 lines (143 loc) 5.04 kB
import { logger } from '../logging.js'; /** * Base class for MCP connectors. */ export class BaseConnector { client = null; connectionManager = null; toolsCache = null; connected = false; opts; constructor(opts = {}) { this.opts = opts; } /** Disconnect and release resources. */ async disconnect() { if (!this.connected) { logger.debug('Not connected to MCP implementation'); return; } logger.debug('Disconnecting from MCP implementation'); await this.cleanupResources(); this.connected = false; logger.debug('Disconnected from MCP implementation'); } /** Check if the client is connected */ get isClientConnected() { return this.client != null; } /** * Initialise the MCP session **after** `connect()` has succeeded. * * In the SDK, `Client.connect(transport)` automatically performs the * protocol‑level `initialize` handshake, so we only need to cache the list of * tools and expose some server info. */ async initialize(defaultRequestOptions = this.opts.defaultRequestOptions ?? {}) { if (!this.client) { throw new Error('MCP client is not connected'); } logger.debug('Caching server capabilities & tools'); // Cache server capabilities for callers who need them. const capabilities = this.client.getServerCapabilities(); // Fetch and cache tools const listToolsRes = await this.client.listTools(undefined, defaultRequestOptions); this.toolsCache = (listToolsRes.tools ?? []); logger.debug(`Fetched ${this.toolsCache.length} tools from server`); return capabilities; } /** Lazily expose the cached tools list. */ get tools() { if (!this.toolsCache) { throw new Error('MCP client is not initialized; call initialize() first'); } return this.toolsCache; } /** Call a tool on the server. */ async callTool(name, args, options) { if (!this.client) { throw new Error('MCP client is not connected'); } logger.debug(`Calling tool '${name}' with args`, args); const res = await this.client.callTool({ name, arguments: args }, undefined, options); logger.debug(`Tool '${name}' returned`, res); return res; } /** List resources from the server. */ async listResources(options) { if (!this.client) { throw new Error('MCP client is not connected'); } logger.debug('Listing resources'); return await this.client.listResources(undefined, options); } /** Read a resource by URI. */ async readResource(uri, options) { if (!this.client) { throw new Error('MCP client is not connected'); } logger.debug(`Reading resource ${uri}`); const res = await this.client.readResource({ uri }, options); return { content: res.content, mimeType: res.mimeType }; } async listPrompts() { if (!this.client) { throw new Error('MCP client is not connected'); } logger.debug('Listing prompt'); return await this.client.listPrompts(); } async getPrompt(name, args) { if (!this.client) { throw new Error('MCP client is not connected'); } logger.debug(`Getting prompt ${name}`); return await this.client.getPrompt({ name, arguments: args }); } /** Send a raw request through the client. */ async request(method, params = null, options) { if (!this.client) { throw new Error('MCP client is not connected'); } logger.debug(`Sending raw request '${method}' with params`, params); return await this.client.request({ method, params: params ?? {} }, undefined, options); } /** * Helper to tear down the client & connection manager safely. */ async cleanupResources() { const issues = []; if (this.client) { try { if (typeof this.client.close === 'function') { await this.client.close(); } } catch (e) { const msg = `Error closing client: ${e}`; logger.warn(msg); issues.push(msg); } finally { this.client = null; } } if (this.connectionManager) { try { await this.connectionManager.stop(); } catch (e) { const msg = `Error stopping connection manager: ${e}`; logger.warn(msg); issues.push(msg); } finally { this.connectionManager = null; } } this.toolsCache = null; if (issues.length) { logger.warn(`Resource cleanup finished with ${issues.length} issue(s)`); } } }