mcp-client.service.ts•2.22 kB
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import * as path from 'path';
@Injectable()
export class McpClientService implements OnModuleInit, OnModuleDestroy {
private client: Client;
private transport: StdioClientTransport;
async onModuleInit() {
await this.connect();
}
async onModuleDestroy() {
await this.disconnect();
}
private async connect() {
try {
// 启动 MCP Server 进程并创建 stdio transport
const serverPath = path.join(process.cwd(), 'dist', 'mcp-standalone.js');
this.transport = new StdioClientTransport({
command: 'node',
args: [serverPath],
env: process.env as Record<string, string>,
});
// 创建 MCP Client
this.client = new Client(
{
name: 'chat-api-client',
version: '1.0.0',
},
{
capabilities: {},
}
);
// 连接到 MCP Server
await this.client.connect(this.transport);
console.log('✅ MCP Client connected to MCP Server');
} catch (error) {
console.error('Failed to connect to MCP Server:', error);
throw error;
}
}
private async disconnect() {
try {
if (this.client) {
await this.client.close();
}
console.log('MCP Client disconnected');
} catch (error) {
console.error('Error disconnecting MCP Client:', error);
}
}
async callTool(name: string, args: any): Promise<any> {
try {
const result = await this.client.callTool({
name,
arguments: args,
});
return result;
} catch (error: any) {
console.error('MCP Tool call error:', error);
throw new Error(`MCP 工具调用失败: ${error.message}`);
}
}
async listTools(): Promise<any> {
try {
const result = await this.client.listTools();
return result.tools;
} catch (error: any) {
console.error('MCP List tools error:', error);
throw new Error(`获取工具列表失败: ${error.message}`);
}
}
}