feat: MCP market

This commit is contained in:
Kadxy
2025-01-09 19:51:01 +08:00
parent 0c14ce6417
commit 7d51bfd42e
14 changed files with 1607 additions and 30 deletions

View File

@@ -7,15 +7,16 @@ import {
Primitive,
} from "./client";
import { MCPClientLogger } from "./logger";
import conf from "./mcp_config.json";
import { McpRequestMessage } from "./types";
import { McpRequestMessage, McpConfig, ServerConfig } from "./types";
import fs from "fs/promises";
import path from "path";
const logger = new MCPClientLogger("MCP Actions");
// Use Map to store all clients
const clientsMap = new Map<
string,
{ client: Client; primitives: Primitive[] }
{ client: Client | null; primitives: Primitive[]; errorMsg: string | null }
>();
// Whether initialized
@@ -24,27 +25,76 @@ let initialized = false;
// Store failed clients
let errorClients: string[] = [];
const CONFIG_PATH = path.join(process.cwd(), "app/mcp/mcp_config.json");
// 获取 MCP 配置
export async function getMcpConfig(): Promise<McpConfig> {
try {
const configStr = await fs.readFile(CONFIG_PATH, "utf-8");
return JSON.parse(configStr);
} catch (error) {
console.error("Failed to read MCP config:", error);
return { mcpServers: {} };
}
}
// 更新 MCP 配置
export async function updateMcpConfig(config: McpConfig): Promise<void> {
try {
await fs.writeFile(CONFIG_PATH, JSON.stringify(config, null, 2));
} catch (error) {
console.error("Failed to write MCP config:", error);
throw error;
}
}
// 重新初始化所有客户端
export async function reinitializeMcpClients() {
logger.info("Reinitializing MCP clients...");
// 遍历所有客户端,关闭
try {
for (const [clientId, clientData] of clientsMap.entries()) {
clientData.client?.close();
}
} catch (error) {
logger.error(`Failed to close clients: ${error}`);
}
// 清空状态
clientsMap.clear();
errorClients = [];
initialized = false;
// 重新初始化
return initializeMcpClients();
}
// Initialize all configured clients
export async function initializeMcpClients() {
// If already initialized, return
if (initialized) {
return;
return { errorClients };
}
logger.info("Starting to initialize MCP clients...");
errorClients = [];
const config = await getMcpConfig();
// Initialize all clients, key is clientId, value is client config
for (const [clientId, config] of Object.entries(conf.mcpServers)) {
for (const [clientId, serverConfig] of Object.entries(config.mcpServers)) {
try {
logger.info(`Initializing MCP client: ${clientId}`);
const client = await createClient(config, clientId);
const client = await createClient(serverConfig as ServerConfig, clientId);
const primitives = await listPrimitives(client);
clientsMap.set(clientId, { client, primitives });
clientsMap.set(clientId, { client, primitives, errorMsg: null });
logger.success(
`Client [${clientId}] initialized, ${primitives.length} primitives supported`,
);
} catch (error) {
errorClients.push(clientId);
clientsMap.set(clientId, {
client: null,
primitives: [],
errorMsg: error instanceof Error ? error.message : String(error),
});
logger.error(`Failed to initialize client ${clientId}: ${error}`);
}
}
@@ -58,8 +108,9 @@ export async function initializeMcpClients() {
}
const availableClients = await getAvailableClients();
logger.info(`Available clients: ${availableClients.join(",")}`);
return { errorClients };
}
// Execute MCP request
@@ -87,9 +138,9 @@ export async function executeMcpAction(
// Get all available client IDs
export async function getAvailableClients() {
return Array.from(clientsMap.keys()).filter(
(clientId) => !errorClients.includes(clientId),
);
return Array.from(clientsMap.entries())
.filter(([_, data]) => data.errorMsg === null)
.map(([clientId]) => clientId);
}
// Get all primitives from all clients
@@ -104,3 +155,62 @@ export async function getAllPrimitives(): Promise<
primitives,
}));
}
// 获取客户端的 Primitives
export async function getClientPrimitives(clientId: string) {
try {
const clientData = clientsMap.get(clientId);
if (!clientData) {
console.warn(`Client ${clientId} not found in map`);
return null;
}
if (clientData.errorMsg) {
console.warn(`Client ${clientId} has error: ${clientData.errorMsg}`);
return null;
}
return clientData.primitives;
} catch (error) {
console.error(`Failed to get primitives for client ${clientId}:`, error);
return null;
}
}
// 重启所有客户端
export async function restartAllClients() {
logger.info("Restarting all MCP clients...");
// 清空状态
clientsMap.clear();
errorClients = [];
initialized = false;
// 重新初始化
await initializeMcpClients();
return {
success: errorClients.length === 0,
errorClients,
};
}
// 获取所有客户端状态
export async function getAllClientStatus(): Promise<
Record<string, string | null>
> {
const status: Record<string, string | null> = {};
for (const [clientId, data] of clientsMap.entries()) {
status[clientId] = data.errorMsg;
}
return status;
}
// 检查客户端状态
export async function getClientErrors(): Promise<
Record<string, string | null>
> {
const errors: Record<string, string | null> = {};
for (const [clientId, data] of clientsMap.entries()) {
errors[clientId] = data.errorMsg;
}
return errors;
}