aigroup-econ-mcp 0.4.2__tar.gz → 0.6.0__tar.gz

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.

Files changed (32) hide show
  1. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/PKG-INFO +2 -2
  2. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/pyproject.toml +2 -2
  3. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/__init__.py +2 -2
  4. aigroup_econ_mcp-0.6.0/src/aigroup_econ_mcp/server.py +452 -0
  5. aigroup_econ_mcp-0.6.0/src/aigroup_econ_mcp/tools/__init__.py +19 -0
  6. aigroup_econ_mcp-0.6.0/src/aigroup_econ_mcp/tools/tool_descriptions.py +750 -0
  7. aigroup_econ_mcp-0.4.2/src/aigroup_econ_mcp/server.py +0 -452
  8. aigroup_econ_mcp-0.4.2/src/aigroup_econ_mcp/tools/__init__.py +0 -18
  9. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/.gitignore +0 -0
  10. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/LICENSE +0 -0
  11. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/README.md +0 -0
  12. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/cli.py +0 -0
  13. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/config.py +0 -0
  14. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/base.py +0 -0
  15. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/cache.py +0 -0
  16. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/data_loader.py +0 -0
  17. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/file_parser.py +0 -0
  18. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/machine_learning.py +0 -0
  19. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/ml_ensemble.py +0 -0
  20. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/ml_evaluation.py +0 -0
  21. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/ml_models.py +0 -0
  22. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/ml_regularization.py +0 -0
  23. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/monitoring.py +0 -0
  24. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/optimized_example.py +0 -0
  25. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/panel_data.py +0 -0
  26. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/regression.py +0 -0
  27. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/statistics.py +0 -0
  28. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/time_series.py +0 -0
  29. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/timeout.py +0 -0
  30. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/tool_handlers.py +0 -0
  31. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/tool_registry.py +0 -0
  32. {aigroup_econ_mcp-0.4.2 → aigroup_econ_mcp-0.6.0}/src/aigroup_econ_mcp/tools/validation.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aigroup-econ-mcp
3
- Version: 0.4.2
4
- Summary: 专业计量经济学MCP工具 - 让大模型直接进行数据分析
3
+ Version: 0.6.0
4
+ Summary: 专业计量经济学MCP工具 - 让大模型直接进行数据分析(优化版:增强工具描述,提升大模型调用体验)
5
5
  Project-URL: Homepage, https://github.com/aigroup/aigroup-econ-mcp
6
6
  Project-URL: Repository, https://github.com/aigroup/aigroup-econ-mcp.git
