temp
This commit is contained in:
@@ -4,7 +4,8 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"mcp": "node src/mcp.ts"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
|
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
|
||||||
@@ -15,6 +16,7 @@
|
|||||||
"@types/node": "^24.9.1"
|
"@types/node": "^24.9.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dotenv": "^17.2.3"
|
"dotenv": "^17.2.3",
|
||||||
|
"@modelcontextprotocol/sdk": "^1.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/index.ts
20
src/index.ts
@@ -1,5 +1,4 @@
|
|||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
import path from 'path';
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
const token = process.env.BAILIAN_API_KEY || '';
|
const token = process.env.BAILIAN_API_KEY || '';
|
||||||
@@ -26,26 +25,26 @@ const chat = async (message: { role: string, content: string }[]) => {
|
|||||||
|
|
||||||
const fn1 = {
|
const fn1 = {
|
||||||
id: 'get_weather',
|
id: 'get_weather',
|
||||||
description: '获取天气',
|
description: '获取天气,参数是 location 地址,返回该城市的当前天气',
|
||||||
fn: async (params: { location: string }) => {
|
fn: async (params: { location: string }) => {
|
||||||
return `当前${params.location}的天气是:晴,25度,湿度60%。`;
|
return `当前${params.location}的天气是:晴,25度,湿度60%。`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const fn2 = {
|
const fn2 = {
|
||||||
id: 'get_time',
|
id: 'get_time',
|
||||||
description: '获取时间',
|
description: `获取时间, 参数是 city 地址,返回该城市的当前时间`,
|
||||||
fn: async (params: { timezone: string }) => {
|
fn: async (params: { city: string }) => {
|
||||||
return `当前${params.timezone}的时间是:2024-06-01 10:00 AM。`;
|
return `当前${params.city}的时间是:${new Date().toLocaleTimeString()}。`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fns = [fn1, fn2];
|
const fns = [fn1, fn2];
|
||||||
const callPrompst = `你是一个函数调用助手,可以根据用户的需求选择合适的函数进行调用,并返回 JSON 数据, 格式为 { id: string, payload: {} } ,函数列表如下:
|
const callPrompts = `你是一个函数调用助手,可以根据用户的需求选择合适的函数进行调用,
|
||||||
|
并返回 JSON 数据, 格式为 { id: string, payload: {} } ,函数列表如下:
|
||||||
|
|
||||||
${fns.map(fn => `id: ${fn.id}
|
${fns.map(fn => `id: ${fn.id}
|
||||||
description: ${fn.description}`).join('\n\n')}
|
description: ${fn.description}`).join('\n\n')}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const pickJson = (text: string) => {
|
const pickJson = (text: string) => {
|
||||||
const jsonStart = text.indexOf('{');
|
const jsonStart = text.indexOf('{');
|
||||||
const jsonEnd = text.lastIndexOf('}');
|
const jsonEnd = text.lastIndexOf('}');
|
||||||
@@ -61,10 +60,11 @@ const pickJson = (text: string) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const main = async () => {
|
const main = async () => {
|
||||||
const userMessage = '请告诉我北京的天气。';
|
// const userMessage = '请告诉我上海的天气。';
|
||||||
|
const userMessage = '请告诉我杭州的时间。';
|
||||||
|
|
||||||
const messages = [
|
const messages = [
|
||||||
{ role: 'system', content: callPrompst },
|
{ role: 'system', content: callPrompts },
|
||||||
{ role: 'user', content: userMessage }
|
{ role: 'user', content: userMessage }
|
||||||
];
|
];
|
||||||
// 获取函数调用建议
|
// 获取函数调用建议
|
||||||
@@ -76,7 +76,7 @@ const main = async () => {
|
|||||||
|
|
||||||
const fn = fns.find(f => f.id === json?.id);
|
const fn = fns.find(f => f.id === json?.id);
|
||||||
if (fn) {
|
if (fn) {
|
||||||
const fnResult = await fn.fn({ location: '北京', timezone: '纽约' });
|
const fnResult = await fn.fn({ ...json.payload });
|
||||||
console.log(`Function ${fn.id} result:`, fnResult);
|
console.log(`Function ${fn.id} result:`, fnResult);
|
||||||
} else {
|
} else {
|
||||||
console.log('No matching function found.');
|
console.log('No matching function found.');
|
||||||
|
|||||||
122
src/mcp.ts
Normal file
122
src/mcp.ts
Normal file
@@ -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);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user