| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- "use server";
- import {
- createClient,
- executeRequest,
- listTools,
- removeClient,
- } from "./client";
- import { MCPClientLogger } from "./logger";
- import {
- DEFAULT_MCP_CONFIG,
- McpClientData,
- McpConfigData,
- McpRequestMessage,
- ServerConfig,
- ServerStatusResponse,
- } from "./types";
- import fs from "fs/promises";
- import path from "path";
- const logger = new MCPClientLogger("MCP Actions");
- const CONFIG_PATH = path.join(process.cwd(), "app/mcp/mcp_config.json");
- const clientsMap = new Map<string, McpClientData>();
- // 获取客户端状态
- export async function getClientStatus(
- clientId: string,
- ): Promise<ServerStatusResponse> {
- const status = clientsMap.get(clientId);
- const config = await getMcpConfigFromFile();
- const serverConfig = config.mcpServers[clientId];
- // 如果配置中不存在该服务器
- if (!serverConfig) {
- return { status: "undefined", errorMsg: null };
- }
- // 如果服务器配置为暂停状态
- if (serverConfig.status === "paused") {
- return { status: "paused", errorMsg: null };
- }
- // 如果 clientsMap 中没有记录
- if (!status) {
- return { status: "undefined", errorMsg: null };
- }
- // 如果有错误
- if (status.errorMsg) {
- return { status: "error", errorMsg: status.errorMsg };
- }
- // 如果客户端正常运行
- if (status.client) {
- return { status: "active", errorMsg: null };
- }
- // 如果客户端不存在
- return { status: "error", errorMsg: "Client not found" };
- }
- // 获取客户端工具
- export async function getClientTools(clientId: string) {
- return clientsMap.get(clientId)?.tools ?? null;
- }
- // 获取可用客户端数量
- export async function getAvailableClientsCount() {
- let count = 0;
- clientsMap.forEach((map) => !map.errorMsg && count++);
- return count;
- }
- // 获取所有客户端工具
- export async function getAllTools() {
- const result = [];
- for (const [clientId, status] of clientsMap.entries()) {
- result.push({
- clientId,
- tools: status.tools,
- });
- }
- return result;
- }
- // 初始化单个客户端
- async function initializeSingleClient(
- clientId: string,
- serverConfig: ServerConfig,
- ) {
- // 如果服务器状态是暂停,则不初始化
- if (serverConfig.status === "paused") {
- logger.info(`Skipping initialization for paused client [${clientId}]`);
- return;
- }
- logger.info(`Initializing client [${clientId}]...`);
- try {
- const client = await createClient(clientId, serverConfig);
- const tools = await listTools(client);
- clientsMap.set(clientId, { client, tools, errorMsg: null });
- logger.success(`Client [${clientId}] initialized successfully`);
- } catch (error) {
- clientsMap.set(clientId, {
- client: null,
- tools: null,
- errorMsg: error instanceof Error ? error.message : String(error),
- });
- logger.error(`Failed to initialize client [${clientId}]: ${error}`);
- }
- }
- // 初始化系统
- export async function initializeMcpSystem() {
- logger.info("MCP Actions starting...");
- try {
- const config = await getMcpConfigFromFile();
- // 初始化所有客户端
- for (const [clientId, serverConfig] of Object.entries(config.mcpServers)) {
- await initializeSingleClient(clientId, serverConfig);
- }
- return config;
- } catch (error) {
- logger.error(`Failed to initialize MCP system: ${error}`);
- throw error;
- }
- }
- // 添加服务器
- export async function addMcpServer(clientId: string, config: ServerConfig) {
- try {
- const currentConfig = await getMcpConfigFromFile();
- const newConfig = {
- ...currentConfig,
- mcpServers: {
- ...currentConfig.mcpServers,
- [clientId]: config,
- },
- };
- await updateMcpConfig(newConfig);
- // 只初始化新添加的服务器
- await initializeSingleClient(clientId, config);
- return newConfig;
- } catch (error) {
- logger.error(`Failed to add server [${clientId}]: ${error}`);
- throw error;
- }
- }
- // 暂停服务器
- export async function pauseMcpServer(clientId: string) {
- try {
- const currentConfig = await getMcpConfigFromFile();
- const serverConfig = currentConfig.mcpServers[clientId];
- if (!serverConfig) {
- throw new Error(`Server ${clientId} not found`);
- }
- // 先更新配置
- const newConfig: McpConfigData = {
- ...currentConfig,
- mcpServers: {
- ...currentConfig.mcpServers,
- [clientId]: {
- ...serverConfig,
- status: "paused" as const,
- },
- },
- };
- await updateMcpConfig(newConfig);
- // 然后关闭客户端
- const client = clientsMap.get(clientId);
- if (client?.client) {
- await removeClient(client.client);
- }
- clientsMap.delete(clientId);
- return newConfig;
- } catch (error) {
- logger.error(`Failed to pause server [${clientId}]: ${error}`);
- throw error;
- }
- }
- // 恢复服务器
- export async function resumeMcpServer(clientId: string): Promise<boolean> {
- try {
- const currentConfig = await getMcpConfigFromFile();
- const serverConfig = currentConfig.mcpServers[clientId];
- if (!serverConfig) {
- throw new Error(`Server ${clientId} not found`);
- }
- // 先尝试初始化客户端
- logger.info(`Trying to initialize client [${clientId}]...`);
- try {
- const client = await createClient(clientId, serverConfig);
- const tools = await listTools(client);
- clientsMap.set(clientId, { client, tools, errorMsg: null });
- logger.success(`Client [${clientId}] initialized successfully`);
- // 初始化成功后更新配置
- const newConfig: McpConfigData = {
- ...currentConfig,
- mcpServers: {
- ...currentConfig.mcpServers,
- [clientId]: {
- ...serverConfig,
- status: "active" as const,
- },
- },
- };
- await updateMcpConfig(newConfig);
- // 再次确认状态
- const status = await getClientStatus(clientId);
- return status.status === "active";
- } catch (error) {
- const currentConfig = await getMcpConfigFromFile();
- const serverConfig = currentConfig.mcpServers[clientId];
- // 如果配置中存在该服务器,则更新其状态为 error
- if (serverConfig) {
- serverConfig.status = "error";
- await updateMcpConfig(currentConfig);
- }
- // 初始化失败
- clientsMap.set(clientId, {
- client: null,
- tools: null,
- errorMsg: error instanceof Error ? error.message : String(error),
- });
- logger.error(`Failed to initialize client [${clientId}]: ${error}`);
- return false;
- }
- } catch (error) {
- logger.error(`Failed to resume server [${clientId}]: ${error}`);
- throw error;
- }
- }
- // 移除服务器
- export async function removeMcpServer(clientId: string) {
- try {
- const currentConfig = await getMcpConfigFromFile();
- const { [clientId]: _, ...rest } = currentConfig.mcpServers;
- const newConfig = {
- ...currentConfig,
- mcpServers: rest,
- };
- await updateMcpConfig(newConfig);
- // 关闭并移除客户端
- const client = clientsMap.get(clientId);
- if (client?.client) {
- await removeClient(client.client);
- }
- clientsMap.delete(clientId);
- return newConfig;
- } catch (error) {
- logger.error(`Failed to remove server [${clientId}]: ${error}`);
- throw error;
- }
- }
- // 重启所有客户端
- export async function restartAllClients() {
- logger.info("Restarting all clients...");
- try {
- // 关闭所有客户端
- for (const client of clientsMap.values()) {
- if (client.client) {
- await removeClient(client.client);
- }
- }
- // 清空状态
- clientsMap.clear();
- // 重新初始化
- const config = await getMcpConfigFromFile();
- for (const [clientId, serverConfig] of Object.entries(config.mcpServers)) {
- await initializeSingleClient(clientId, serverConfig);
- }
- return config;
- } catch (error) {
- logger.error(`Failed to restart clients: ${error}`);
- throw error;
- }
- }
- // 执行 MCP 请求
- export async function executeMcpAction(
- clientId: string,
- request: McpRequestMessage,
- ) {
- try {
- const client = clientsMap.get(clientId);
- if (!client?.client) {
- throw new Error(`Client ${clientId} not found`);
- }
- logger.info(`Executing request for [${clientId}]`);
- return await executeRequest(client.client, request);
- } catch (error) {
- logger.error(`Failed to execute request for [${clientId}]: ${error}`);
- throw error;
- }
- }
- // 获取 MCP 配置文件
- export async function getMcpConfigFromFile(): Promise<McpConfigData> {
- try {
- const configStr = await fs.readFile(CONFIG_PATH, "utf-8");
- return JSON.parse(configStr);
- } catch (error) {
- logger.error(`Failed to load MCP config, using default config: ${error}`);
- return DEFAULT_MCP_CONFIG;
- }
- }
- // 更新 MCP 配置文件
- async function updateMcpConfig(config: McpConfigData): Promise<void> {
- try {
- await fs.writeFile(CONFIG_PATH, JSON.stringify(config, null, 2));
- } catch (error) {
- throw error;
- }
- }
- // 重新初始化单个客户端
- export async function reinitializeClient(clientId: string) {
- const config = await getMcpConfigFromFile();
- const serverConfig = config.mcpServers[clientId];
- if (!serverConfig) {
- throw new Error(`Server config not found for client ${clientId}`);
- }
- await initializeSingleClient(clientId, serverConfig);
- }
|