aigroup-econ-mcp 0.1.2__py3-none-any.whl → 0.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of aigroup-econ-mcp might be problematic. Click here for more details.
- aigroup_econ_mcp/__init__.py +18 -18
- aigroup_econ_mcp/cli.py +86 -81
- aigroup_econ_mcp/server.py +123 -57
- aigroup_econ_mcp/tools/__init__.py +6 -6
- aigroup_econ_mcp/tools/regression.py +213 -213
- aigroup_econ_mcp/tools/statistics.py +133 -133
- aigroup_econ_mcp/tools/time_series.py +259 -259
- aigroup_econ_mcp-0.1.6.dist-info/METADATA +448 -0
- aigroup_econ_mcp-0.1.6.dist-info/RECORD +12 -0
- {aigroup_econ_mcp-0.1.2.dist-info → aigroup_econ_mcp-0.1.6.dist-info}/licenses/LICENSE +20 -20
- aigroup_econ_mcp-0.1.2.dist-info/METADATA +0 -226
- aigroup_econ_mcp-0.1.2.dist-info/RECORD +0 -12
- {aigroup_econ_mcp-0.1.2.dist-info → aigroup_econ_mcp-0.1.6.dist-info}/WHEEL +0 -0
- {aigroup_econ_mcp-0.1.2.dist-info → aigroup_econ_mcp-0.1.6.dist-info}/entry_points.txt +0 -0
aigroup_econ_mcp/__init__.py
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
"""
|
|
2
|
-
AIGroup 计量经济学 MCP 服务
|
|
3
|
-
专业计量经济学MCP工具 - 让大模型直接进行数据分析
|
|
4
|
-
|
|
5
|
-
提供:
|
|
6
|
-
- 描述性统计分析
|
|
7
|
-
- OLS回归分析
|
|
8
|
-
- 时间序列分析
|
|
9
|
-
- 假设检验
|
|
10
|
-
- 模型诊断
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
__version__ = "0.1.
|
|
14
|
-
__author__ = "AIGroup"
|
|
15
|
-
__description__ = "专业计量经济学MCP工具 - 让大模型直接进行数据分析"
|
|
16
|
-
|
|
17
|
-
from .server import create_mcp_server
|
|
18
|
-
|
|
1
|
+
"""
|
|
2
|
+
AIGroup 计量经济学 MCP 服务
|
|
3
|
+
专业计量经济学MCP工具 - 让大模型直接进行数据分析
|
|
4
|
+
|
|
5
|
+
提供:
|
|
6
|
+
- 描述性统计分析
|
|
7
|
+
- OLS回归分析
|
|
8
|
+
- 时间序列分析
|
|
9
|
+
- 假设检验
|
|
10
|
+
- 模型诊断
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
__version__ = "0.1.6"
|
|
14
|
+
__author__ = "AIGroup"
|
|
15
|
+
__description__ = "专业计量经济学MCP工具 - 让大模型直接进行数据分析"
|
|
16
|
+
|
|
17
|
+
from .server import create_mcp_server
|
|
18
|
+
|
|
19
19
|
__all__ = ["create_mcp_server", "__version__", "__author__", "__description__"]
|
aigroup_econ_mcp/cli.py
CHANGED
|
@@ -1,82 +1,87 @@
|
|
|
1
|
-
"""
|
|
2
|
-
AIGroup 计量经济学 MCP 服务命令行入口
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import sys
|
|
6
|
-
import click
|
|
7
|
-
from .server import create_mcp_server
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@click.command()
|
|
11
|
-
@click.option('--port', default=8000, help='服务器端口')
|
|
12
|
-
@click.option('--host', default='127.0.0.1', help='服务器地址')
|
|
13
|
-
@click.option('--transport', default='stdio',
|
|
14
|
-
type=click.Choice(['stdio', 'streamable-http', 'sse']),
|
|
15
|
-
help='传输协议 (默认: stdio)')
|
|
16
|
-
@click.option('--debug', is_flag=True, help='启用调试模式')
|
|
17
|
-
@click.option('--mount-path', default=None, help='挂载路径')
|
|
18
|
-
@click.option('--version', is_flag=True, help='显示版本信息')
|
|
19
|
-
def cli(port: int, host: str, transport: str, debug: bool, mount_path: str, version: bool):
|
|
20
|
-
"""AIGroup 计量经济学 MCP 工具
|
|
21
|
-
|
|
22
|
-
默认以stdio模式启动MCP服务器,适用于MCP客户端集成。
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
# 处理版本标志
|
|
26
|
-
if version:
|
|
27
|
-
|
|
28
|
-
click.echo("
|
|
29
|
-
click.echo("
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
#
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
click.echo(f"[INFO]
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
1
|
+
"""
|
|
2
|
+
AIGroup 计量经济学 MCP 服务命令行入口
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
import click
|
|
7
|
+
from .server import create_mcp_server
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command()
|
|
11
|
+
@click.option('--port', default=8000, help='服务器端口')
|
|
12
|
+
@click.option('--host', default='127.0.0.1', help='服务器地址')
|
|
13
|
+
@click.option('--transport', default='stdio',
|
|
14
|
+
type=click.Choice(['stdio', 'streamable-http', 'sse']),
|
|
15
|
+
help='传输协议 (默认: stdio)')
|
|
16
|
+
@click.option('--debug', is_flag=True, help='启用调试模式')
|
|
17
|
+
@click.option('--mount-path', default=None, help='挂载路径')
|
|
18
|
+
@click.option('--version', is_flag=True, help='显示版本信息')
|
|
19
|
+
def cli(port: int, host: str, transport: str, debug: bool, mount_path: str, version: bool):
|
|
20
|
+
"""AIGroup 计量经济学 MCP 工具
|
|
21
|
+
|
|
22
|
+
默认以stdio模式启动MCP服务器,适用于MCP客户端集成。
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# 处理版本标志
|
|
26
|
+
if version:
|
|
27
|
+
from . import __version__
|
|
28
|
+
click.echo(f"aigroup-econ-mcp v{__version__}", err=True)
|
|
29
|
+
click.echo("Professional econometrics MCP tool", err=True)
|
|
30
|
+
click.echo("Author: AIGroup", err=True)
|
|
31
|
+
sys.exit(0)
|
|
32
|
+
|
|
33
|
+
# 创建MCP服务器
|
|
34
|
+
mcp_server = create_mcp_server()
|
|
35
|
+
|
|
36
|
+
# 设置调试模式
|
|
37
|
+
if debug:
|
|
38
|
+
mcp_server.settings.debug = True
|
|
39
|
+
click.echo(f"[DEBUG] 调试模式已启用", err=True)
|
|
40
|
+
|
|
41
|
+
# 根据传输协议启动服务器
|
|
42
|
+
if transport == 'stdio':
|
|
43
|
+
# stdio模式直接运行,不输出任何日志到stdout(MCP协议通信)
|
|
44
|
+
# 所有日志输出到stderr
|
|
45
|
+
from . import __version__
|
|
46
|
+
click.echo(f"[INFO] aigroup-econ-mcp v{__version__} starting...", err=True)
|
|
47
|
+
click.echo(f"[INFO] Transport: stdio (MCP protocol)", err=True)
|
|
48
|
+
if debug:
|
|
49
|
+
click.echo(f"[DEBUG] Debug mode enabled", err=True)
|
|
50
|
+
click.echo(f"[INFO] Server ready. Waiting for MCP client connection...", err=True)
|
|
51
|
+
mcp_server.run(transport='stdio')
|
|
52
|
+
|
|
53
|
+
elif transport == 'streamable-http':
|
|
54
|
+
# Streamable HTTP模式
|
|
55
|
+
click.echo(f"[INFO] Starting aigroup-econ-mcp server", err=True)
|
|
56
|
+
click.echo(f"[INFO] Professional econometrics MCP tool for AI data analysis", err=True)
|
|
57
|
+
click.echo(f"[INFO] Transport protocol: {transport}", err=True)
|
|
58
|
+
click.echo(f"[INFO] Service address: http://{host}:{port}", err=True)
|
|
59
|
+
if mount_path:
|
|
60
|
+
click.echo(f"[INFO] Mount path: {mount_path}", err=True)
|
|
61
|
+
|
|
62
|
+
mcp_server.run(
|
|
63
|
+
transport='streamable-http',
|
|
64
|
+
host=host,
|
|
65
|
+
port=port,
|
|
66
|
+
mount_path=mount_path or '/mcp'
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
elif transport == 'sse':
|
|
70
|
+
# SSE模式
|
|
71
|
+
click.echo(f"[INFO] Starting aigroup-econ-mcp server", err=True)
|
|
72
|
+
click.echo(f"[INFO] Professional econometrics MCP tool for AI data analysis", err=True)
|
|
73
|
+
click.echo(f"[INFO] Transport protocol: {transport}", err=True)
|
|
74
|
+
click.echo(f"[INFO] Service address: http://{host}:{port}", err=True)
|
|
75
|
+
if mount_path:
|
|
76
|
+
click.echo(f"[INFO] Mount path: {mount_path}", err=True)
|
|
77
|
+
|
|
78
|
+
mcp_server.run(
|
|
79
|
+
transport='sse',
|
|
80
|
+
host=host,
|
|
81
|
+
port=port,
|
|
82
|
+
mount_path=mount_path or '/sse'
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if __name__ == "__main__":
|
|
82
87
|
cli()
|
aigroup_econ_mcp/server.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
"""
|
|
2
3
|
AIGroup 计量经济学 MCP 服务器
|
|
3
4
|
使用最新的MCP特性提供专业计量经济学分析工具
|
|
@@ -15,7 +16,7 @@ from statsmodels.tsa import stattools
|
|
|
15
16
|
from scipy import stats
|
|
16
17
|
from pydantic import BaseModel, Field
|
|
17
18
|
|
|
18
|
-
from mcp.server.fastmcp import FastMCP, Context
|
|
19
|
+
from mcp.server.fastmcp import FastMCP, Context
|
|
19
20
|
from mcp.server.session import ServerSession
|
|
20
21
|
from mcp.types import CallToolResult, TextContent
|
|
21
22
|
|
|
@@ -70,12 +71,7 @@ class AppContext:
|
|
|
70
71
|
version: str = "0.1.0"
|
|
71
72
|
|
|
72
73
|
|
|
73
|
-
#
|
|
74
|
-
server_icon = Icon(
|
|
75
|
-
src="https://img.icons8.com/fluency/48/bar-chart.png",
|
|
76
|
-
mimeType="image/png",
|
|
77
|
-
sizes=["48x48"]
|
|
78
|
-
)
|
|
74
|
+
# 服务器图标(已移除,因为MCP库不再支持Icon类)
|
|
79
75
|
|
|
80
76
|
|
|
81
77
|
@asynccontextmanager
|
|
@@ -171,7 +167,7 @@ async def descriptive_statistics(
|
|
|
171
167
|
- 建议样本量 >= 30 以获得可靠的统计推断"""
|
|
172
168
|
)
|
|
173
169
|
]
|
|
174
|
-
) ->
|
|
170
|
+
) -> CallToolResult:
|
|
175
171
|
"""计算描述性统计量
|
|
176
172
|
|
|
177
173
|
📊 功能说明:
|
|
@@ -205,18 +201,26 @@ async def descriptive_statistics(
|
|
|
205
201
|
await ctx.info(f"开始计算描述性统计,处理 {len(data)} 个变量")
|
|
206
202
|
|
|
207
203
|
try:
|
|
204
|
+
# 数据验证
|
|
205
|
+
if not data:
|
|
206
|
+
raise ValueError("数据不能为空")
|
|
207
|
+
|
|
208
208
|
df = pd.DataFrame(data)
|
|
209
|
-
|
|
210
|
-
#
|
|
209
|
+
|
|
210
|
+
# 检查数据一致性
|
|
211
|
+
if len(df.columns) == 0:
|
|
212
|
+
raise ValueError("至少需要一个变量")
|
|
213
|
+
|
|
214
|
+
# 基础统计量 - 修复:返回所有变量的综合统计
|
|
211
215
|
result = DescriptiveStatsResult(
|
|
212
216
|
count=len(df),
|
|
213
|
-
mean=df.mean().
|
|
214
|
-
std=df.std().
|
|
215
|
-
min=df.min().
|
|
216
|
-
max=df.max().
|
|
217
|
-
median=df.median().
|
|
218
|
-
skewness=df.skew().
|
|
219
|
-
kurtosis=df.kurtosis().
|
|
217
|
+
mean=df.mean().mean(), # 所有变量的均值
|
|
218
|
+
std=df.std().mean(), # 所有变量的标准差均值
|
|
219
|
+
min=df.min().min(), # 所有变量的最小值
|
|
220
|
+
max=df.max().max(), # 所有变量的最大值
|
|
221
|
+
median=df.median().mean(), # 所有变量的中位数均值
|
|
222
|
+
skewness=df.skew().mean(), # 所有变量的偏度均值
|
|
223
|
+
kurtosis=df.kurtosis().mean() # 所有变量的峰度均值
|
|
220
224
|
)
|
|
221
225
|
|
|
222
226
|
# 计算相关系数矩阵
|
|
@@ -301,7 +305,7 @@ async def ols_regression(
|
|
|
301
305
|
- 建议使用有意义的名称以便解释结果"""
|
|
302
306
|
)
|
|
303
307
|
] = None
|
|
304
|
-
) ->
|
|
308
|
+
) -> CallToolResult:
|
|
305
309
|
"""执行普通最小二乘法(OLS)回归分析
|
|
306
310
|
|
|
307
311
|
📊 功能说明:
|
|
@@ -337,40 +341,63 @@ async def ols_regression(
|
|
|
337
341
|
await ctx.info(f"开始OLS回归分析,样本大小: {len(y_data)},自变量数量: {len(x_data[0]) if x_data else 0}")
|
|
338
342
|
|
|
339
343
|
try:
|
|
344
|
+
# 数据验证
|
|
345
|
+
if not y_data:
|
|
346
|
+
raise ValueError("因变量数据不能为空")
|
|
347
|
+
if not x_data:
|
|
348
|
+
raise ValueError("自变量数据不能为空")
|
|
349
|
+
if len(y_data) != len(x_data):
|
|
350
|
+
raise ValueError(f"因变量和自变量的观测数量不一致: y_data={len(y_data)}, x_data={len(x_data)}")
|
|
351
|
+
|
|
340
352
|
# 准备数据
|
|
341
|
-
X = np.
|
|
342
|
-
|
|
343
|
-
|
|
353
|
+
X = np.array(x_data)
|
|
354
|
+
y = np.array(y_data)
|
|
355
|
+
|
|
356
|
+
# 添加常数项
|
|
357
|
+
X_with_const = sm.add_constant(X)
|
|
344
358
|
|
|
345
359
|
# 拟合模型
|
|
346
|
-
model = sm.OLS(
|
|
347
|
-
|
|
348
|
-
# 构建结果
|
|
349
|
-
result = OLSRegressionResult(
|
|
350
|
-
rsquared=model.rsquared,
|
|
351
|
-
rsquared_adj=model.rsquared_adj,
|
|
352
|
-
f_statistic=model.fvalue,
|
|
353
|
-
f_pvalue=model.f_pvalue,
|
|
354
|
-
aic=model.aic,
|
|
355
|
-
bic=model.bic,
|
|
356
|
-
coefficients={}
|
|
357
|
-
)
|
|
360
|
+
model = sm.OLS(y, X_with_const).fit()
|
|
358
361
|
|
|
359
|
-
#
|
|
362
|
+
# 构建系数字典
|
|
360
363
|
conf_int = model.conf_int()
|
|
364
|
+
coefficients = {}
|
|
365
|
+
|
|
366
|
+
# 修复:正确处理feature_names为None的情况
|
|
367
|
+
if feature_names is None:
|
|
368
|
+
feature_names = [f"x{i+1}" for i in range(X.shape[1])]
|
|
369
|
+
elif len(feature_names) != X.shape[1]:
|
|
370
|
+
await ctx.warning(f"提供的feature_names数量({len(feature_names)})与自变量数量({X.shape[1]})不匹配,使用默认命名")
|
|
371
|
+
feature_names = [f"x{i+1}" for i in range(X.shape[1])]
|
|
372
|
+
|
|
361
373
|
for i, coef in enumerate(model.params):
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
"
|
|
369
|
-
"
|
|
374
|
+
if i == 0:
|
|
375
|
+
var_name = "const"
|
|
376
|
+
else:
|
|
377
|
+
var_name = feature_names[i-1]
|
|
378
|
+
|
|
379
|
+
coefficients[var_name] = {
|
|
380
|
+
"coef": float(coef), # 转换numpy.float64为float
|
|
381
|
+
"std_err": float(model.bse[i]),
|
|
382
|
+
"t_value": float(model.tvalues[i]),
|
|
383
|
+
"p_value": float(model.pvalues[i]),
|
|
384
|
+
"ci_lower": float(conf_int[i][0]),
|
|
385
|
+
"ci_upper": float(conf_int[i][1])
|
|
370
386
|
}
|
|
387
|
+
|
|
388
|
+
# 构建结果
|
|
389
|
+
result = OLSRegressionResult(
|
|
390
|
+
rsquared=float(model.rsquared),
|
|
391
|
+
rsquared_adj=float(model.rsquared_adj),
|
|
392
|
+
f_statistic=float(model.fvalue),
|
|
393
|
+
f_pvalue=float(model.f_pvalue),
|
|
394
|
+
aic=float(model.aic),
|
|
395
|
+
bic=float(model.bic),
|
|
396
|
+
coefficients=coefficients
|
|
397
|
+
)
|
|
371
398
|
|
|
372
399
|
await ctx.info("OLS回归分析完成")
|
|
373
|
-
|
|
400
|
+
|
|
374
401
|
return CallToolResult(
|
|
375
402
|
content=[
|
|
376
403
|
TextContent(
|
|
@@ -422,7 +449,8 @@ async def hypothesis_testing(
|
|
|
422
449
|
说明:
|
|
423
450
|
- 仅在双样本t检验时需要提供
|
|
424
451
|
- 单样本t检验时保持为None
|
|
425
|
-
-
|
|
452
|
+
- 两组数据可以
|
|
453
|
+
有不同的样本量
|
|
426
454
|
- ADF检验不需要第二组数据"""
|
|
427
455
|
)
|
|
428
456
|
] = None,
|
|
@@ -447,7 +475,7 @@ async def hypothesis_testing(
|
|
|
447
475
|
- 检验时间序列平稳性 → 使用 adf"""
|
|
448
476
|
)
|
|
449
477
|
] = "t_test"
|
|
450
|
-
) ->
|
|
478
|
+
) -> CallToolResult:
|
|
451
479
|
"""执行统计假设检验
|
|
452
480
|
|
|
453
481
|
📊 功能说明:
|
|
@@ -574,7 +602,7 @@ async def time_series_analysis(
|
|
|
574
602
|
- 日均气温数据"""
|
|
575
603
|
)
|
|
576
604
|
]
|
|
577
|
-
) ->
|
|
605
|
+
) -> CallToolResult:
|
|
578
606
|
"""时间序列统计分析
|
|
579
607
|
|
|
580
608
|
📊 功能说明:
|
|
@@ -632,19 +660,40 @@ async def time_series_analysis(
|
|
|
632
660
|
await ctx.info(f"开始时间序列分析,数据点数量: {len(data)}")
|
|
633
661
|
|
|
634
662
|
try:
|
|
663
|
+
# 数据验证
|
|
664
|
+
if not data:
|
|
665
|
+
raise ValueError("时间序列数据不能为空")
|
|
666
|
+
if len(data) < 5:
|
|
667
|
+
raise ValueError("时间序列数据至少需要5个观测点")
|
|
668
|
+
|
|
635
669
|
# ADF单位根检验
|
|
636
670
|
adf_result = stattools.adfuller(data)
|
|
637
671
|
|
|
638
672
|
# 自相关和偏自相关函数
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
673
|
+
# 修复:安全计算nlags,避免PACF计算失败
|
|
674
|
+
max_nlags = min(20, len(data) - 1, len(data) // 2)
|
|
675
|
+
if max_nlags < 1:
|
|
676
|
+
max_nlags = 1 # 确保至少计算1阶
|
|
677
|
+
|
|
678
|
+
# 修复:使用try-except处理ACF/PACF计算可能失败的情况
|
|
679
|
+
try:
|
|
680
|
+
acf_values = stattools.acf(data, nlags=max_nlags)
|
|
681
|
+
pacf_values = stattools.pacf(data, nlags=max_nlags)
|
|
682
|
+
except Exception as acf_error:
|
|
683
|
+
await ctx.warning(f"ACF/PACF计算遇到问题: {str(acf_error)},使用简化计算")
|
|
684
|
+
# 使用更简单的计算方法
|
|
685
|
+
acf_values = np.zeros(max_nlags + 1)
|
|
686
|
+
pacf_values = np.zeros(max_nlags + 1)
|
|
687
|
+
acf_values[0] = 1.0 # 0阶自相关总是1
|
|
688
|
+
pacf_values[0] = 1.0 # 0阶偏自相关总是1
|
|
689
|
+
|
|
690
|
+
# 转换numpy类型为Python原生类型
|
|
642
691
|
result = TimeSeriesStatsResult(
|
|
643
|
-
adf_statistic=adf_result[0],
|
|
644
|
-
adf_pvalue=adf_result[1],
|
|
645
|
-
stationary=adf_result[1] < 0.05,
|
|
646
|
-
acf=acf_values.tolist(),
|
|
647
|
-
pacf=pacf_values.tolist()
|
|
692
|
+
adf_statistic=float(adf_result[0]),
|
|
693
|
+
adf_pvalue=float(adf_result[1]),
|
|
694
|
+
stationary=bool(adf_result[1] < 0.05),
|
|
695
|
+
acf=[float(x) for x in acf_values.tolist()],
|
|
696
|
+
pacf=[float(x) for x in pacf_values.tolist()]
|
|
648
697
|
)
|
|
649
698
|
|
|
650
699
|
await ctx.info("时间序列分析完成")
|
|
@@ -730,7 +779,7 @@ async def correlation_analysis(
|
|
|
730
779
|
- 有序分类数据 → kendall"""
|
|
731
780
|
)
|
|
732
781
|
] = "pearson"
|
|
733
|
-
) ->
|
|
782
|
+
) -> CallToolResult:
|
|
734
783
|
"""变量间相关性分析
|
|
735
784
|
|
|
736
785
|
📊 功能说明:
|
|
@@ -773,16 +822,33 @@ async def correlation_analysis(
|
|
|
773
822
|
await ctx.info(f"开始相关性分析: {method}")
|
|
774
823
|
|
|
775
824
|
try:
|
|
825
|
+
# 数据验证
|
|
826
|
+
if not data:
|
|
827
|
+
raise ValueError("数据不能为空")
|
|
828
|
+
if len(data) < 2:
|
|
829
|
+
raise ValueError("至少需要2个变量进行相关性分析")
|
|
830
|
+
|
|
776
831
|
df = pd.DataFrame(data)
|
|
777
832
|
correlation_matrix = df.corr(method=method)
|
|
778
833
|
|
|
779
834
|
await ctx.info("相关性分析完成")
|
|
780
835
|
|
|
781
|
-
|
|
836
|
+
# 修复:返回正确的CallToolResult类型
|
|
837
|
+
return CallToolResult(
|
|
838
|
+
content=[
|
|
839
|
+
TextContent(
|
|
840
|
+
type="text",
|
|
841
|
+
text=f"{method.title()}相关系数矩阵:\n{correlation_matrix.round(4).to_string()}"
|
|
842
|
+
)
|
|
843
|
+
]
|
|
844
|
+
)
|
|
782
845
|
|
|
783
846
|
except Exception as e:
|
|
784
847
|
await ctx.error(f"相关性分析出错: {str(e)}")
|
|
785
|
-
return
|
|
848
|
+
return CallToolResult(
|
|
849
|
+
content=[TextContent(type="text", text=f"错误: {str(e)}")],
|
|
850
|
+
isError=True
|
|
851
|
+
)
|
|
786
852
|
|
|
787
853
|
|
|
788
854
|
def create_mcp_server() -> FastMCP:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"""
|
|
2
|
-
计量经济学工具模块
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from . import regression, statistics, time_series
|
|
6
|
-
|
|
1
|
+
"""
|
|
2
|
+
计量经济学工具模块
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from . import regression, statistics, time_series
|
|
6
|
+
|
|
7
7
|
__all__ = ["regression", "statistics", "time_series"]
|