yszl-mcp
Version:
Scenic Area Tourist Flow Query Server with official MCP SDK
104 lines (89 loc) • 2.67 kB
JavaScript
import crypto from 'crypto';
import axios from 'axios';
/**
* 游客年龄分布查询工具
*/
export class AgePortraitTool {
constructor() {
this.apiUrl = process.env.API_URL;
this.account = process.env.ACCOUNT;
this.appSecret = process.env.APP_SECRET;
}
/**
* 生成API请求签名
* @param {Object} params - 请求参数
* @returns {string} - MD5签名
*/
generateSignature(params) {
// 按照参数名称排序
const sortedParams = Object.keys(params).sort().reduce(
(result, key) => {
result[key] = params[key];
return result;
},
{}
);
// 构建签名字符串:按顺序拼接参数值,用分号分隔
let signStr = '';
for (const key in sortedParams) {
signStr += sortedParams[key] + ';';
}
signStr += this.appSecret;
console.log('签名字符串:', signStr);
// 返回MD5哈希
return crypto.createHash('md5').update(signStr).digest('hex').toUpperCase();
}
/**
* 执行工具查询游客年龄分布
* @param {Object} params - 查询参数
* @param {string} params.scenicId - 景区ID
* @param {string} params.date - 查询日期,格式:YYYY-MM-DD
* @returns {Promise<Object>} - 年龄分布数据
*/
async execute(params) {
try {
// 验证必填参数
if (!params.scenicId) {
throw new Error('缺少必填参数: scenicId');
}
if (!params.date) {
throw new Error('缺少必填参数: date');
}
// 准备请求参数
const requestParams = {
account: this.account,
ts: Date.now().toString(),
code: params.scenicId,
day: params.date
};
// 生成签名
const sign = this.generateSignature(requestParams);
// 构建请求数据
const requestData = {
...requestParams,
sign
};
// 发送API请求
const response = await axios.post(`${this.apiUrl}/v3/day/tl/tourist/portrait/age`, requestData);
console.log('API响应:', JSON.stringify({
status: response.status,
data: response.data,
request: {
url: response.config.url,
method: response.config.method,
data: JSON.stringify(response.config.data)
}
}, null, 2));
// 检查API响应
if (response.data.code !== 200) {
throw new Error(`API错误: ${response.data.message}`);
}
// 返回年龄分布数据
return response.data.data;
} catch (error) {
console.error(`游客年龄分布查询出错: ${error.message}`);
throw error;
}
}
}
export default AgePortraitTool;