@lobehub/chat
Version:
Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.
96 lines (83 loc) • 3.12 kB
text/typescript
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import {
StdioClientTransport,
getDefaultEnvironment,
} from '@modelcontextprotocol/sdk/client/stdio.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.d.ts';
import type { Progress } from '@modelcontextprotocol/sdk/types.js';
import debug from 'debug';
import { MCPClientParams, McpTool } from './types';
const log = debug('lobe-mcp:client');
export class MCPClient {
private mcp: Client;
private transport: Transport;
constructor(params: MCPClientParams) {
log('Creating MCPClient with connection: %O', params);
this.mcp = new Client({ name: 'lobehub-mcp-client', version: '1.0.0' });
switch (params.type) {
case 'http': {
log('Using HTTP transport with url: %s', params.url);
this.transport = new StreamableHTTPClientTransport(new URL(params.url));
break;
}
case 'stdio': {
log('Using Stdio transport with command: %s and args: %O', params.command, params.args);
this.transport = new StdioClientTransport({
args: params.args,
command: params.command,
env: {
...getDefaultEnvironment(),
...params.env,
},
});
break;
}
default: {
const err = new Error(`Unsupported MCP connection type: ${(params as any).type}`);
log('Error creating client: %O', err);
throw err;
}
}
}
async initialize(options: { onProgress?: (progress: Progress) => void } = {}) {
log('Initializing MCP connection...');
try {
await this.mcp.connect(this.transport, { onprogress: options.onProgress });
log('MCP connection initialized.');
} catch (e) {
if ((e as any).code === -32_000) {
throw new Error('Fail to connecting MCP Server, please check your configuration.');
}
log('MCP connection failed:', e);
throw e;
}
}
async disconnect() {
log('Disconnecting MCP connection...');
// Assuming the mcp client has a disconnect method
if (this.mcp && typeof (this.mcp as any).disconnect === 'function') {
await (this.mcp as any).disconnect();
log('MCP connection disconnected.');
} else {
log('MCP client does not have a disconnect method or is not initialized.');
// Depending on the transport, we might need specific cleanup
if (this.transport && typeof (this.transport as any).close === 'function') {
(this.transport as any).close();
log('Transport closed.');
}
}
}
async listTools() {
log('Listing tools...');
const { tools } = await this.mcp.listTools();
log('Listed tools: %O', tools);
return tools as McpTool[];
}
async callTool(toolName: string, args: any) {
log('Calling tool: %s with args: %O', toolName, args);
const result = await this.mcp.callTool({ arguments: args, name: toolName });
log('Tool call result: %O', result);
return result;
}
}