ChatGPT-Next-Web/app/mcp/client.ts
2025-05-08 19:28:47 +08:00

78 lines
1.8 KiB
TypeScript

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { MCPClientLogger } from "./logger";
import {
ListToolsResponse,
McpRequestMessage,
ServerConfig,
isServerSseConfig,
} from "./types";
import { z } from "zod";
const logger = new MCPClientLogger();
export async function createClient(
id: string,
config: ServerConfig,
): Promise<Client> {
logger.info(`Creating client for ${id}...`);
let transport;
if (isServerSseConfig(config)) {
const { SSEClientTransport } = await import(
"@modelcontextprotocol/sdk/client/sse.js"
);
transport = new SSEClientTransport(new URL(config.url));
} else {
if (EXPORT_MODE) {
throw new Error(
"Cannot use stdio transport in export mode. Please use SSE transport configuration instead.",
);
} else {
const { StdioClientTransport } = await import(
"@modelcontextprotocol/sdk/client/stdio.js"
);
transport = new StdioClientTransport({
command: config.command,
args: config.args,
env: {
...Object.fromEntries(
Object.entries(process.env)
.filter(([_, v]) => v !== undefined)
.map(([k, v]) => [k, v as string]),
),
...(config.env || {}),
},
});
}
}
const client = new Client(
{
name: `nextchat-mcp-client-${id}`,
version: "1.0.0",
},
{
capabilities: {},
},
);
await client.connect(transport);
return client;
}
export async function removeClient(client: Client) {
logger.info(`Removing client...`);
await client.close();
}
export async function listTools(client: Client): Promise<ListToolsResponse> {
return client.listTools();
}
export async function executeRequest(
client: Client,
request: McpRequestMessage,
) {
return client.request(request, z.any());
}