// mcp/src/server.ts
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ListResourcesRequestSchema,
ListResourceTemplatesRequestSchema,
ReadResourceRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import { WhkerDBClient } from './client/WhkerDBClient.js';
import { SocketClient } from './client/SocketClient.js';
import {
roomTools,
createRoomToolHandlers,
treeTools,
createTreeToolHandlers,
objectTools,
createObjectToolHandlers,
pdfTools,
createPdfToolHandlers,
imageTools,
createImageToolHandlers,
} from './tools/index.js';
import { getResources, getResourceTemplates, createResourceHandlers } from './resources/index.js';
export interface McpServerOptions {
serverUrl?: string;
}
/**
* 创建 WhkerDB MCP 服务器
*/
export function createMcpServer(options: McpServerOptions = {}) {
const serverUrl = options.serverUrl || process.env.WHKERDB_SERVER_URL || 'http://localhost:3001';
// 创建 HTTP 客户端
const httpClient = new WhkerDBClient(serverUrl);
// Socket 客户端状态
let socketClient: SocketClient | null = null;
const getSocketClient = () => socketClient;
const setSocketClient = (client: SocketClient | null) => {
socketClient = client;
};
const createSocketClient = (userId: string, username: string) => {
return new SocketClient({
serverUrl,
userId,
username,
});
};
// 创建工具处理器
const roomHandlers = createRoomToolHandlers(
httpClient,
getSocketClient,
setSocketClient,
createSocketClient
);
const treeHandlers = createTreeToolHandlers(getSocketClient);
const objectHandlers = createObjectToolHandlers(getSocketClient);
const pdfHandlers = createPdfToolHandlers(httpClient, getSocketClient);
const imageHandlers = createImageToolHandlers(httpClient, getSocketClient);
// 合并所有工具处理器
const allToolHandlers: Record<string, (args: any) => Promise<any>> = {
...roomHandlers,
...treeHandlers,
...objectHandlers,
...pdfHandlers,
...imageHandlers,
};
// 创建资源处理器
const resourceHandlers = createResourceHandlers(httpClient, getSocketClient);
// 合并所有工具定义
const allTools = [...roomTools, ...treeTools, ...objectTools, ...pdfTools, ...imageTools];
// 创建 MCP 服务器
const server = new Server(
{
name: 'whkerdb-mcp',
version: '1.0.0',
},
{
capabilities: {
tools: {},
resources: {},
},
}
);
// 注册工具列表处理器
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: allTools,
};
});
// 注册工具调用处理器
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
const handler = allToolHandlers[name];
if (!handler) {
throw new Error(`未知的工具: ${name}`);
}
try {
return await handler(args || {});
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({ error: true, message }, null, 2),
},
],
isError: true,
};
}
});
// 注册资源列表处理器
server.setRequestHandler(ListResourcesRequestSchema, async () => {
return {
resources: getResources(getSocketClient),
};
});
// 注册资源模板列表处理器
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
return {
resourceTemplates: getResourceTemplates(),
};
});
// 注册资源读取处理器
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const { uri } = request.params;
try {
return await resourceHandlers.readResource(uri);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(message);
}
});
// 清理函数
const cleanup = () => {
if (socketClient) {
socketClient.disconnect();
socketClient = null;
}
};
return {
server,
cleanup,
httpClient,
getSocketClient,
};
}