agent功能开发增加MCP后端

This commit is contained in:
2025-11-07 18:11:29 +08:00
parent a1c76a257c
commit e7ba8c4c2d
11 changed files with 936 additions and 1 deletions

248
src/services/mcpService.js Normal file
View File

@@ -0,0 +1,248 @@
// src/services/mcpService.js
// MCP (Model Context Protocol) 服务层
// 用于与FastAPI后端的MCP工具进行交互
import axios from 'axios';
import { getApiBase } from '../utils/apiConfig';
import { logger } from '../utils/logger';
/**
* MCP API客户端
*/
class MCPService {
constructor() {
this.baseURL = `${getApiBase()}/mcp`;
this.client = axios.create({
baseURL: this.baseURL,
timeout: 60000, // 60秒超时MCP工具可能需要较长时间
headers: {
'Content-Type': 'application/json',
},
});
// 请求拦截器
this.client.interceptors.request.use(
(config) => {
logger.debug('MCPService', 'Request', {
url: config.url,
method: config.method,
data: config.data,
});
return config;
},
(error) => {
logger.error('MCPService', 'Request Error', error);
return Promise.reject(error);
}
);
// 响应拦截器
this.client.interceptors.response.use(
(response) => {
logger.debug('MCPService', 'Response', {
url: response.config.url,
status: response.status,
data: response.data,
});
return response.data;
},
(error) => {
logger.error('MCPService', 'Response Error', {
url: error.config?.url,
status: error.response?.status,
message: error.message,
});
return Promise.reject(error);
}
);
}
/**
* 列出所有可用的MCP工具
* @returns {Promise<Object>} 工具列表
*/
async listTools() {
try {
const response = await this.client.get('/tools');
return {
success: true,
data: response.tools || [],
};
} catch (error) {
return {
success: false,
error: error.message || '获取工具列表失败',
};
}
}
/**
* 获取特定工具的定义
* @param {string} toolName - 工具名称
* @returns {Promise<Object>} 工具定义
*/
async getTool(toolName) {
try {
const response = await this.client.get(`/tools/${toolName}`);
return {
success: true,
data: response,
};
} catch (error) {
return {
success: false,
error: error.message || '获取工具定义失败',
};
}
}
/**
* 调用MCP工具
* @param {string} toolName - 工具名称
* @param {Object} arguments - 工具参数
* @returns {Promise<Object>} 工具执行结果
*/
async callTool(toolName, toolArguments) {
try {
const response = await this.client.post('/tools/call', {
tool: toolName,
arguments: toolArguments,
});
return {
success: true,
data: response.data || response,
};
} catch (error) {
return {
success: false,
error: error.response?.data?.detail || error.message || '工具调用失败',
};
}
}
/**
* 智能对话 - 根据用户输入自动选择合适的工具
* @param {string} userMessage - 用户消息
* @param {Array} conversationHistory - 对话历史(可选)
* @returns {Promise<Object>} AI响应
*/
async chat(userMessage, conversationHistory = []) {
try {
// 这里可以实现智能路由逻辑
// 根据用户输入判断应该调用哪个工具
// 示例:关键词匹配
if (userMessage.includes('新闻') || userMessage.includes('资讯')) {
return await this.callTool('search_china_news', {
query: userMessage.replace(/新闻|资讯/g, '').trim(),
top_k: 5,
});
} else if (userMessage.includes('概念') || userMessage.includes('板块')) {
const query = userMessage.replace(/概念|板块/g, '').trim();
return await this.callTool('search_concepts', {
query,
size: 5,
sort_by: 'change_pct',
});
} else if (userMessage.includes('涨停')) {
const query = userMessage.replace(/涨停/g, '').trim();
return await this.callTool('search_limit_up_stocks', {
query,
mode: 'hybrid',
page_size: 5,
});
} else if (/^[0-9]{6}$/.test(userMessage.trim())) {
// 6位数字 = 股票代码
return await this.callTool('get_stock_basic_info', {
seccode: userMessage.trim(),
});
} else {
// 默认:搜索新闻
return await this.callTool('search_china_news', {
query: userMessage,
top_k: 5,
});
}
} catch (error) {
return {
success: false,
error: error.message || '对话处理失败',
};
}
}
/**
* 工具类别枚举
*/
static TOOL_CATEGORIES = {
NEWS: 'news', // 新闻搜索
STOCK: 'stock', // 股票信息
CONCEPT: 'concept', // 概念板块
LIMIT_UP: 'limit_up', // 涨停分析
RESEARCH: 'research', // 研报搜索
ROADSHOW: 'roadshow', // 路演信息
FINANCIAL: 'financial', // 财务数据
TRADE: 'trade', // 交易数据
};
/**
* 常用工具快捷方式
*/
async searchNews(query, topK = 5, exactMatch = false) {
return await this.callTool('search_china_news', {
query,
top_k: topK,
exact_match: exactMatch,
});
}
async searchConcepts(query, size = 10, sortBy = 'change_pct') {
return await this.callTool('search_concepts', {
query,
size,
sort_by: sortBy,
});
}
async searchLimitUpStocks(query, mode = 'hybrid', pageSize = 10) {
return await this.callTool('search_limit_up_stocks', {
query,
mode,
page_size: pageSize,
});
}
async getStockInfo(seccode) {
return await this.callTool('get_stock_basic_info', {
seccode,
});
}
async getStockConcepts(stockCode, size = 10) {
return await this.callTool('get_stock_concepts', {
stock_code: stockCode,
size,
});
}
async searchResearchReports(query, mode = 'hybrid', size = 5) {
return await this.callTool('search_research_reports', {
query,
mode,
size,
});
}
async getConceptStatistics(days = 7, minStockCount = 3) {
return await this.callTool('get_concept_statistics', {
days,
min_stock_count: minStockCount,
});
}
}
// 导出单例实例
export const mcpService = new MCPService();
// 导出类(供测试使用)
export default MCPService;