7
7
  Project-URL: Issues, https://github.com/aigroup/aigroup-econ-mcp/issues
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "aigroup-econ-mcp"
7
- version = "0.4.2"
8
- description = "专业计量经济学MCP工具 - 让大模型直接进行数据分析"
7
+ version = "0.6.0"
8
+ description = "专业计量经济学MCP工具 - 让大模型直接进行数据分析(优化版:增强工具描述,提升大模型调用体验)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
11
  authors = [
@@ -10,9 +10,9 @@ AIGroup 计量经济学 MCP 服务
10
10
  - 模型诊断
11
11
  """
12
12
 
13
- __version__ = "0.4.2"
13
+ __version__ = "0.5.0"
14
14
  __author__ = "AIGroup"
15
- __description__ = "专业计量经济学MCP工具 - 让大模型直接进行数据分析"
15
+ __description__ = "专业计量经济学MCP工具 - 让大模型直接进行数据分析(重构版:工具描述模块化)"
16
16
 
17
17
  from .server import create_mcp_server
18
18
 
@@ -0,0 +1,452 @@
1
+ """
2
+ AIGroup 计量经济学 MCP 服务器 - 优化版
3
+ 使用组件化架构,代码量减少80%,同时自动支持文件输入
4
+ """
5
+
6
+ from typing import Dict, Any, Optional, List, Annotated
7
+ from collections.abc import AsyncIterator
8
+ from contextlib import asynccontextmanager
9
+ from dataclasses import dataclass
10
+
11
+ from pydantic import BaseModel, Field
12
+ from mcp.server.fastmcp import FastMCP, Context
13
+ from mcp.server.session import ServerSession
14
+ from mcp.types import CallToolResult, TextContent
15
+
16
+ # 导入工具处理器
17
+ from .tools.tool_handlers import (
18
+ handle_descriptive_statistics,
19
+ handle_ols_regression,
20
+ handle_hypothesis_testing,
21
+ handle_time_series_analysis,
22
+ handle_correlation_analysis,
23
+ handle_panel_fixed_effects,
24
+ handle_panel_random_effects,
25
+ handle_panel_hausman_test,
26
+ handle_panel_unit_root_test,
27
+ handle_var_model,
28
+ handle_vecm_model,
29
+ handle_garch_model,
30
+ handle_state_space_model,
31
+ handle_variance_decomposition,
32
+ handle_random_forest,
33
+ handle_gradient_boosting,
34
+ handle_lasso_regression,
35
+ handle_ridge_regression,
36
+ handle_cross_validation,
37
+ handle_feature_importance
38
+ )
39
+
40
+ # 导入装饰器和工具描述
41
+ from .tools.base import with_file_support_decorator as econometric_tool
42
+ from .tools.tool_descriptions import (
43
+ get_tool_description,
44
+ get_field_description,
45
+ DESCRIPTIVE_STATISTICS,
46
+ OLS_REGRESSION,
47
+ HYPOTHESIS_TESTING,
48
+ TIME_SERIES_ANALYSIS,
49
+ CORRELATION_ANALYSIS,
50
+ PANEL_FIXED_EFFECTS,
51
+ PANEL_RANDOM_EFFECTS,
52
+ PANEL_HAUSMAN_TEST,
53
+ PANEL_UNIT_ROOT_TEST,
54
+ VAR_MODEL_ANALYSIS,
55
+ VECM_MODEL_ANALYSIS,
56
+ GARCH_MODEL_ANALYSIS,
57
+ STATE_SPACE_MODEL_ANALYSIS,
58
+ VARIANCE_DECOMPOSITION_ANALYSIS,
59
+ RANDOM_FOREST_REGRESSION_ANALYSIS,
60
+ GRADIENT_BOOSTING_REGRESSION_ANALYSIS,
61
+ LASSO_REGRESSION_ANALYSIS,
62
+ RIDGE_REGRESSION_ANALYSIS,
63
+ CROSS_VALIDATION_ANALYSIS,
64
+ FEATURE_IMPORTANCE_ANALYSIS_TOOL
65
+ )
66
+
67
+
68
+ # 应用上下文
69
+ @dataclass
70
+ class AppContext:
71
+ """应用上下文,包含共享资源"""
72
+ config: Dict[str, Any]
73
+ version: str = "0.6.0"
74
+
75
+
76
+ @asynccontextmanager
77
+ async def lifespan(server: FastMCP) -> AsyncIterator[AppContext]:
78
+ """服务器生命周期管理"""
79
+ config = {
80
+ "max_sample_size": 10000,
81
+ "default_significance_level": 0.05,
82
+ "supported_tests": ["t_test", "f_test", "chi_square", "adf"],
83
+ "data_types": ["cross_section", "time_series", "panel"]
84
+ }
85
+ try:
86
+ yield AppContext(config=config, version="0.6.0")
87
+ finally:
88
+ pass
89
+
90
+
91
+ # 创建MCP服务器实例
92
+ mcp = FastMCP(
93
+ name="aigroup-econ-mcp",
94
+ instructions="Econometrics MCP Server - Provides data analysis with automatic file input support",
95
+ lifespan=lifespan
96
+ )
97
+
98
+
99
+ # ============================================================================
100
+ # 基础统计工具 (5个) - 自动支持文件输入
101
+ # ============================================================================
102
+
103
+ @mcp.tool()
104
+ @econometric_tool('multi_var_dict')
105
+ async def descriptive_statistics(
106
+ ctx: Context[ServerSession, AppContext],
107
+ file_path: Annotated[Optional[str], Field(default=None, description=DESCRIPTIVE_STATISTICS.get_field_description("file_path"))] = None,
108
+ file_content: Annotated[Optional[str], Field(default=None, description=DESCRIPTIVE_STATISTICS.get_field_description("file_content"))] = None,
109
+ file_format: Annotated[str, Field(default="auto", description=DESCRIPTIVE_STATISTICS.get_field_description("file_format"))] = "auto",
110
+ data: Annotated[Optional[Dict[str, List[float]]], Field(default=None, description=DESCRIPTIVE_STATISTICS.get_field_description("data"))] = None
111
+ ) -> CallToolResult:
112
+ """计算描述性统计量"""
113
+ return await handle_descriptive_statistics(ctx, data=data)
114
+
115
+
116
+ @mcp.tool()
117
+ @econometric_tool('regression')
118
+ async def ols_regression(
119
+ ctx: Context[ServerSession, AppContext],
120
+ file_path: Annotated[Optional[str], Field(default=None, description=OLS_REGRESSION.get_field_description("file_path"))] = None,
121
+ file_content: Annotated[Optional[str], Field(default=None, description=OLS_REGRESSION.get_field_description("file_content"))] = None,
122
+ file_format: Annotated[str, Field(default="auto", description=OLS_REGRESSION.get_field_description("file_format"))] = "auto",
123
+ y_data: Annotated[Optional[List[float]], Field(default=None, description=OLS_REGRESSION.get_field_description("y_data"))] = None,
124
+ x_data: Annotated[Optional[List[List[float]]], Field(default=None, description=OLS_REGRESSION.get_field_description("x_data"))] = None,
125
+ feature_names: Annotated[Optional[List[str]], Field(default=None, description=OLS_REGRESSION.get_field_description("feature_names"))] = None
126
+ ) -> CallToolResult:
127
+ """OLS回归分析"""
128
+ return await handle_ols_regression(ctx, y_data=y_data, x_data=x_data, feature_names=feature_names)
129
+
130
+
131
+ @mcp.tool()
132
+ @econometric_tool('single_var')
133
+ async def hypothesis_testing(
134
+ ctx: Context[ServerSession, AppContext],
135
+ file_path: Annotated[Optional[str], Field(default=None, description=HYPOTHESIS_TESTING.get_field_description("file_path"))] = None,
136
+ file_content: Annotated[Optional[str], Field(default=None, description=HYPOTHESIS_TESTING.get_field_description("file_content"))] = None,
137
+ file_format: Annotated[str, Field(default="auto", description=HYPOTHESIS_TESTING.get_field_description("file_format"))] = "auto",
138
+ data: Annotated[Optional[List[float]], Field(default=None, description=HYPOTHESIS_TESTING.get_field_description("data"))] = None,
139
+ data2: Annotated[Optional[List[float]], Field(default=None, description=HYPOTHESIS_TESTING.get_field_description("data2"))] = None,
140
+ test_type: Annotated[str, Field(default="t_test", description=HYPOTHESIS_TESTING.get_field_description("test_type"))] = "t_test"
141
+ ) -> CallToolResult:
142
+ """假设检验 - 支持文件或直接数据输入"""
143
+ return await handle_hypothesis_testing(ctx, data1=data, data2=data2, test_type=test_type)
144
+
145
+
146
+ @mcp.tool()
147
+ @econometric_tool('single_var')
148
+ async def time_series_analysis(
149
+ ctx: Context[ServerSession, AppContext],
150
+ file_path: Annotated[Optional[str], Field(default=None, description=TIME_SERIES_ANALYSIS.get_field_description("file_path"))] = None,
151
+ file_content: Annotated[Optional[str], Field(default=None, description=TIME_SERIES_ANALYSIS.get_field_description("file_content"))] = None,
152
+ file_format: Annotated[str, Field(default="auto", description=TIME_SERIES_ANALYSIS.get_field_description("file_format"))] = "auto",
153
+ data: Annotated[Optional[List[float]], Field(default=None, description=TIME_SERIES_ANALYSIS.get_field_description("data"))] = None
154
+ ) -> CallToolResult:
155
+ """时间序列分析 - 支持文件或直接数据输入"""
156
+ return await handle_time_series_analysis(ctx, data=data)
157
+
158
+
159
+ @mcp.tool()
160
+ @econometric_tool('multi_var_dict')
161
+ async def correlation_analysis(
162
+ ctx: Context[ServerSession, AppContext],
163
+ file_path: Annotated[Optional[str], Field(default=None, description=CORRELATION_ANALYSIS.get_field_description("file_path"))] = None,
164
+ file_content: Annotated[Optional[str], Field(default=None, description=CORRELATION_ANALYSIS.get_field_description("file_content"))] = None,
165
+ file_format: Annotated[str, Field(default="auto", description=CORRELATION_ANALYSIS.get_field_description("file_format"))] = "auto",
166
+ data: Annotated[Optional[Dict[str, List[float]]], Field(default=None, description=CORRELATION_ANALYSIS.get_field_description("data"))] = None,
167
+ method: Annotated[str, Field(default="pearson", description=CORRELATION_ANALYSIS.get_field_description("method"))] = "pearson"
168
+ ) -> CallToolResult:
169
+ """相关性分析 - 支持文件或直接数据输入"""
170
+ return await handle_correlation_analysis(ctx, data=data, method=method)
171
+
172
+
173
+ # ============================================================================
174
+ # 面板数据工具 (4个) - 自动支持文件输入
175
+ # ============================================================================
176
+
177
+ @mcp.tool()
178
+ @econometric_tool('panel')
179
+ async def panel_fixed_effects(
180
+ ctx: Context[ServerSession, AppContext],
181
+ file_path: Annotated[Optional[str], Field(default=None, description=PANEL_FIXED_EFFECTS.get_field_description("file_path"))] = None,
182
+ file_content: Annotated[Optional[str], Field(default=None, description=PANEL_FIXED_EFFECTS.get_field_description("file_content"))] = None,
183
+ file_format: Annotated[str, Field(default="auto", description=PANEL_FIXED_EFFECTS.get_field_description("file_format"))] = "auto",
184
+ y_data: Annotated[Optional[List[float]], Field(default=None, description=PANEL_FIXED_EFFECTS.get_field_description("y_data"))] = None,
185
+ x_data: Annotated[Optional[List[List[float]]], Field(default=None, description=PANEL_FIXED_EFFECTS.get_field_description("x_data"))] = None,
186
+ entity_ids: Annotated[Optional[List[str]], Field(default=None, description=PANEL_FIXED_EFFECTS.get_field_description("entity_ids"))] = None,
187
+ time_periods: Annotated[Optional[List[str]], Field(default=None, description=PANEL_FIXED_EFFECTS.get_field_description("time_periods"))] = None,
188
+ feature_names: Annotated[Optional[List[str]], Field(default=None, description=PANEL_FIXED_EFFECTS.get_field_description("feature_names"))] = None,
189
+ entity_effects: Annotated[bool, Field(default=True, description=PANEL_FIXED_EFFECTS.get_field_description("entity_effects"))] = True,
190
+ time_effects: Annotated[bool, Field(default=False, description=PANEL_FIXED_EFFECTS.get_field_description("time_effects"))] = False
191
+ ) -> CallToolResult:
192
+ """固定效应模型 - 支持文件输入"""
193
+ return await handle_panel_fixed_effects(ctx, y_data, x_data, entity_ids, time_periods,
194
+ feature_names, entity_effects, time_effects)
195
+
196
+
197
+ @mcp.tool()
198
+ @econometric_tool('panel')
199
+ async def panel_random_effects(
200
+ ctx: Context[ServerSession, AppContext],
201
+ file_path: Annotated[Optional[str], Field(default=None, description=PANEL_RANDOM_EFFECTS.get_field_description("file_path"))] = None,
202
+ file_content: Annotated[Optional[str], Field(default=None, description=PANEL_RANDOM_EFFECTS.get_field_description("file_content"))] = None,
203
+ file_format: Annotated[str, Field(default="auto", description=PANEL_RANDOM_EFFECTS.get_field_description("file_format"))] = "auto",
204
+ y_data: Annotated[Optional[List[float]], Field(default=None, description=PANEL_RANDOM_EFFECTS.get_field_description("y_data"))] = None,
205
+ x_data: Annotated[Optional[List[List[float]]], Field(default=None, description=PANEL_RANDOM_EFFECTS.get_field_description("x_data"))] = None,
206
+ entity_ids: Annotated[Optional[List[str]], Field(default=None, description=PANEL_RANDOM_EFFECTS.get_field_description("entity_ids"))] = None,
207
+ time_periods: Annotated[Optional[List[str]], Field(default=None, description=PANEL_RANDOM_EFFECTS.get_field_description("time_periods"))] = None,
208
+ feature_names: Annotated[Optional[List[str]], Field(default=None, description=PANEL_RANDOM_EFFECTS.get_field_description("feature_names"))] = None,
209
+ entity_effects: Annotated[bool, Field(default=True, description=PANEL_RANDOM_EFFECTS.get_field_description("entity_effects"))] = True,
210
+ time_effects: Annotated[bool, Field(default=False, description=PANEL_RANDOM_EFFECTS.get_field_description("time_effects"))] = False
211
+ ) -> CallToolResult:
212
+ """随机效应模型 - 支持文件输入"""
213
+ return await handle_panel_random_effects(ctx, y_data, x_data, entity_ids, time_periods,
214
+ feature_names, entity_effects, time_effects)
215
+
216
+
217
+ @mcp.tool()
218
+ @econometric_tool('panel')
219
+ async def panel_hausman_test(
220
+ ctx: Context[ServerSession, AppContext],
221
+ file_path: Annotated[Optional[str], Field(default=None, description=PANEL_HAUSMAN_TEST.get_field_description("file_path"))] = None,
222
+ file_content: Annotated[Optional[str], Field(default=None, description=PANEL_HAUSMAN_TEST.get_field_description("file_content"))] = None,
223
+ file_format: Annotated[str, Field(default="auto", description=PANEL_HAUSMAN_TEST.get_field_description("file_format"))] = "auto",
224
+ y_data: Annotated[Optional[List[float]], Field(default=None, description=PANEL_HAUSMAN_TEST.get_field_description("y_data"))] = None,
225
+ x_data: Annotated[Optional[List[List[float]]], Field(default=None, description=PANEL_HAUSMAN_TEST.get_field_description("x_data"))] = None,
226
+ entity_ids: Annotated[Optional[List[str]], Field(default=None, description=PANEL_HAUSMAN_TEST.get_field_description("entity_ids"))] = None,
227
+ time_periods: Annotated[Optional[List[str]], Field(default=None, description=PANEL_HAUSMAN_TEST.get_field_description("time_periods"))] = None,
228
+ feature_names: Annotated[Optional[List[str]], Field(default=None, description=PANEL_HAUSMAN_TEST.get_field_description("feature_names"))] = None
229
+ ) -> CallToolResult:
230
+ """Hausman检验 - 支持文件输入"""
231
+ return await handle_panel_hausman_test(ctx, y_data, x_data, entity_ids, time_periods, feature_names)
232
+
233
+
234
+ @mcp.tool()
235
+ @econometric_tool('panel') # 保持panel类型以获取entity_ids和time_periods
236
+ async def panel_unit_root_test(
237
+ ctx: Context[ServerSession, AppContext],
238
+ file_path: Annotated[Optional[str], Field(default=None, description=PANEL_UNIT_ROOT_TEST.get_field_description("file_path"))] = None,
239
+ file_content: Annotated[Optional[str], Field(default=None, description=PANEL_UNIT_ROOT_TEST.get_field_description("file_content"))] = None,
240
+ file_format: Annotated[str, Field(default="auto", description=PANEL_UNIT_ROOT_TEST.get_field_description("file_format"))] = "auto",
241
+ data: Annotated[Optional[List[float]], Field(default=None, description=PANEL_UNIT_ROOT_TEST.get_field_description("data"))] = None,
242
+ y_data: Annotated[Optional[List[float]], Field(default=None, description=PANEL_UNIT_ROOT_TEST.get_field_description("y_data"))] = None, # 从panel转换来的
243
+ x_data: Annotated[Optional[List[List[float]]], Field(default=None, description=PANEL_UNIT_ROOT_TEST.get_field_description("x_data"))] = None, # 从panel转换来的,忽略
244
+ entity_ids: Annotated[Optional[List[str]], Field(default=None, description=PANEL_UNIT_ROOT_TEST.get_field_description("entity_ids"))] = None,
245
+ time_periods: Annotated[Optional[List[str]], Field(default=None, description=PANEL_UNIT_ROOT_TEST.get_field_description("time_periods"))] = None,
246
+ feature_names: Annotated[Optional[List[str]], Field(default=None, description=PANEL_UNIT_ROOT_TEST.get_field_description("feature_names"))] = None, # 从panel转换来的,忽略
247
+ test_type: Annotated[str, Field(default="levinlin", description=PANEL_UNIT_ROOT_TEST.get_field_description("test_type"))] = "levinlin"
248
+ ) -> CallToolResult:
249
+ """面板单位根检验 - 支持文件输入"""
250
+ # 传递所有参数给handler
251
+ return await handle_panel_unit_root_test(
252
+ ctx,
253
+ data=data,
254
+ y_data=y_data,
255
+ entity_ids=entity_ids,
256
+ time_periods=time_periods,
257
+ test_type=test_type
258
+ )
259
+
260
+
261
+ # ============================================================================
262
+ # 高级时间序列工具 (5个) - 自动支持文件输入
263
+ # ============================================================================
264
+
265
+ @mcp.tool()
266
+ @econometric_tool('time_series')
267
+ async def var_model_analysis(
268
+ ctx: Context[ServerSession, AppContext],
269
+ file_path: Annotated[Optional[str], Field(default=None, description=VAR_MODEL_ANALYSIS.get_field_description("file_path"))] = None,
270
+ file_content: Annotated[Optional[str], Field(default=None, description=VAR_MODEL_ANALYSIS.get_field_description("file_content"))] = None,
271
+ file_format: Annotated[str, Field(default="auto", description=VAR_MODEL_ANALYSIS.get_field_description("file_format"))] = "auto",
272
+ data: Annotated[Optional[Dict[str, List[float]]], Field(default=None, description=VAR_MODEL_ANALYSIS.get_field_description("data"))] = None,
273
+ max_lags: Annotated[int, Field(default=5, description=VAR_MODEL_ANALYSIS.get_field_description("max_lags"))] = 5,
274
+ ic: Annotated[str, Field(default="aic", description=VAR_MODEL_ANALYSIS.get_field_description("ic"))] = "aic"
275
+ ) -> CallToolResult:
276
+ """VAR模型分析 - 支持文件输入"""
277
+ return await handle_var_model(ctx, data, max_lags, ic)
278
+
279
+
280
+ @mcp.tool()
281
+ @econometric_tool('time_series')
282
+ async def vecm_model_analysis(
283
+ ctx: Context[ServerSession, AppContext],
284
+ file_path: Annotated[Optional[str], Field(default=None, description=VECM_MODEL_ANALYSIS.get_field_description("file_path"))] = None,
285
+ file_content: Annotated[Optional[str], Field(default=None, description=VECM_MODEL_ANALYSIS.get_field_description("file_content"))] = None,
286
+ file_format: Annotated[str, Field(default="auto", description=VECM_MODEL_ANALYSIS.get_field_description("file_format"))] = "auto",
287
+ data: Annotated[Optional[Dict[str, List[float]]], Field(default=None, description=VECM_MODEL_ANALYSIS.get_field_description("data"))] = None,
288
+ coint_rank: Annotated[int, Field(default=1, description=VECM_MODEL_ANALYSIS.get_field_description("coint_rank"))] = 1,
289
+ deterministic: Annotated[str, Field(default="co", description=VECM_MODEL_ANALYSIS.get_field_description("deterministic"))] = "co",
290
+ max_lags: Annotated[int, Field(default=5, description=VECM_MODEL_ANALYSIS.get_field_description("max_lags"))] = 5
291
+ ) -> CallToolResult:
292
+ """VECM模型分析 - 支持文件输入"""
293
+ return await handle_vecm_model(ctx, data, coint_rank, deterministic, max_lags)
294
+
295
+
296
+ @mcp.tool()
297
+ @econometric_tool('single_var')
298
+ async def garch_model_analysis(
299
+ ctx: Context[ServerSession, AppContext],
300
+ file_path: Annotated[Optional[str], Field(default=None, description=GARCH_MODEL_ANALYSIS.get_field_description("file_path"))] = None,
301
+ file_content: Annotated[Optional[str], Field(default=None, description=GARCH_MODEL_ANALYSIS.get_field_description("file_content"))] = None,
302
+ file_format: Annotated[str, Field(default="auto", description=GARCH_MODEL_ANALYSIS.get_field_description("file_format"))] = "auto",
303
+ data: Annotated[Optional[List[float]], Field(default=None, description=GARCH_MODEL_ANALYSIS.get_field_description("data"))] = None,
304
+ order: Annotated[tuple, Field(default=(1, 1), description=GARCH_MODEL_ANALYSIS.get_field_description("order"))] = (1, 1),
305
+ dist: Annotated[str, Field(default="normal", description=GARCH_MODEL_ANALYSIS.get_field_description("dist"))] = "normal"
306
+ ) -> CallToolResult:
307
+ """GARCH模型分析 - 支持文件输入"""
308
+ return await handle_garch_model(ctx, data, order, dist)
309
+
310
+
311
+ @mcp.tool()
312
+ @econometric_tool('single_var')
313
+ async def state_space_model_analysis(
314
+ ctx: Context[ServerSession, AppContext],
315
+ file_path: Annotated[Optional[str], Field(default=None, description=STATE_SPACE_MODEL_ANALYSIS.get_field_description("file_path"))] = None,
316
+ file_content: Annotated[Optional[str], Field(default=None, description=STATE_SPACE_MODEL_ANALYSIS.get_field_description("file_content"))] = None,
317
+ file_format: Annotated[str, Field(default="auto", description=STATE_SPACE_MODEL_ANALYSIS.get_field_description("file_format"))] = "auto",
318
+ data: Annotated[Optional[List[float]], Field(default=None, description=STATE_SPACE_MODEL_ANALYSIS.get_field_description("data"))] = None,
319
+ state_dim: Annotated[int, Field(default=1, description=STATE_SPACE_MODEL_ANALYSIS.get_field_description("state_dim"))] = 1,
320
+ observation_dim: Annotated[int, Field(default=1, description=STATE_SPACE_MODEL_ANALYSIS.get_field_description("observation_dim"))] = 1,
321
+ trend: Annotated[bool, Field(default=True, description=STATE_SPACE_MODEL_ANALYSIS.get_field_description("trend"))] = True,
322
+ seasonal: Annotated[bool, Field(default=False, description=STATE_SPACE_MODEL_ANALYSIS.get_field_description("seasonal"))] = False,
323
+ period: Annotated[int, Field(default=12, description=STATE_SPACE_MODEL_ANALYSIS.get_field_description("period"))] = 12
324
+ ) -> CallToolResult:
325
+ """状态空间模型分析 - 支持文件输入"""
326
+ return await handle_state_space_model(ctx, data, state_dim, observation_dim, trend, seasonal, period)
327
+
328
+
329
+ @mcp.tool()
330
+ @econometric_tool('time_series')
331
+ async def variance_decomposition_analysis(
332
+ ctx: Context[ServerSession, AppContext],
333
+ file_path: Annotated[Optional[str], Field(default=None, description=VARIANCE_DECOMPOSITION_ANALYSIS.get_field_description("file_path"))] = None,
334
+ file_content: Annotated[Optional[str], Field(default=None, description=VARIANCE_DECOMPOSITION_ANALYSIS.get_field_description("file_content"))] = None,
335
+ file_format: Annotated[str, Field(default="auto", description=VARIANCE_DECOMPOSITION_ANALYSIS.get_field_description("file_format"))] = "auto",
336
+ data: Annotated[Optional[Dict[str, List[float]]], Field(default=None, description=VARIANCE_DECOMPOSITION_ANALYSIS.get_field_description("data"))] = None,
337
+ periods: Annotated[int, Field(default=10, description=VARIANCE_DECOMPOSITION_ANALYSIS.get_field_description("periods"))] = 10,
338
+ max_lags: Annotated[int, Field(default=5, description=VARIANCE_DECOMPOSITION_ANALYSIS.get_field_description("max_lags"))] = 5
339
+ ) -> CallToolResult:
340
+ """方差分解分析 - 支持文件输入"""
341
+ return await handle_variance_decomposition(ctx, data, periods, max_lags)
342
+
343
+
344
+ # ============================================================================
345
+ # 机器学习工具 (6个) - 自动支持文件输入
346
+ # ============================================================================
347
+
348
+ @mcp.tool()
349
+ @econometric_tool('regression')
350
+ async def random_forest_regression_analysis(
351
+ ctx: Context[ServerSession, AppContext],
352
+ file_path: Annotated[Optional[str], Field(default=None, description=RANDOM_FOREST_REGRESSION_ANALYSIS.get_field_description("file_path"))] = None,
353
+ file_content: Annotated[Optional[str], Field(default=None, description=RANDOM_FOREST_REGRESSION_ANALYSIS.get_field_description("file_content"))] = None,
354
+ file_format: Annotated[str, Field(default="auto", description=RANDOM_FOREST_REGRESSION_ANALYSIS.get_field_description("file_format"))] = "auto",
355
+ y_data: Annotated[Optional[List[float]], Field(default=None, description=RANDOM_FOREST_REGRESSION_ANALYSIS.get_field_description("y_data"))] = None,
356
+ x_data: Annotated[Optional[List[List[float]]], Field(default=None, description=RANDOM_FOREST_REGRESSION_ANALYSIS.get_field_description("x_data"))] = None,
357
+ feature_names: Annotated[Optional[List[str]], Field(default=None, description=RANDOM_FOREST_REGRESSION_ANALYSIS.get_field_description("feature_names"))] = None,
358
+ n_estimators: Annotated[int, Field(default=100, description=RANDOM_FOREST_REGRESSION_ANALYSIS.get_field_description("n_estimators"))] = 100,
359
+ max_depth: Annotated[Optional[int], Field(default=None, description=RANDOM_FOREST_REGRESSION_ANALYSIS.get_field_description("max_depth"))] = None
360
+ ) -> CallToolResult:
361
+ """随机森林回归 - 支持文件输入"""
362
+ return await handle_random_forest(ctx, y_data, x_data, feature_names, n_estimators, max_depth)
363
+
364
+
365
+ @mcp.tool()
366
+ @econometric_tool('regression')
367
+ async def gradient_boosting_regression_analysis(
368
+ ctx: Context[ServerSession, AppContext],
369
+ file_path: Annotated[Optional[str], Field(default=None, description=GRADIENT_BOOSTING_REGRESSION_ANALYSIS.get_field_description("file_path"))] = None,
370
+ file_content: Annotated[Optional[str], Field(default=None, description=GRADIENT_BOOSTING_REGRESSION_ANALYSIS.get_field_description("file_content"))] = None,
371
+ file_format: Annotated[str, Field(default="auto", description=GRADIENT_BOOSTING_REGRESSION_ANALYSIS.get_field_description("file_format"))] = "auto",
372
+ y_data: Annotated[Optional[List[float]], Field(default=None, description=GRADIENT_BOOSTING_REGRESSION_ANALYSIS.get_field_description("y_data"))] = None,
373
+ x_data: Annotated[Optional[List[List[float]]], Field(default=None, description=GRADIENT_BOOSTING_REGRESSION_ANALYSIS.get_field_description("x_data"))] = None,
374
+ feature_names: Annotated[Optional[List[str]], Field(default=None, description=GRADIENT_BOOSTING_REGRESSION_ANALYSIS.get_field_description("feature_names"))] = None,
375
+ n_estimators: Annotated[int, Field(default=100, description=GRADIENT_BOOSTING_REGRESSION_ANALYSIS.get_field_description("n_estimators"))] = 100,
376
+ learning_rate: Annotated[float, Field(default=0.1, description=GRADIENT_BOOSTING_REGRESSION_ANALYSIS.get_field_description("learning_rate"))] = 0.1,
377
+ max_depth: Annotated[int, Field(default=3, description=GRADIENT_BOOSTING_REGRESSION_ANALYSIS.get_field_description("max_depth"))] = 3
378
+ ) -> CallToolResult:
379
+ """梯度提升树回归 - 支持文件输入"""
380
+ return await handle_gradient_boosting(ctx, y_data, x_data, feature_names, n_estimators, learning_rate, max_depth)
381
+
382
+
383
+ @mcp.tool()
384
+ @econometric_tool('regression')
385
+ async def lasso_regression_analysis(
386
+ ctx: Context[ServerSession, AppContext],
387
+ file_path: Annotated[Optional[str], Field(default=None, description=LASSO_REGRESSION_ANALYSIS.get_field_description("file_path"))] = None,
388
+ file_content: Annotated[Optional[str], Field(default=None, description=LASSO_REGRESSION_ANALYSIS.get_field_description("file_content"))] = None,
389
+ file_format: Annotated[str, Field(default="auto", description=LASSO_REGRESSION_ANALYSIS.get_field_description("file_format"))] = "auto",
390
+ y_data: Annotated[Optional[List[float]], Field(default=None, description=LASSO_REGRESSION_ANALYSIS.get_field_description("y_data"))] = None,
391
+ x_data: Annotated[Optional[List[List[float]]], Field(default=None, description=LASSO_REGRESSION_ANALYSIS.get_field_description("x_data"))] = None,
392
+ feature_names: Annotated[Optional[List[str]], Field(default=None, description=LASSO_REGRESSION_ANALYSIS.get_field_description("feature_names"))] = None,
393
+ alpha: Annotated[float, Field(default=1.0, description=LASSO_REGRESSION_ANALYSIS.get_field_description("alpha"))] = 1.0
394
+ ) -> CallToolResult:
395
+ """Lasso回归 - 支持文件输入"""
396
+ return await handle_lasso_regression(ctx, y_data, x_data, feature_names, alpha)
397
+
398
+
399
+ @mcp.tool()
400
+ @econometric_tool('regression')
401
+ async def ridge_regression_analysis(
402
+ ctx: Context[ServerSession, AppContext],
403
+ file_path: Annotated[Optional[str], Field(default=None, description=RIDGE_REGRESSION_ANALYSIS.get_field_description("file_path"))] = None,
404
+ file_content: Annotated[Optional[str], Field(default=None, description=RIDGE_REGRESSION_ANALYSIS.get_field_description("file_content"))] = None,
405
+ file_format: Annotated[str, Field(default="auto", description=RIDGE_REGRESSION_ANALYSIS.get_field_description("file_format"))] = "auto",
406
+ y_data: Annotated[Optional[List[float]], Field(default=None, description=RIDGE_REGRESSION_ANALYSIS.get_field_description("y_data"))] = None,
407
+ x_data: Annotated[Optional[List[List[float]]], Field(default=None, description=RIDGE_REGRESSION_ANALYSIS.get_field_description("x_data"))] = None,
408
+ feature_names: Annotated[Optional[List[str]], Field(default=None, description=RIDGE_REGRESSION_ANALYSIS.get_field_description("feature_names"))] = None,
409
+ alpha: Annotated[float, Field(default=1.0, description=RIDGE_REGRESSION_ANALYSIS.get_field_description("alpha"))] = 1.0
410
+ ) -> CallToolResult:
411
+ """Ridge回归 - 支持文件输入"""
412
+ return await handle_ridge_regression(ctx, y_data, x_data, feature_names, alpha)
413
+
414
+
415
+ @mcp.tool()
416
+ @econometric_tool('regression')
417
+ async def cross_validation_analysis(
418
+ ctx: Context[ServerSession, AppContext],
419
+ file_path: Annotated[Optional[str], Field(default=None, description=CROSS_VALIDATION_ANALYSIS.get_field_description("file_path"))] = None,
420
+ file_content: Annotated[Optional[str], Field(default=None, description=CROSS_VALIDATION_ANALYSIS.get_field_description("file_content"))] = None,
421
+ file_format: Annotated[str, Field(default="auto", description=CROSS_VALIDATION_ANALYSIS.get_field_description("file_format"))] = "auto",
422
+ y_data: Annotated[Optional[List[float]], Field(default=None, description=CROSS_VALIDATION_ANALYSIS.get_field_description("y_data"))] = None,
423
+ x_data: Annotated[Optional[List[List[float]]], Field(default=None, description=CROSS_VALIDATION_ANALYSIS.get_field_description("x_data"))] = None,
424
+ feature_names: Annotated[Optional[List[str]], Field(default=None, description=CROSS_VALIDATION_ANALYSIS.get_field_description("feature_names"))] = None,
425
+ model_type: Annotated[str, Field(default="random_forest", description=CROSS_VALIDATION_ANALYSIS.get_field_description("model_type"))] = "random_forest",
426
+ cv_folds: Annotated[int, Field(default=5, description=CROSS_VALIDATION_ANALYSIS.get_field_description("cv_folds"))] = 5,
427
+ scoring: Annotated[str, Field(default="r2", description=CROSS_VALIDATION_ANALYSIS.get_field_description("scoring"))] = "r2"
428
+ ) -> CallToolResult:
429
+ """交叉验证 - 支持文件输入"""
430
+ return await handle_cross_validation(ctx, y_data, x_data, model_type, cv_folds, scoring)
431
+
432
+
433
+ @mcp.tool()
434
+ @econometric_tool('regression')
435
+ async def feature_importance_analysis_tool(
436
+ ctx: Context[ServerSession, AppContext],
437
+ file_path: Annotated[Optional[str], Field(default=None, description=FEATURE_IMPORTANCE_ANALYSIS_TOOL.get_field_description("file_path"))] = None,
438
+ file_content: Annotated[Optional[str], Field(default=None, description=FEATURE_IMPORTANCE_ANALYSIS_TOOL.get_field_description("file_content"))] = None,
439
+ file_format: Annotated[str, Field(default="auto", description=FEATURE_IMPORTANCE_ANALYSIS_TOOL.get_field_description("file_format"))] = "auto",
440
+ y_data: Annotated[Optional[List[float]], Field(default=None, description=FEATURE_IMPORTANCE_ANALYSIS_TOOL.get_field_description("y_data"))] = None,
441
+ x_data: Annotated[Optional[List[List[float]]], Field(default=None, description=FEATURE_IMPORTANCE_ANALYSIS_TOOL.get_field_description("x_data"))] = None,
442
+ feature_names: Annotated[Optional[List[str]], Field(default=None, description=FEATURE_IMPORTANCE_ANALYSIS_TOOL.get_field_description("feature_names"))] = None,
443
+ method: Annotated[str, Field(default="random_forest", description=FEATURE_IMPORTANCE_ANALYSIS_TOOL.get_field_description("method"))] = "random_forest",
444
+ top_k: Annotated[int, Field(default=5, description=FEATURE_IMPORTANCE_ANALYSIS_TOOL.get_field_description("top_k"))] = 5
445
+ ) -> CallToolResult:
446
+ """特征重要性分析 - 支持文件输入"""
447
+ return await handle_feature_importance(ctx, y_data, x_data, feature_names, method, top_k)
448
+
449
+
450
+ def create_mcp_server() -> FastMCP:
451
+ """创建并返回MCP服务器实例"""
452
+ return mcp
@@ -0,0 +1,19 @@
1
+ """
2
+ 计量经济学工具模块
3
+ """
4
+
5
+ from . import regression, statistics, time_series, machine_learning, panel_data
6
+ from . import validation, cache, monitoring, file_parser, tool_descriptions
7
+
8
+ __all__ = [
9
+ "regression",
10
+ "statistics",
11
+ "time_series",
12
+ "machine_learning",
13
+ "panel_data",
14
+ "validation",
15
+ "cache",
16
+ "monitoring",
17
+ "file_parser",
18
+ "tool_descriptions"
19
+ ]