Files
FastGPT/packages/service/core/app/mcp.ts
Theresa 2d3117c5da feat: update ESLint config with @typescript-eslint/consistent-type-imports (#4746)
* update: Add type

* fix: update import statement for NextApiRequest type

* fix: update imports to use type for LexicalEditor and EditorState

* Refactor imports to use 'import type' for type-only imports across multiple files

- Updated imports in various components and API files to use 'import type' for better clarity and to optimize TypeScript's type checking.
- Ensured consistent usage of type imports in files related to chat, dataset, workflow, and user management.
- Improved code readability and maintainability by distinguishing between value and type imports.

* refactor: remove old ESLint configuration and add new rules

- Deleted the old ESLint configuration file from the app project.
- Added a new ESLint configuration file with updated rules and settings.
- Changed imports to use type-only imports in various files for better clarity and performance.
- Updated TypeScript configuration to remove unnecessary options.
- Added an ESLint ignore file to exclude build and dependency directories from linting.

* fix: update imports to use 'import type' for type-only imports in schema files
2025-05-06 17:33:09 +08:00

95 lines
2.6 KiB
TypeScript

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
import { type ToolType } from '@fastgpt/global/core/app/type';
import { addLog } from '../../common/system/log';
import { retryFn } from '@fastgpt/global/common/system/utils';
export class MCPClient {
private client: Client;
private url: string;
constructor(config: { url: string }) {
this.url = config.url;
this.client = new Client({
name: 'FastGPT-MCP-client',
version: '1.0.0'
});
}
private async getConnection(): Promise<Client> {
try {
const transport = new StreamableHTTPClientTransport(new URL(this.url));
await this.client.connect(transport);
return this.client;
} catch (error) {
await this.client.connect(new SSEClientTransport(new URL(this.url)));
return this.client;
}
}
// 内部方法:关闭连接
private async closeConnection() {
try {
await retryFn(() => this.client.close(), 3);
} catch (error) {
addLog.error('[MCP Client] Failed to close connection:', error);
}
}
/**
* Get available tools list
* @returns List of tools
*/
public async getTools(): Promise<ToolType[]> {
try {
const client = await this.getConnection();
const response = await client.listTools();
if (!Array.isArray(response.tools)) {
return Promise.reject('[MCP Client] Get tools response is not an array');
}
const tools = response.tools.map((tool) => ({
name: tool.name,
description: tool.description || '',
inputSchema: tool.inputSchema || {
type: 'object',
properties: {}
}
}));
// @ts-ignore
return tools;
} catch (error) {
addLog.error('[MCP Client] Failed to get tools:', error);
return Promise.reject(error);
} finally {
await this.closeConnection();
}
}
/**
* Call tool
* @param toolName Tool name
* @param params Parameters
* @returns Tool execution result
*/
public async toolCall(toolName: string, params: Record<string, any>): Promise<any> {
try {
const client = await this.getConnection();
addLog.debug(`[MCP Client] Call tool: ${toolName}`, params);
return await client.callTool({
name: toolName,
arguments: params
});
} catch (error) {
addLog.error(`[MCP Client] Failed to call tool ${toolName}:`, error);
return Promise.reject(error);
} finally {
await this.closeConnection();
}
}
}