We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/zhewenzhang/tushare_MCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""
测试所有MCP工具的脚本(版本2)
该脚本通过直接调用工具模块中的函数来测试,而不是通过MCP服务器
"""
import sys
import os
from datetime import datetime
from typing import Dict, List, Tuple, Any
from pathlib import Path
# 添加项目根目录到路径
project_root = Path(__file__).parent
sys.path.insert(0, str(project_root))
# 初始化环境
from config.token_manager import get_tushare_token, init_env_file
import tushare as ts
init_env_file()
token = get_tushare_token()
if token:
ts.set_token(token)
print(f"✓ 已加载 Tushare token")
else:
print("⚠️ 未找到 Tushare token,部分工具可能无法正常工作")
# 创建MCP服务器实例用于注册工具
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Tushare Stock Info Test")
# 用于存储工具函数的字典
captured_tools = {}
# 创建一个包装器来捕获工具函数
original_tool_decorator = mcp.tool
def tool_wrapper(*args, **kwargs):
def decorator(func):
# 注册工具
wrapped = original_tool_decorator(*args, **kwargs)(func)
# 保存工具函数
captured_tools[func.__name__] = func
return wrapped
return decorator
# 替换tool装饰器
mcp.tool = tool_wrapper
# 注册所有工具
print("\n开始注册所有MCP工具...")
from tools import discover_tools
registered_modules = discover_tools(mcp)
print(f"✓ 已注册 {len(registered_modules)} 个工具模块")
print(f"✓ 捕获到 {len(captured_tools)} 个工具函数\n")
# 测试结果存储
test_results: List[Dict[str, Any]] = []
def run_test(tool_name: str, test_params: Dict[str, Any] = None, description: str = "") -> Tuple[bool, str]:
"""运行单个工具的测试"""
if test_params is None:
test_params = {}
try:
if tool_name not in captured_tools:
return False, f"工具 {tool_name} 未找到"
tool_func = captured_tools[tool_name]
result = tool_func(**test_params)
if result is None:
return False, "工具返回 None"
result_text = str(result)
# 检查是否是错误消息
if isinstance(result, str):
if result.startswith("请先配置"):
return False, result
# 某些"未找到"可能是正常的(如查询特定日期没有数据)
if "请提供" in result:
return False, result
return True, f"成功: {result_text[:200]}..." if len(result_text) > 200 else f"成功: {result_text}"
except Exception as e:
error_msg = f"异常: {type(e).__name__}: {str(e)}"
return False, error_msg
# 获取测试日期
test_date = datetime.now().strftime("%Y%m%d")
print(f"使用测试日期: {test_date}\n")
# ==================== 定义所有测试用例 ====================
test_cases = []
# 1. Alpha策略分析工具
test_cases.extend([
("analyze_sector_alpha_strategy", {"sector_code": "801080.SI", "benchmark_code": "000300.SH", "end_date": test_date}, "分析单个板块Alpha"),
("rank_sectors_by_alpha", {"benchmark_code": "000300.SH", "end_date": test_date, "top_n": 5}, "申万一级行业Alpha排名"),
("rank_l2_sectors_by_alpha", {"benchmark_code": "000300.SH", "end_date": test_date, "top_n": 10}, "申万二级行业Alpha排名"),
("rank_l1_sectors_alpha_full", {"benchmark_code": "000300.SH", "end_date": test_date}, "申万一级行业Alpha完整排行"),
("rank_l1_sectors_alpha_velocity", {"benchmark_code": "000300.SH", "end_date": test_date}, "申万一级行业Alpha排名上升速度"),
("rank_l2_sectors_alpha_velocity", {"benchmark_code": "000300.SH", "end_date": test_date, "top_n": 10}, "申万二级行业Alpha排名上升速度"),
("analyze_concept_alpha_strategy", {"concept_code": "BK1184.DC", "benchmark_code": "000300.SH", "end_date": test_date}, "分析概念板块Alpha"),
("rank_concepts_by_alpha", {"benchmark_code": "000300.SH", "end_date": test_date, "top_n": 10}, "概念板块Alpha排名"),
("rank_concepts_alpha_velocity", {"benchmark_code": "000300.SH", "end_date": test_date}, "概念板块Alpha排名上升速度"),
])
# 2. 股票行情工具
test_cases.extend([
("get_stock_basic_info", {"ts_code": "000001.SZ"}, "获取股票基本信息"),
("search_stocks", {"keyword": "平安"}, "搜索股票"),
("get_stock_daily", {"ts_code": "000001.SZ", "trade_date": test_date}, "获取A股日线行情"),
("get_stock_weekly", {"ts_code": "000001.SZ", "trade_date": test_date}, "获取A股周线行情"),
("get_etf_daily", {"ts_code": "510300.SH", "trade_date": test_date}, "获取ETF日线行情"),
("get_index_daily", {"ts_code": "000300.SH", "trade_date": test_date}, "获取A股指数日线行情"),
("get_share_float", {"ts_code": "000001.SZ"}, "获取限售股解禁数据"),
("get_stock_repurchase", {}, "获取股票回购数据"),
("get_pledge_detail", {"ts_code": "000001.SZ"}, "获取股权质押明细"),
("get_block_trade", {"trade_date": test_date}, "获取大宗交易数据"),
("scan_announcement_signals", {"check_date": test_date}, "扫描公告信号"),
("get_stock_holder_trade", {"ts_code": "000001.SZ"}, "获取股东增减持数据"),
("get_stock_holder_number", {"ts_code": "000001.SZ"}, "获取股东户数数据"),
("get_stock_survey", {"ts_code": "000001.SZ"}, "获取机构调研数据"),
("get_cyq_perf", {"ts_code": "000001.SZ", "trade_date": test_date}, "获取筹码分析数据"),
("get_margin", {"trade_date": test_date}, "获取融资融券汇总数据"),
("get_margin_detail", {"ts_code": "000001.SZ", "trade_date": test_date}, "获取融资融券明细数据"),
("get_stock_moneyflow_dc", {"ts_code": "000001.SZ", "trade_date": test_date}, "获取个股资金流向"),
("get_daily_basic", {"ts_code": "000001.SZ", "trade_date": test_date}, "获取每日指标数据"),
("get_top_list", {"trade_date": test_date}, "获取龙虎榜每日明细"),
("get_top_inst", {"trade_date": test_date}, "获取龙虎榜机构明细"),
])
# 3. 指数行情工具
test_cases.extend([
("get_global_index", {"index_code": "DJI", "trade_date": test_date}, "获取国际指数行情"),
("search_global_indexes", {"keyword": "道琼斯"}, "搜索国际指数"),
("get_sw_industry_daily", {"level": "L1", "trade_date": test_date}, "获取申万行业指数日线"),
("get_industry_index_codes", {"level": "L1"}, "获取申万行业分类代码"),
])
# 4. 外汇工具
test_cases.extend([
("get_fx_daily", {"ts_code": "USDCNH.FXCM", "trade_date": test_date}, "获取外汇日线行情"),
])
# 5. 期货工具
test_cases.extend([
("get_fut_basic", {"exchange": "SHFE"}, "获取期货合约基本信息"),
("get_nh_index", {"ts_code": "NHCI.NH", "trade_date": test_date}, "获取南华期货指数"),
("get_fut_holding", {"trade_date": test_date}, "获取期货持仓排名"),
("get_fut_wsr", {"trade_date": test_date}, "获取期货仓单日报"),
])
# 6. 财务报表工具
test_cases.extend([
("get_income_statement", {"ts_code": "000001.SZ", "start_date": "20230101", "end_date": "20231231"}, "获取利润表数据"),
("get_fina_indicator", {"ts_code": "000001.SZ"}, "获取财务指标数据"),
])
# 7. 概念板块工具
test_cases.extend([
("get_eastmoney_concept_board", {"trade_date": test_date}, "获取东财概念板块行情"),
("get_eastmoney_concept_member", {"ts_code": "BK1184.DC", "trade_date": test_date}, "获取东财概念成分"),
("get_eastmoney_concept_daily", {"trade_date": test_date, "idx_type": "概念板块"}, "获取东财概念日线"),
("get_concept_moneyflow_dc", {"trade_date": test_date}, "获取板块资金流向"),
])
# 8. 成交量异动分析工具
test_cases.extend([
("scan_l2_volume_anomaly", {"end_date": test_date}, "扫描成交量异动"),
])
# 9. 缓存管理工具
test_cases.extend([
("get_cache_stats", {}, "获取缓存统计信息"),
])
# ==================== 执行测试 ====================
print("=" * 80)
print("开始测试所有MCP工具")
print("=" * 80)
print()
total_tests = len(test_cases)
success_count = 0
fail_count = 0
skip_count = 0
for i, (tool_name, params, description) in enumerate(test_cases, 1):
print(f"[{i}/{total_tests}] 测试: {tool_name} - {description}")
print(f" 参数: {params}")
success, result = run_test(tool_name, params, description)
if success:
print(f" ✓ 成功")
success_count += 1
else:
if "权限" in result or "积分" in result or "未找到" in result or "请先配置" in result:
print(f" ⚠️ 跳过: {result}")
skip_count += 1
else:
print(f" ✗ 失败: {result}")
fail_count += 1
test_results.append({
"tool_name": tool_name,
"description": description,
"params": params,
"success": success,
"result": result,
"timestamp": datetime.now().isoformat()
})
print()
# ==================== 生成测试报告 ====================
print("=" * 80)
print("测试报告")
print("=" * 80)
print()
print(f"总测试数: {total_tests}")
print(f"成功: {success_count} ({success_count/total_tests*100:.1f}%)")
print(f"失败: {fail_count} ({fail_count/total_tests*100:.1f}%)")
print(f"跳过: {skip_count} ({skip_count/total_tests*100:.1f}%)")
print()
# 按类别统计
categories = {
"Alpha策略分析": ["analyze_sector_alpha_strategy", "rank_sectors_by_alpha", "rank_l2_sectors_by_alpha",
"rank_l1_sectors_alpha_full", "rank_l1_sectors_alpha_velocity", "rank_l2_sectors_alpha_velocity",
"analyze_concept_alpha_strategy", "rank_concepts_by_alpha", "rank_concepts_alpha_velocity"],
"股票行情": ["get_stock_basic_info", "search_stocks", "get_stock_daily", "get_stock_weekly",
"get_etf_daily", "get_index_daily", "get_share_float", "get_stock_repurchase",
"get_pledge_detail", "get_block_trade", "scan_announcement_signals", "get_stock_holder_trade",
"get_stock_holder_number", "get_stock_survey", "get_cyq_perf", "get_margin",
"get_margin_detail", "get_stock_moneyflow_dc", "get_daily_basic", "get_top_list", "get_top_inst"],
"指数行情": ["get_global_index", "search_global_indexes", "get_sw_industry_daily", "get_industry_index_codes"],
"外汇": ["get_fx_daily"],
"期货": ["get_fut_basic", "get_nh_index", "get_fut_holding", "get_fut_wsr"],
"财务报表": ["get_income_statement", "get_fina_indicator"],
"概念板块": ["get_eastmoney_concept_board", "get_eastmoney_concept_member", "get_eastmoney_concept_daily", "get_concept_moneyflow_dc"],
"成交量异动": ["scan_l2_volume_anomaly"],
"缓存管理": ["get_cache_stats"]
}
print("\n按类别统计:")
print("-" * 80)
for category, tool_names in categories.items():
category_results = [r for r in test_results if r["tool_name"] in tool_names]
if category_results:
cat_success = sum(1 for r in category_results if r["success"])
cat_total = len(category_results)
print(f"{category}: {cat_success}/{cat_total} 成功 ({cat_success/cat_total*100:.1f}%)")
# 失败的测试详情
if fail_count > 0:
print("\n失败的测试详情:")
print("-" * 80)
for result in test_results:
if not result["success"] and "权限" not in result["result"] and "积分" not in result["result"]:
print(f" ✗ {result['tool_name']}: {result['result']}")
# 保存测试报告到文件
report_file = project_root / "test_report.txt"
with open(report_file, "w", encoding="utf-8") as f:
f.write("=" * 80 + "\n")
f.write("MCP工具测试报告\n")
f.write(f"测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write("=" * 80 + "\n\n")
f.write(f"总测试数: {total_tests}\n")
f.write(f"成功: {success_count} ({success_count/total_tests*100:.1f}%)\n")
f.write(f"失败: {fail_count} ({fail_count/total_tests*100:.1f}%)\n")
f.write(f"跳过: {skip_count} ({skip_count/total_tests*100:.1f}%)\n\n")
f.write("\n详细测试结果:\n")
f.write("-" * 80 + "\n")
for result in test_results:
status = "✓" if result["success"] else "✗"
f.write(f"{status} {result['tool_name']} - {result['description']}\n")
f.write(f" 参数: {result['params']}\n")
f.write(f" 结果: {result['result'][:200]}\n")
f.write("\n")
print(f"\n测试报告已保存到: {report_file}")
# 退出码
sys.exit(0 if fail_count == 0 else 1)