diff --git a/package.json b/package.json index 67bfbc8..4633be6 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "mcp": "node src/mcp.ts" }, "keywords": [], "author": "abearxiong (https://www.xiongxiao.me)", @@ -15,6 +16,7 @@ "@types/node": "^24.9.1" }, "dependencies": { - "dotenv": "^17.2.3" + "dotenv": "^17.2.3", + "@modelcontextprotocol/sdk": "^1.0.0" } } diff --git a/src/index.ts b/src/index.ts index e4e0ec5..973ea48 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,4 @@ import dotenv from 'dotenv'; -import path from 'path'; dotenv.config(); const token = process.env.BAILIAN_API_KEY || ''; @@ -26,26 +25,26 @@ const chat = async (message: { role: string, content: string }[]) => { const fn1 = { id: 'get_weather', - description: '获取天气', + description: '获取天气,参数是 location 地址,返回该城市的当前天气', fn: async (params: { location: string }) => { return `当前${params.location}的天气是:晴,25度,湿度60%。`; } } const fn2 = { id: 'get_time', - description: '获取时间', - fn: async (params: { timezone: string }) => { - return `当前${params.timezone}的时间是:2024-06-01 10:00 AM。`; + description: `获取时间, 参数是 city 地址,返回该城市的当前时间`, + fn: async (params: { city: string }) => { + return `当前${params.city}的时间是:${new Date().toLocaleTimeString()}。`; } } const fns = [fn1, fn2]; -const callPrompst = `你是一个函数调用助手,可以根据用户的需求选择合适的函数进行调用,并返回 JSON 数据, 格式为 { id: string, payload: {} } ,函数列表如下: +const callPrompts = `你是一个函数调用助手,可以根据用户的需求选择合适的函数进行调用, +并返回 JSON 数据, 格式为 { id: string, payload: {} } ,函数列表如下: ${fns.map(fn => `id: ${fn.id} description: ${fn.description}`).join('\n\n')} `; - const pickJson = (text: string) => { const jsonStart = text.indexOf('{'); const jsonEnd = text.lastIndexOf('}'); @@ -61,10 +60,11 @@ const pickJson = (text: string) => { return null; } const main = async () => { - const userMessage = '请告诉我北京的天气。'; + // const userMessage = '请告诉我上海的天气。'; + const userMessage = '请告诉我杭州的时间。'; const messages = [ - { role: 'system', content: callPrompst }, + { role: 'system', content: callPrompts }, { role: 'user', content: userMessage } ]; // 获取函数调用建议 @@ -76,7 +76,7 @@ const main = async () => { const fn = fns.find(f => f.id === json?.id); if (fn) { - const fnResult = await fn.fn({ location: '北京', timezone: '纽约' }); + const fnResult = await fn.fn({ ...json.payload }); console.log(`Function ${fn.id} result:`, fnResult); } else { console.log('No matching function found.'); diff --git a/src/mcp.ts b/src/mcp.ts new file mode 100644 index 0000000..d61549a --- /dev/null +++ b/src/mcp.ts @@ -0,0 +1,122 @@ +import { Server } from '@modelcontextprotocol/sdk/server'; +import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio'; +import { + CallToolRequestSchema, + ListToolsRequestSchema, +} from '@modelcontextprotocol/sdk/types'; +import type { CallToolRequest } from '@modelcontextprotocol/sdk/types'; + +// 创建MCP服务器实例 +const server = new Server( + { + name: 'weather-time-server', + version: '1.0.0', + }, + { + capabilities: { + tools: {}, + }, + } +); + +// 获取天气工具 +server.setRequestHandler(ListToolsRequestSchema, async () => { + return { + tools: [ + { + name: 'get_weather', + description: '获取天气,参数是 location 地址,返回该城市的当前天气', + inputSchema: { + type: 'object', + properties: { + location: { + type: 'string', + description: '要查询天气的城市地址' + } + }, + required: ['location'] + } + }, + { + name: 'get_time', + description: '获取时间, 参数是 city 地址,返回该城市的当前时间', + inputSchema: { + type: 'object', + properties: { + city: { + type: 'string', + description: '要查询时间的城市地址' + } + }, + required: ['city'] + } + } + ] + }; +}); + +// 处理工具调用 +server.setRequestHandler(CallToolRequestSchema, async (request: CallToolRequest) => { + const { name, arguments: args } = request.params; + + try { + switch (name) { + case 'get_weather': { + const location = args?.location as string; + if (!location) { + throw new Error('缺少必需的参数: location'); + } + const weather = `当前${location}的天气是:晴,25度,湿度60%。`; + return { + content: [ + { + type: 'text', + text: weather + } + ] + }; + } + + case 'get_time': { + const city = args?.city as string; + if (!city) { + throw new Error('缺少必需的参数: city'); + } + const time = `当前${city}的时间是:2024-06-01 10:00 AM。`; + return { + content: [ + { + type: 'text', + text: time + } + ] + }; + } + + default: + throw new Error(`未知工具: ${name}`); + } + } catch (error) { + return { + content: [ + { + type: 'text', + text: `错误: ${error instanceof Error ? error.message : String(error)}` + } + ], + isError: true + }; + } +}); + +// 启动服务器 +async function main() { + const transport = new StdioServerTransport(); + await server.connect(transport); + console.error('Weather & Time MCP Server running on stdio'); +} + +main().catch((error) => { + console.error('服务器启动失败:', error); + process.exit(1); +}); \ No newline at end of file