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.

125 lines (124 loc) 4.32 kB
import fs from 'node:fs'; import path from 'node:path'; import { createConnectorFromConfig, loadConfigFile } from './config.js'; import { logger } from './logging.js'; import { MCPSession } from './session.js'; export class MCPClient { config = {}; sessions = {}; activeSessions = []; constructor(config) { if (config) { if (typeof config === 'string') { this.config = loadConfigFile(config); } else { this.config = config; } } } static fromDict(cfg) { return new MCPClient(cfg); } static fromConfigFile(path) { return new MCPClient(loadConfigFile(path)); } addServer(name, serverConfig) { this.config.mcpServers = this.config.mcpServers || {}; this.config.mcpServers[name] = serverConfig; } removeServer(name) { if (this.config.mcpServers?.[name]) { delete this.config.mcpServers[name]; this.activeSessions = this.activeSessions.filter(n => n !== name); } } getServerNames() { return Object.keys(this.config.mcpServers ?? {}); } saveConfig(filepath) { const dir = path.dirname(filepath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } fs.writeFileSync(filepath, JSON.stringify(this.config, null, 2), 'utf-8'); } async createSession(serverName, autoInitialize = true) { const servers = this.config.mcpServers ?? {}; if (Object.keys(servers).length === 0) { throw new Error('No MCP servers defined in config'); } if (!servers[serverName]) { throw new Error(`Server '${serverName}' not found in config`); } const connector = createConnectorFromConfig(servers[serverName]); const session = new MCPSession(connector); if (autoInitialize) { await session.initialize(); } this.sessions[serverName] = session; if (!this.activeSessions.includes(serverName)) { this.activeSessions.push(serverName); } return session; } async createAllSessions(autoInitialize = true) { const servers = this.config.mcpServers ?? {}; if (Object.keys(servers).length === 0) { throw new Error('No MCP servers defined in config'); } for (const name of Object.keys(servers)) { await this.createSession(name, autoInitialize); } return this.sessions; } getSession(serverName) { const session = this.sessions[serverName]; if (!session) { throw new Error(`No session exists for server '${serverName}'`); } return session; } getAllActiveSessions() { return Object.fromEntries(this.activeSessions.map(n => [n, this.sessions[n]])); } async closeSession(serverName) { const session = this.sessions[serverName]; if (!session) { logger.warn(`No session exists for server ${serverName}, nothing to close`); return; } try { logger.debug(`Closing session for server ${serverName}`); await session.disconnect(); } catch (e) { logger.error(`Error closing session for server '${serverName}': ${e}`); } finally { delete this.sessions[serverName]; this.activeSessions = this.activeSessions.filter(n => n !== serverName); } } async closeAllSessions() { const serverNames = Object.keys(this.sessions); const errors = []; for (const serverName of serverNames) { try { logger.debug(`Closing session for server ${serverName}`); await this.closeSession(serverName); } catch (e) { const errorMsg = `Failed to close session for server '${serverName}': ${e}`; logger.error(errorMsg); errors.push(errorMsg); } } if (errors.length) { logger.error(`Encountered ${errors.length} errors while closing sessions`); } else { logger.debug('All sessions closed successfully'); } } }