Skip to main content
Glama
xiaobenyang_mcp_tools.ts6.29 kB
import {McpServer} from "@modelcontextprotocol/sdk/server/mcp.js" import {z, ZodType} from "zod"; // Optional: If you have user-level config, define it here const apiKey: string = process.env.API_KEY || ''; // const mcpID: string = process.env.MCP_ID; const mcpID: string = '1804087353852938'; console.log("apiKey: " + apiKey) console.log("mcpID: " + mcpID) const calcXiaoBenYangApi = async function (fullArgs: Record<string, any>) { // 发起 POST 请求 const response = await fetch('https://xiaobenyang.com/api', { method: 'POST', headers: { 'APIKEY': apiKey, 'aid': mcpID }, body: new URLSearchParams(fullArgs) }); const apiResult = await response.text(); return { content: [ { type: "text", text: apiResult // 将字符串结果放入 content 中 } ] }; }; const handleXiaoBenYangApi = async (args: Record<string, any>, aid: string) => { console.log("handleXiaoBenYangApi: " + aid); // 校验aid是否存在 if (aid === undefined || aid === null) { throw new Error("缺少必要参数 'aid'"); } // 合并参数 const fullArgs = {...args, aid}; // 调用API return calcXiaoBenYangApi(fullArgs); }; /** * Java 类型转 Zod 类型的映射表 */ const JAVA_TO_ZOD_MAP: Record<string, (...generics: string[]) => ZodType> = { // 基础类型(全类名) 'java.lang.String': () => z.string(), 'java.lang.Integer': () => z.number().int(), 'java.lang.Long': () => z.number().int(), 'java.lang.Float': () => z.number(), 'java.lang.Double': () => z.number(), 'java.lang.Boolean': () => z.boolean(), 'java.time.LocalDate': () => z.string().regex(/^\d{4}-\d{2}-\d{2}$/), 'java.time.LocalDateTime': () => z.string().regex(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/), // 集合类型(全类名) 'java.util.List': (genericType) => z.array(convertJavaTypeToZod(genericType)), // 'java.util.Set': (genericType) => z.array(convertJavaTypeToZod(genericType)).unique(), 'java.util.Map': (keyType, valueType) => z.record(convertJavaTypeToZod(keyType), convertJavaTypeToZod(valueType)), // 简单类名映射 String: () => z.string(), Integer: () => z.number().int(), Long: () => z.number().int(), Float: () => z.number(), Double: () => z.number(), Boolean: () => z.boolean(), List: (genericType) => z.array(convertJavaTypeToZod(genericType)), }; /** * 解析 Java 泛型类型 * @param javaType Java 类型字符串 * @returns 解析结果 { base: 基础类型, generics: 泛型参数数组 } */ function parseGenericType(javaType: string): { base: string; generics: string[] } { const angleBracketIndex = javaType.indexOf('<'); if (angleBracketIndex === -1) { return {base: javaType.trim(), generics: []}; } const baseType = javaType.slice(0, angleBracketIndex).trim(); const genericsStr = javaType.slice(angleBracketIndex + 1, javaType.lastIndexOf('>')).trim(); const generics: string[] = []; let balance = 0; let current = ''; for (const char of genericsStr) { if (char === '<') balance++; if (char === '>') balance--; if (char === ',' && balance === 0) { generics.push(current.trim()); current = ''; } else { current += char; } } if (current) generics.push(current.trim()); return {base: baseType, generics}; } /** * 将 Java 类型名称转换为 Zod 类型 * @param javaType Java 类型全名 * @returns Zod 类型对象 */ function convertJavaTypeToZod(javaType: string): ZodType { const {base: baseType, generics} = parseGenericType(javaType); if (JAVA_TO_ZOD_MAP[baseType]) { return JAVA_TO_ZOD_MAP[baseType](...generics); } const simpleTypeName = baseType.split('.').pop() || baseType; if (JAVA_TO_ZOD_MAP[simpleTypeName]) { return JAVA_TO_ZOD_MAP[simpleTypeName](...generics); } return z.object({}); } // 定义参数类型接口 interface ApiParam { name: string; type: string; description?: string; required: boolean; } const convertParamsToZ = function (params: Record<string, string>) { const zParams: Record<string, ZodType> = {}; for (const param in params) { let zodType = convertJavaTypeToZod(param["type"]); if (param["description"]) { zodType = zodType.describe(param["description"]); } if (!param["required"]) { // 注意:原逻辑可能有误,required为true时不应optional zodType = zodType.optional(); } zParams[param["name"]] = zodType; } console.log(JSON.stringify(zParams)) return zParams; }; const server = new McpServer({ name: "Say Hello", version: "1.0.0", }) console.log("1111111"); let isLoading: boolean = false; fetch('https://xiaobenyang.com/api/' + mcpID, { method: 'GET', }).then((res) => { console.log("g22222"); if (!res.ok) { console.log("g33333"); throw new Error(`请求失败:${res.status}`); } return res.json(); // 解析响应体为 JSON(假设返回 { apiDescList: [...] }) }) .then((data) => { console.log("g44444"); const apiDescList = data.tools; const addToolXiaoBenYangApi = function ( aid: string, title: string, desc: string, params: Record<string, ZodType> ) { server.registerTool( title, { title: title, description: desc, inputSchema: params, } , async (args: Record<string, any>) => handleXiaoBenYangApi(args, aid) ) }; console.log("g5555"); for (const apiDesc of apiDescList) { addToolXiaoBenYangApi(apiDesc.apiId.toString(), apiDesc.title, apiDesc.description ? apiDesc.description : apiDesc.title, convertParamsToZ(apiDesc.params) ); } isLoading = true; console.log("g66666"); }); export { server, isLoading};

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/xiaobenyang-com/mcp_tools_3'

If you have feedback or need assistance with the MCP directory API, please join our Discord server