national-stats-mcp 1.0.2 → 1.2.0
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.
- package/README.md +176 -6
- package/dist/api-client.d.ts +67 -2
- package/dist/api-client.js +305 -8
- package/dist/index.js +1 -1
- package/dist/types.d.ts +165 -0
- package/dist/types.js +27 -0
- package/national-stats-mcp-1.1.0.tgz +0 -0
- package/package.json +2 -2
- package/zb.json +0 -226
package/README.md
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
# 国家统计局MCP/Agent数据获取工具
|
|
2
2
|
|
|
3
3
|
## 项目概述
|
|
4
|
-
本项目是一个基于MCP(Model Context Protocol)协议的国家统计局数据获取服务,为AI Agent提供直接访问国家统计局API
|
|
4
|
+
本项目是一个基于MCP(Model Context Protocol)协议的国家统计局数据获取服务,为AI Agent提供直接访问国家统计局API的功能。项目**同时支持新版API (V2.0)和旧版API**,支持获取各种统计数据,包含关键词搜索、分类浏览、时间维度查询等功能。
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
### 🆕 新版 API V2.0 (2026.03.27更新)
|
|
7
|
+
新版API采用UUID标识符架构,具有以下特点:
|
|
8
|
+
- ✅ **UUID标识**: 使用UUID作为唯一标识符,摒弃旧的层级代码系统
|
|
9
|
+
- ✅ **三步查询**: 树形导航 → 指标元数据 → 批量取值
|
|
10
|
+
- ✅ **时间分片**: 同一指标按5年或统计制度变革周期分割,支持更精细的数据管理
|
|
11
|
+
- ✅ **批量查询**: 支持一次性查询多个指标、多个时间点数据
|
|
12
|
+
- ✅ **缓存优化**: 内置智能缓存机制,提升查询效率
|
|
13
|
+
- ✅ **完整元数据**: 包含统计口径说明、单位信息等关键元数据
|
|
14
|
+
|
|
15
|
+
### 旧版 API (向后兼容)
|
|
7
16
|
- ✅ 关键词搜索:直接搜索获取指标代码及最新值(推荐用于快速查询)
|
|
8
17
|
- ✅ 树形分类:可浏览和递归获取所有分类/指标体系
|
|
18
|
+
- ✅ 预遍历数据:提供完整的预遍历分类编码体系,可直接读取使用(减少递归调用)
|
|
9
19
|
- ✅ 时间范围:可查询各数据库对应可用时间维度
|
|
10
20
|
- ✅ 标准API:遵循国家统计局接口文档的全部规范
|
|
11
21
|
- ✅ 容错机制:内置重试逻辑、请求延迟、数据验证等功能
|
|
@@ -61,12 +71,129 @@ node dist/index.js --port 8080
|
|
|
61
71
|
批量获取多个统计指标的数据。
|
|
62
72
|
- 参数:`queries`(必需)- 查询参数数组
|
|
63
73
|
|
|
74
|
+
## 🆕 新版 API V2.0 使用指南
|
|
75
|
+
|
|
76
|
+
### 核心概念
|
|
77
|
+
|
|
78
|
+
新版API引入以下关键概念:
|
|
79
|
+
|
|
80
|
+
| 标识符 | 说明 |
|
|
81
|
+
|--------|------|
|
|
82
|
+
| **pid** | 父节点ID,用于在目录树中向下展开 |
|
|
83
|
+
| **cid** | 数据集ID,代表一个叶子节点(特定指标+地区+时间段) |
|
|
84
|
+
| **indicatorId** | 具体指标ID,代表数据集中的某一列 |
|
|
85
|
+
| **时间分片** | 同一指标按时间分成多个cid(如2021-2025, 2026-至今) |
|
|
86
|
+
|
|
87
|
+
### 新版API客户端使用示例
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { NewStatsApiClient, CategoryCode } from './src/api-client';
|
|
91
|
+
|
|
92
|
+
// 创建客户端实例
|
|
93
|
+
const client = new NewStatsApiClient();
|
|
94
|
+
|
|
95
|
+
// 方式一:一步到位查询(推荐)
|
|
96
|
+
async function quickQuery() {
|
|
97
|
+
const result = await client.searchAndGet(
|
|
98
|
+
'CPI', // 关键词
|
|
99
|
+
'居民消费价格指数', // 指标名称(可选)
|
|
100
|
+
'202601MM', // 起始时间(可选)
|
|
101
|
+
'202603MM' // 结束时间(可选)
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
console.log('数据集ID:', result.cid);
|
|
105
|
+
console.log('指标信息:', result.indicator);
|
|
106
|
+
console.log('数据:', result.data);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 方式二:分步查询(适合复杂场景)
|
|
110
|
+
async function stepByStep() {
|
|
111
|
+
// 1. 搜索定位数据集
|
|
112
|
+
const searchResults = await client.search({
|
|
113
|
+
search: 'GDP',
|
|
114
|
+
pageSize: 10
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// 2. 获取树结构(遍历分类)
|
|
118
|
+
const treeNodes = await client.getTree({
|
|
119
|
+
code: CategoryCode.MONTHLY, // 月度数据
|
|
120
|
+
pid: '' // 根节点
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// 3. 获取指标列表
|
|
124
|
+
const indicators = await client.getIndicators({
|
|
125
|
+
cid: 'your-cid-here'
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// 4. 查询数据
|
|
129
|
+
const data = await client.getData({
|
|
130
|
+
cid: 'your-cid-here',
|
|
131
|
+
indicatorIds: ['indicator-id-1', 'indicator-id-2'],
|
|
132
|
+
das: [{ text: '全国', value: '000000000000' }],
|
|
133
|
+
dts: ['202601MM-202612MM']
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// 方式三:获取所有叶子节点(慎用,耗时)
|
|
138
|
+
async function getAllLeafs() {
|
|
139
|
+
const leafs = await client.getAllLeafNodes(CategoryCode.MONTHLY);
|
|
140
|
+
console.log(`共找到 ${leafs.length} 个数据集`);
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 时间编码格式
|
|
145
|
+
|
|
146
|
+
新版API使用特定的时间编码格式:
|
|
147
|
+
|
|
148
|
+
| 类型 | 格式 | 示例 |
|
|
149
|
+
|------|------|------|
|
|
150
|
+
| 月度 | YYYYMM + MM | 202602MM (2026年2月) |
|
|
151
|
+
| 季度 | YYYYQ + SS | 20254SS (2025年第4季度) |
|
|
152
|
+
| 年度 | YYYY + YY | 2025YY (2025年) |
|
|
153
|
+
| 范围 | Start-End | 202601MM-202612MM |
|
|
154
|
+
|
|
155
|
+
### 分类代码
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
enum CategoryCode {
|
|
159
|
+
MONTHLY = '1', // 月度数据
|
|
160
|
+
QUARTERLY = '2', // 季度数据
|
|
161
|
+
YEARLY = '3', // 年度数据
|
|
162
|
+
PROVINCE_QUARTERLY = '5', // 分省季度
|
|
163
|
+
PROVINCE_YEARLY = '6', // 分省年度
|
|
164
|
+
OTHER = '7', // 其他/普查
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 最佳实践
|
|
169
|
+
|
|
170
|
+
1. **优先使用搜索接口**: 用 `search()` 快速定位cid,避免全量遍历树
|
|
171
|
+
2. **处理时间分片**: 同一指标可能有多个cid,需按时间拼接数据
|
|
172
|
+
3. **批量请求**: `getData()` 支持多个indicatorIds,一次请求获取多个指标
|
|
173
|
+
4. **关注元数据**: 查看indicator的`i_mark`字段了解统计口径
|
|
174
|
+
5. **利用缓存**: 客户端内置缓存,树结构和指标列表会自动缓存
|
|
175
|
+
|
|
64
176
|
## 模块介绍
|
|
65
177
|
- `src/index.ts`: MCP服务器主入口,实现MCP协议规范
|
|
66
|
-
- `src/api-client.ts`: 国家统计局API
|
|
178
|
+
- `src/api-client.ts`: 国家统计局API交互模块,提供完整的数据获取功能
|
|
179
|
+
- **NewStatsApiClient**: 新版API V2.0客户端(推荐)
|
|
180
|
+
- **StatsApiClient**: 旧版API客户端(向后兼容)
|
|
181
|
+
- `src/types.ts`: 完整的类型定义,包含新旧两版API的数据结构
|
|
67
182
|
|
|
68
183
|
## 遵循国家统计局API标准
|
|
69
|
-
|
|
184
|
+
|
|
185
|
+
### 新版 API V2.0
|
|
186
|
+
项目严格实现新版API接口规范:
|
|
187
|
+
- 搜索接口 `/external/query` 用于关键词搜索和快速定位cid
|
|
188
|
+
- 树遍历接口 `/new/queryIndexTreeAsync` 用于浏览分类树和获取cid
|
|
189
|
+
- 指标查询接口 `/new/queryIndicatorsByCid` 用于获取指标列表
|
|
190
|
+
- 数据查询接口 `/getEsDataByCidAndDt` 用于批量获取时间序列数据
|
|
191
|
+
- 内置缓存机制:树结构24小时,指标列表12小时
|
|
192
|
+
- UUID标识符系统和时间分片机制
|
|
193
|
+
- 完整的错误处理和重试逻辑
|
|
194
|
+
|
|
195
|
+
### 旧版 API (向后兼容)
|
|
196
|
+
项目严格实现旧版API接口规范:
|
|
70
197
|
- 搜索接口 `/search.htm` 用于关键词查找和快速获取最新值
|
|
71
198
|
- 分类接口 `/easyquery.htm` 用于遍历指标分类树
|
|
72
199
|
- 数据接口 `/easyquery.htm` 用于查询历史时间序列
|
|
@@ -76,15 +203,27 @@ node dist/index.js --port 8080
|
|
|
76
203
|
|
|
77
204
|
## 数据编码对应
|
|
78
205
|
- `dbcode.json`: 存储数据库代码及其相应的名称
|
|
79
|
-
- `zb.json`: 包含用于查询不同类型国家数据的类别和子类别代码
|
|
80
206
|
- `wbcode.json`: 维度代码定义
|
|
207
|
+
- **预遍历编码数据**:
|
|
208
|
+
- **npm包中不包含**: `nbs_data_repository/` (因文件体积较大)
|
|
209
|
+
- **需从GitHub获取**: 预先遍历获取的完整的国家统计局分类编码体系(可减少递归调用)
|
|
210
|
+
- 完整数据集在 GitHub 仓库中,请从 [GitHub 仓库](https://github.com/Ddhjx-code/notional_data) 下载
|
|
211
|
+
- `csnd/`, `csyd/`: 城市统计数据(年度、月度)
|
|
212
|
+
- `fsnd/`, `fsyd/`: 分省年度、月度数据
|
|
213
|
+
- `hgnd/`, `hgjd/`, `hgyd/`: 国民经济核算数据(年度、季度、月度)
|
|
214
|
+
- `gjnd/`, `gjyd/`, `gatnd/`, `gatyd/`: 国际、港澳台统计数据(年度、月度)
|
|
215
|
+
- 每个数据库目录下包含预遍历的分类编码(以JSON文件形式存储):
|
|
216
|
+
- 如 `nbs_data_repository/hgjd/A01.json` 包含A01分类下的具体指标
|
|
217
|
+
- 文件内容格式: `[{"id": "指标ID", "pid": "父级ID", "name": "指标名", "isParent": 是否为父级}]`
|
|
81
218
|
|
|
82
219
|
## 为AI Agent的使用
|
|
83
220
|
本项目专门设计为MCP服务器,可以直接集成到AI Agent系统中,提供国家统计局数据查询能力。Agent可根据使用场景选择最合适的工具:
|
|
84
221
|
|
|
85
222
|
- **快速查询**:使用 `search_statistics` 直接通过关键词获取指标和最新值
|
|
86
|
-
- **分类浏览**:使用 `get_statistics_categories`
|
|
223
|
+
- **分类浏览**:使用 `get_statistics_categories` 获取分类体系;对于完整指标体系,可优先参考 `nbs_data_repository` 目录下的预遍历编码文件
|
|
224
|
+
- **递归获取**:`get_statistics_leaf_categories` 用于递归获取所有叶子节点(由于已有预遍历数据,此功能使用频率较低)
|
|
87
225
|
- **深度查询**:使用 `get_statistics_time_options` 和 `get_statistics_data` 获取历史序列数据
|
|
226
|
+
- **预遍历数据**:`nbs_data_repository` 目录下已预存各类统计数据库的详细分类编码,可直接读取使用,避免实时API递归调用
|
|
88
227
|
|
|
89
228
|
## 开发
|
|
90
229
|
进行开发时可使用:
|
|
@@ -92,6 +231,37 @@ node dist/index.js --port 8080
|
|
|
92
231
|
npm run dev
|
|
93
232
|
```
|
|
94
233
|
|
|
234
|
+
## 使用建议
|
|
235
|
+
|
|
236
|
+
对于AI Agent开发者,根据使用方式采用不同策略:
|
|
237
|
+
|
|
238
|
+
### npm 包使用(核心库):
|
|
239
|
+
1. **安装**: `npm install national-stats-mcp`
|
|
240
|
+
2. **功能**: 使用 API 工具进行动态数据查询
|
|
241
|
+
3. **使用**: `search_statistics`、`get_statistics_data` 等
|
|
242
|
+
4. **递归调用**: 当需要完整分类体系时,使用 `get_statistics_leaf_categories`
|
|
243
|
+
|
|
244
|
+
### GitHub 仓库使用(完整版本):
|
|
245
|
+
1. **克隆完整仓库**:
|
|
246
|
+
```bash
|
|
247
|
+
git clone https://github.com/Ddhjx-code/notional_data.git
|
|
248
|
+
```
|
|
249
|
+
2. **优先使用预遍历数据**: 从 `nbs_data_repository` 目录直接读取已存在的分类编码信息
|
|
250
|
+
3. **快速查询**: 使用 `search_statistics` 工具进行关键词搜索
|
|
251
|
+
4. **实时数据获取**: 使用 `get_statistics_data` 获取具体统计数据
|
|
252
|
+
5. **递归调用**: 仅在预遍历数据不满足需求时使用 `get_statistics_leaf_categories`
|
|
253
|
+
|
|
254
|
+
### 预遍历数据优势(当可访问完整数据集时):
|
|
255
|
+
- ✅ 快速访问:无需等待实时API调用和递归遍历
|
|
256
|
+
- ✅ 大数据量:包含国家统计局完整分类体系
|
|
257
|
+
- ✅ 稳定性好:离线数据访问不受API限制
|
|
258
|
+
- ✅ 减少API调用:降低对国家统计局服务器压力
|
|
259
|
+
|
|
260
|
+
### 递归API使用场景:
|
|
261
|
+
- 临时获取最新指标(若预遍历数据未及时更新)
|
|
262
|
+
- 特殊查询需求超出预遍历数据范围
|
|
263
|
+
- 在较小环境中仅安装了 npm 包的情况
|
|
264
|
+
|
|
95
265
|
## 贡献
|
|
96
266
|
欢迎对本代码进行修改。请确保遵循项目的编码标准。
|
|
97
267
|
|
package/dist/api-client.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export interface StatsSearchResult {
|
|
|
39
39
|
report: string;
|
|
40
40
|
}>;
|
|
41
41
|
}
|
|
42
|
-
export interface
|
|
42
|
+
export interface ParsedSearchResult {
|
|
43
43
|
name: string;
|
|
44
44
|
value: string;
|
|
45
45
|
time: string;
|
|
@@ -80,7 +80,7 @@ export declare class StatsApiClient {
|
|
|
80
80
|
/**
|
|
81
81
|
* 解析搜索结果
|
|
82
82
|
*/
|
|
83
|
-
parseSearchResult(result: StatsSearchResult):
|
|
83
|
+
parseSearchResult(result: StatsSearchResult): ParsedSearchResult[];
|
|
84
84
|
/**
|
|
85
85
|
* 获取指标分类树
|
|
86
86
|
*/
|
|
@@ -118,4 +118,69 @@ export declare class StatsApiClient {
|
|
|
118
118
|
error?: string;
|
|
119
119
|
}>>;
|
|
120
120
|
}
|
|
121
|
+
import { TreeNode, Indicator, DataQueryParams, SearchItem, TreeQueryParams, IndicatorQueryParams, SearchQueryParams, CategoryCode, NewApiClientConfig, DataPoint } from './types';
|
|
122
|
+
/**
|
|
123
|
+
* 新版国家统计局API客户端 (V2.0)
|
|
124
|
+
* 基于UUID标识符的新架构
|
|
125
|
+
*/
|
|
126
|
+
export declare class NewStatsApiClient {
|
|
127
|
+
private baseUrl;
|
|
128
|
+
private timeout;
|
|
129
|
+
private rootId;
|
|
130
|
+
private treeCache;
|
|
131
|
+
private indicatorsCache;
|
|
132
|
+
private readonly DEFAULT_TREE_TTL;
|
|
133
|
+
private readonly DEFAULT_INDICATORS_TTL;
|
|
134
|
+
constructor(config?: NewApiClientConfig);
|
|
135
|
+
/**
|
|
136
|
+
* 搜索数据集
|
|
137
|
+
* 用于快速定位 cid
|
|
138
|
+
*/
|
|
139
|
+
search(params: SearchQueryParams): Promise<SearchItem[]>;
|
|
140
|
+
/**
|
|
141
|
+
* 获取树结构
|
|
142
|
+
* 用于遍历目录树,获取叶子节点(cid)
|
|
143
|
+
*/
|
|
144
|
+
getTree(params: TreeQueryParams): Promise<TreeNode[]>;
|
|
145
|
+
/**
|
|
146
|
+
* 递归获取所有叶子节点(cid)
|
|
147
|
+
* 注意:此方法耗时较长,慎用
|
|
148
|
+
*/
|
|
149
|
+
getAllLeafNodes(code: CategoryCode): Promise<TreeNode[]>;
|
|
150
|
+
/**
|
|
151
|
+
* 获取指标列表
|
|
152
|
+
* 根据 cid 获取所有可用指标
|
|
153
|
+
*/
|
|
154
|
+
getIndicators(params: IndicatorQueryParams): Promise<Indicator[]>;
|
|
155
|
+
/**
|
|
156
|
+
* 查询数据
|
|
157
|
+
* 批量获取多个指标、多个时间点的数据
|
|
158
|
+
*/
|
|
159
|
+
getData(params: DataQueryParams): Promise<DataPoint[]>;
|
|
160
|
+
/**
|
|
161
|
+
* 辅助方法: 搜索并获取数据
|
|
162
|
+
* 一步到位:搜索关键词 -> 获取cid -> 获取指标 -> 查询数据
|
|
163
|
+
*/
|
|
164
|
+
searchAndGet(keyword: string, indicatorName?: string, startTime?: string, endTime?: string): Promise<{
|
|
165
|
+
cid: string;
|
|
166
|
+
indicator: Indicator;
|
|
167
|
+
data: DataPoint[];
|
|
168
|
+
}>;
|
|
169
|
+
/**
|
|
170
|
+
* 辅助方法: 从 globalid 提取 cid (最后一段)
|
|
171
|
+
*/
|
|
172
|
+
private extractCidFromGlobalId;
|
|
173
|
+
/**
|
|
174
|
+
* 清除所有缓存
|
|
175
|
+
*/
|
|
176
|
+
clearCache(): void;
|
|
177
|
+
/**
|
|
178
|
+
* 设置根节点ID
|
|
179
|
+
*/
|
|
180
|
+
setRootId(rootId: string): void;
|
|
181
|
+
/**
|
|
182
|
+
* 获取当前根节点ID
|
|
183
|
+
*/
|
|
184
|
+
getRootId(): string;
|
|
185
|
+
}
|
|
121
186
|
//# sourceMappingURL=api-client.d.ts.map
|
package/dist/api-client.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.StatsApiClient = void 0;
|
|
6
|
+
exports.NewStatsApiClient = exports.StatsApiClient = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
8
|
// 国家统计局API客户端
|
|
9
9
|
class StatsApiClient {
|
|
@@ -16,15 +16,16 @@ class StatsApiClient {
|
|
|
16
16
|
* 搜索指标
|
|
17
17
|
*/
|
|
18
18
|
async search(keyword, db = '', page = 0) {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
// 使用 axios 的 params 选项来避免编码问题
|
|
20
|
+
const params = {
|
|
21
|
+
s: keyword, // 让 axios 正确处理编码
|
|
21
22
|
m: 'searchdata',
|
|
22
|
-
db
|
|
23
|
+
db,
|
|
23
24
|
p: page.toString(),
|
|
24
|
-
}
|
|
25
|
-
|
|
25
|
+
};
|
|
26
|
+
console.error(`GET Request URL (base): ${this.baseUrl}/search.htm with params:`, JSON.stringify(params));
|
|
26
27
|
try {
|
|
27
|
-
const response = await axios_1.default.get(
|
|
28
|
+
const response = await axios_1.default.get(`${this.baseUrl}/search.htm`, { params });
|
|
28
29
|
return response.data;
|
|
29
30
|
}
|
|
30
31
|
catch (error) {
|
|
@@ -69,6 +70,8 @@ class StatsApiClient {
|
|
|
69
70
|
dbcode,
|
|
70
71
|
wdcode
|
|
71
72
|
};
|
|
73
|
+
console.error(`POST Request URL: ${this.baseUrl}/easyquery.htm`);
|
|
74
|
+
console.error(`POST Request Body:`, JSON.stringify(params));
|
|
72
75
|
try {
|
|
73
76
|
const response = await axios_1.default.post(`${this.baseUrl}/easyquery.htm`, new URLSearchParams(params));
|
|
74
77
|
return response.data;
|
|
@@ -105,7 +108,7 @@ class StatsApiClient {
|
|
|
105
108
|
}
|
|
106
109
|
catch (error) {
|
|
107
110
|
retries++;
|
|
108
|
-
console.
|
|
111
|
+
console.error(`Category request failed for node ${nodeId}, attempt ${retries}/${maxRetries}.`);
|
|
109
112
|
if (retries >= maxRetries) {
|
|
110
113
|
throw error;
|
|
111
114
|
}
|
|
@@ -127,6 +130,8 @@ class StatsApiClient {
|
|
|
127
130
|
dbcode,
|
|
128
131
|
wdcode
|
|
129
132
|
};
|
|
133
|
+
console.error(`POST Request URL: ${this.baseUrl}/easyquery.htm`);
|
|
134
|
+
console.error(`POST Request Body:`, JSON.stringify(params));
|
|
130
135
|
try {
|
|
131
136
|
const response = await axios_1.default.post(`${this.baseUrl}/easyquery.htm`, new URLSearchParams(params));
|
|
132
137
|
return response.data;
|
|
@@ -152,6 +157,7 @@ class StatsApiClient {
|
|
|
152
157
|
k1: Date.now(), // 添加时间戳防止缓存
|
|
153
158
|
h: 1
|
|
154
159
|
};
|
|
160
|
+
console.error(`GET Request URL: ${this.baseUrl}/easyquery.htm with params:`, JSON.stringify(params));
|
|
155
161
|
try {
|
|
156
162
|
const response = await axios_1.default.get(`${this.baseUrl}/easyquery.htm`, { params });
|
|
157
163
|
return response.data;
|
|
@@ -180,6 +186,7 @@ class StatsApiClient {
|
|
|
180
186
|
k1: Date.now(), // 添加时间戳防止缓存
|
|
181
187
|
h: 1
|
|
182
188
|
};
|
|
189
|
+
console.error(`GET Request URL: ${this.baseUrl}/easyquery.htm with params:`, JSON.stringify(params));
|
|
183
190
|
try {
|
|
184
191
|
const response = await axios_1.default.get(`${this.baseUrl}/easyquery.htm`, { params });
|
|
185
192
|
return response.data;
|
|
@@ -217,4 +224,294 @@ class StatsApiClient {
|
|
|
217
224
|
}
|
|
218
225
|
}
|
|
219
226
|
exports.StatsApiClient = StatsApiClient;
|
|
227
|
+
// ============= 新版 API 客户端 (V2.0) =============
|
|
228
|
+
const types_1 = require("./types");
|
|
229
|
+
/**
|
|
230
|
+
* 简单的内存缓存实现
|
|
231
|
+
*/
|
|
232
|
+
class SimpleCache {
|
|
233
|
+
cache = new Map();
|
|
234
|
+
get(key) {
|
|
235
|
+
const item = this.cache.get(key);
|
|
236
|
+
if (!item)
|
|
237
|
+
return null;
|
|
238
|
+
if (Date.now() > item.expireAt) {
|
|
239
|
+
this.cache.delete(key);
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
return item.data;
|
|
243
|
+
}
|
|
244
|
+
set(key, data, ttl) {
|
|
245
|
+
this.cache.set(key, {
|
|
246
|
+
data,
|
|
247
|
+
expireAt: Date.now() + ttl,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
clear() {
|
|
251
|
+
this.cache.clear();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* 新版国家统计局API客户端 (V2.0)
|
|
256
|
+
* 基于UUID标识符的新架构
|
|
257
|
+
*/
|
|
258
|
+
class NewStatsApiClient {
|
|
259
|
+
baseUrl;
|
|
260
|
+
timeout;
|
|
261
|
+
rootId;
|
|
262
|
+
// 缓存实例
|
|
263
|
+
treeCache;
|
|
264
|
+
indicatorsCache;
|
|
265
|
+
// 默认配置
|
|
266
|
+
DEFAULT_TREE_TTL = 24 * 60 * 60 * 1000; // 24小时
|
|
267
|
+
DEFAULT_INDICATORS_TTL = 12 * 60 * 60 * 1000; // 12小时
|
|
268
|
+
constructor(config) {
|
|
269
|
+
this.baseUrl = config?.baseUrl || types_1.NEW_API_BASE_URL;
|
|
270
|
+
this.timeout = config?.timeout || 30000;
|
|
271
|
+
this.rootId = config?.rootId || 'fc982599aa684be7969d7b90b1bd0e84'; // 月度数据根节点
|
|
272
|
+
// 初始化缓存
|
|
273
|
+
this.treeCache = new SimpleCache();
|
|
274
|
+
this.indicatorsCache = new SimpleCache();
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* 搜索数据集
|
|
278
|
+
* 用于快速定位 cid
|
|
279
|
+
*/
|
|
280
|
+
async search(params) {
|
|
281
|
+
const url = new URL(`${this.baseUrl}/query`);
|
|
282
|
+
url.searchParams.set('search', params.search);
|
|
283
|
+
url.searchParams.set('pagenum', (params.pagenum || 1).toString());
|
|
284
|
+
url.searchParams.set('pageSize', (params.pageSize || 10).toString());
|
|
285
|
+
console.error(`Search Request: ${url.toString()}`);
|
|
286
|
+
try {
|
|
287
|
+
const response = await axios_1.default.get(url.toString(), {
|
|
288
|
+
timeout: this.timeout,
|
|
289
|
+
});
|
|
290
|
+
return response.data.data?.data || [];
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
294
|
+
throw new Error(`Search request failed: ${error.response?.data || error.message}`);
|
|
295
|
+
}
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* 获取树结构
|
|
301
|
+
* 用于遍历目录树,获取叶子节点(cid)
|
|
302
|
+
*/
|
|
303
|
+
async getTree(params) {
|
|
304
|
+
// 检查缓存
|
|
305
|
+
const cacheKey = `tree_${params.code}_${params.pid || 'root'}`;
|
|
306
|
+
const cached = this.treeCache.get(cacheKey);
|
|
307
|
+
if (cached) {
|
|
308
|
+
console.error(`Tree cache hit for ${cacheKey}`);
|
|
309
|
+
return cached;
|
|
310
|
+
}
|
|
311
|
+
const url = new URL(`${this.baseUrl}/new/queryIndexTreeAsync`);
|
|
312
|
+
if (params.pid) {
|
|
313
|
+
url.searchParams.set('pid', params.pid);
|
|
314
|
+
}
|
|
315
|
+
url.searchParams.set('code', params.code);
|
|
316
|
+
console.error(`Tree Request: ${url.toString()}`);
|
|
317
|
+
try {
|
|
318
|
+
const response = await axios_1.default.get(url.toString(), {
|
|
319
|
+
timeout: this.timeout,
|
|
320
|
+
});
|
|
321
|
+
const nodes = response.data.data || [];
|
|
322
|
+
// 缓存结果
|
|
323
|
+
this.treeCache.set(cacheKey, nodes, this.DEFAULT_TREE_TTL);
|
|
324
|
+
return nodes;
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
328
|
+
throw new Error(`Tree request failed: ${error.response?.data || error.message}`);
|
|
329
|
+
}
|
|
330
|
+
throw error;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* 递归获取所有叶子节点(cid)
|
|
335
|
+
* 注意:此方法耗时较长,慎用
|
|
336
|
+
*/
|
|
337
|
+
async getAllLeafNodes(code) {
|
|
338
|
+
const allLeaves = [];
|
|
339
|
+
const getRecursively = async (pid) => {
|
|
340
|
+
try {
|
|
341
|
+
// 添加延迟避免请求过于频繁
|
|
342
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
343
|
+
const nodes = await this.getTree({ pid, code });
|
|
344
|
+
for (const node of nodes) {
|
|
345
|
+
if (node.isLeaf) {
|
|
346
|
+
allLeaves.push(node);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
await getRecursively(node._id);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
console.error(`Error in recursive tree traversal for pid=${pid}:`, error);
|
|
355
|
+
throw error;
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
await getRecursively();
|
|
359
|
+
return allLeaves;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* 获取指标列表
|
|
363
|
+
* 根据 cid 获取所有可用指标
|
|
364
|
+
*/
|
|
365
|
+
async getIndicators(params) {
|
|
366
|
+
// 检查缓存
|
|
367
|
+
const cacheKey = `indicators_${params.cid}`;
|
|
368
|
+
const cached = this.indicatorsCache.get(cacheKey);
|
|
369
|
+
if (cached) {
|
|
370
|
+
console.error(`Indicators cache hit for ${cacheKey}`);
|
|
371
|
+
return cached;
|
|
372
|
+
}
|
|
373
|
+
const url = new URL(`${this.baseUrl}/new/queryIndicatorsByCid`);
|
|
374
|
+
url.searchParams.set('cid', params.cid);
|
|
375
|
+
if (params.dt) {
|
|
376
|
+
url.searchParams.set('dt', params.dt);
|
|
377
|
+
}
|
|
378
|
+
if (params.name) {
|
|
379
|
+
url.searchParams.set('name', params.name);
|
|
380
|
+
}
|
|
381
|
+
console.error(`Indicators Request: ${url.toString()}`);
|
|
382
|
+
try {
|
|
383
|
+
const response = await axios_1.default.get(url.toString(), {
|
|
384
|
+
timeout: this.timeout,
|
|
385
|
+
});
|
|
386
|
+
const indicators = response.data.data?.list || [];
|
|
387
|
+
// 缓存结果
|
|
388
|
+
this.indicatorsCache.set(cacheKey, indicators, this.DEFAULT_INDICATORS_TTL);
|
|
389
|
+
return indicators;
|
|
390
|
+
}
|
|
391
|
+
catch (error) {
|
|
392
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
393
|
+
throw new Error(`Indicators request failed: ${error.response?.data || error.message}`);
|
|
394
|
+
}
|
|
395
|
+
throw error;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* 查询数据
|
|
400
|
+
* 批量获取多个指标、多个时间点的数据
|
|
401
|
+
*/
|
|
402
|
+
async getData(params) {
|
|
403
|
+
const payload = {
|
|
404
|
+
cid: params.cid,
|
|
405
|
+
indicatorIds: params.indicatorIds,
|
|
406
|
+
das: params.das,
|
|
407
|
+
dts: params.dts,
|
|
408
|
+
showType: params.showType || '1',
|
|
409
|
+
rootId: params.rootId || this.rootId,
|
|
410
|
+
};
|
|
411
|
+
console.error(`Data Request: ${this.baseUrl}/getEsDataByCidAndDt`);
|
|
412
|
+
console.error(`Payload:`, JSON.stringify(payload, null, 2));
|
|
413
|
+
try {
|
|
414
|
+
const response = await axios_1.default.post(`${this.baseUrl}/getEsDataByCidAndDt`, payload, {
|
|
415
|
+
timeout: this.timeout,
|
|
416
|
+
headers: {
|
|
417
|
+
'Content-Type': 'application/json',
|
|
418
|
+
},
|
|
419
|
+
});
|
|
420
|
+
if (!response.data.success) {
|
|
421
|
+
throw new Error('Data query failed: API returned success=false');
|
|
422
|
+
}
|
|
423
|
+
return response.data.data || [];
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
427
|
+
throw new Error(`Data request failed: ${error.response?.data || error.message}`);
|
|
428
|
+
}
|
|
429
|
+
throw error;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* 辅助方法: 搜索并获取数据
|
|
434
|
+
* 一步到位:搜索关键词 -> 获取cid -> 获取指标 -> 查询数据
|
|
435
|
+
*/
|
|
436
|
+
async searchAndGet(keyword, indicatorName, startTime, endTime) {
|
|
437
|
+
// 1. 搜索定位cid
|
|
438
|
+
const searchResults = await this.search({ search: keyword, pageSize: 10 });
|
|
439
|
+
if (!searchResults || searchResults.length === 0) {
|
|
440
|
+
throw new Error(`No results found for keyword: ${keyword}`);
|
|
441
|
+
}
|
|
442
|
+
// 优先选择最新的数据集(通过edate判断)
|
|
443
|
+
const target = searchResults.reduce((latest, current) => {
|
|
444
|
+
if (!latest.edate)
|
|
445
|
+
return current;
|
|
446
|
+
if (!current.edate)
|
|
447
|
+
return latest;
|
|
448
|
+
return current.edate > latest.edate ? current : latest;
|
|
449
|
+
});
|
|
450
|
+
// 从 globalid 提取 cid (如果搜索结果没有直接提供cid)
|
|
451
|
+
const cid = target.cid || this.extractCidFromGlobalId(target.treeinfo_globalid);
|
|
452
|
+
if (!cid) {
|
|
453
|
+
throw new Error('Failed to extract cid from search result');
|
|
454
|
+
}
|
|
455
|
+
// 2. 获取指标列表
|
|
456
|
+
const indicators = await this.getIndicators({ cid });
|
|
457
|
+
if (!indicators || indicators.length === 0) {
|
|
458
|
+
throw new Error(`No indicators found for cid: ${cid}`);
|
|
459
|
+
}
|
|
460
|
+
// 筛选目标指标
|
|
461
|
+
let targetIndicator;
|
|
462
|
+
if (indicatorName) {
|
|
463
|
+
targetIndicator = indicators.find(ind => ind.i_showname.includes(indicatorName));
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
targetIndicator = indicators[0]; // 默认取第一个
|
|
467
|
+
}
|
|
468
|
+
if (!targetIndicator) {
|
|
469
|
+
throw new Error(`Indicator not found: ${indicatorName}`);
|
|
470
|
+
}
|
|
471
|
+
// 3. 查询数据
|
|
472
|
+
const timeRange = startTime && endTime
|
|
473
|
+
? `${startTime}-${endTime}`
|
|
474
|
+
: `${target.sdate || '202001'}MM-${target.edate || '202612'}MM`;
|
|
475
|
+
const data = await this.getData({
|
|
476
|
+
cid,
|
|
477
|
+
indicatorIds: [targetIndicator._id],
|
|
478
|
+
das: [{ text: '全国', value: '000000000000' }],
|
|
479
|
+
dts: [timeRange],
|
|
480
|
+
});
|
|
481
|
+
return {
|
|
482
|
+
cid,
|
|
483
|
+
indicator: targetIndicator,
|
|
484
|
+
data,
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* 辅助方法: 从 globalid 提取 cid (最后一段)
|
|
489
|
+
*/
|
|
490
|
+
extractCidFromGlobalId(globalId) {
|
|
491
|
+
if (!globalId)
|
|
492
|
+
return null;
|
|
493
|
+
const parts = globalId.split('.');
|
|
494
|
+
return parts[parts.length - 1] || null;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* 清除所有缓存
|
|
498
|
+
*/
|
|
499
|
+
clearCache() {
|
|
500
|
+
this.treeCache.clear();
|
|
501
|
+
this.indicatorsCache.clear();
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* 设置根节点ID
|
|
505
|
+
*/
|
|
506
|
+
setRootId(rootId) {
|
|
507
|
+
this.rootId = rootId;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* 获取当前根节点ID
|
|
511
|
+
*/
|
|
512
|
+
getRootId() {
|
|
513
|
+
return this.rootId;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
exports.NewStatsApiClient = NewStatsApiClient;
|
|
220
517
|
//# sourceMappingURL=api-client.js.map
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ const api_client_1 = require("./api-client");
|
|
|
9
9
|
const zod_1 = require("zod");
|
|
10
10
|
const commander_1 = require("commander");
|
|
11
11
|
// 获取版本号,这里使用package.json中的版本
|
|
12
|
-
const VERSION = '1.0.
|
|
12
|
+
const VERSION = '1.0.2';
|
|
13
13
|
// 创建API客户端实例
|
|
14
14
|
const apiClient = new api_client_1.StatsApiClient();
|
|
15
15
|
// 创建MCP服务器
|
package/dist/types.d.ts
CHANGED
|
@@ -22,4 +22,169 @@ export interface StdioServerTransport {
|
|
|
22
22
|
new (): StdioServerTransport;
|
|
23
23
|
}
|
|
24
24
|
export type StartHttpServerFn = (options: SseAndStreamableHttpMcpServerOptions) => Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* 新版API基础URL
|
|
27
|
+
*/
|
|
28
|
+
export declare const NEW_API_BASE_URL = "https://data.stats.gov.cn/dg/website/publicrelease/web/external";
|
|
29
|
+
/**
|
|
30
|
+
* 树节点 - 来自 queryIndexTreeAsync
|
|
31
|
+
*/
|
|
32
|
+
export interface TreeNode {
|
|
33
|
+
_id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
isLeaf: boolean;
|
|
36
|
+
treeinfo_globalid?: string;
|
|
37
|
+
sdate?: string;
|
|
38
|
+
edate?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 树查询响应
|
|
42
|
+
*/
|
|
43
|
+
export interface TreeResponse {
|
|
44
|
+
data: TreeNode[];
|
|
45
|
+
success: boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 指标信息 - 来自 queryIndicatorsByCid
|
|
49
|
+
*/
|
|
50
|
+
export interface Indicator {
|
|
51
|
+
_id: string;
|
|
52
|
+
i_showname: string;
|
|
53
|
+
i_mark?: string;
|
|
54
|
+
du?: string;
|
|
55
|
+
dp?: string;
|
|
56
|
+
order?: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* 指标列表响应
|
|
60
|
+
*/
|
|
61
|
+
export interface IndicatorsResponse {
|
|
62
|
+
data: {
|
|
63
|
+
list: Indicator[];
|
|
64
|
+
};
|
|
65
|
+
success: boolean;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 地区维度项
|
|
69
|
+
*/
|
|
70
|
+
export interface RegionDimension {
|
|
71
|
+
text: string;
|
|
72
|
+
value: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 数据值项
|
|
76
|
+
*/
|
|
77
|
+
export interface DataValue {
|
|
78
|
+
_id: string;
|
|
79
|
+
i_showname?: string;
|
|
80
|
+
value?: string;
|
|
81
|
+
da_name?: string;
|
|
82
|
+
du_name?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 数据点 - 来自 getEsDataByCidAndDt
|
|
86
|
+
*/
|
|
87
|
+
export interface DataPoint {
|
|
88
|
+
code: string;
|
|
89
|
+
name: string;
|
|
90
|
+
values: DataValue[];
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* 数据查询响应
|
|
94
|
+
*/
|
|
95
|
+
export interface DataResponse {
|
|
96
|
+
data: DataPoint[];
|
|
97
|
+
success: boolean;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* 数据查询请求参数
|
|
101
|
+
*/
|
|
102
|
+
export interface DataQueryParams {
|
|
103
|
+
cid: string;
|
|
104
|
+
indicatorIds: string[];
|
|
105
|
+
das: RegionDimension[];
|
|
106
|
+
dts: string[];
|
|
107
|
+
showType?: string;
|
|
108
|
+
rootId?: string;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* 搜索结果项 - 来自 /external/query
|
|
112
|
+
*/
|
|
113
|
+
export interface SearchItem {
|
|
114
|
+
show_name: string;
|
|
115
|
+
type_text: string;
|
|
116
|
+
treeinfo_globalid?: string;
|
|
117
|
+
cid?: string;
|
|
118
|
+
sdate?: string;
|
|
119
|
+
edate?: string;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 搜索响应
|
|
123
|
+
*/
|
|
124
|
+
export interface SearchResponse {
|
|
125
|
+
data: {
|
|
126
|
+
data: SearchItem[];
|
|
127
|
+
total?: number;
|
|
128
|
+
};
|
|
129
|
+
success?: boolean;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* 树查询参数
|
|
133
|
+
*/
|
|
134
|
+
export interface TreeQueryParams {
|
|
135
|
+
pid?: string;
|
|
136
|
+
code: string;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* 指标查询参数
|
|
140
|
+
*/
|
|
141
|
+
export interface IndicatorQueryParams {
|
|
142
|
+
cid: string;
|
|
143
|
+
dt?: string;
|
|
144
|
+
name?: string;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* 搜索查询参数
|
|
148
|
+
*/
|
|
149
|
+
export interface SearchQueryParams {
|
|
150
|
+
search: string;
|
|
151
|
+
pagenum?: number;
|
|
152
|
+
pageSize?: number;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* 时间编码格式枚举
|
|
156
|
+
*/
|
|
157
|
+
export declare enum TimeFormat {
|
|
158
|
+
MONTHLY = "MM",// 月度: YYYYMM, 后缀 MM
|
|
159
|
+
QUARTERLY = "SS",// 季度: YYYYQ, 后缀 SS
|
|
160
|
+
YEARLY = "YY"
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* 分类代码枚举
|
|
164
|
+
*/
|
|
165
|
+
export declare enum CategoryCode {
|
|
166
|
+
MONTHLY = "1",// 月度数据
|
|
167
|
+
QUARTERLY = "2",// 季度数据
|
|
168
|
+
YEARLY = "3",// 年度数据
|
|
169
|
+
PROVINCE_QUARTERLY = "5",// 分省季度
|
|
170
|
+
PROVINCE_YEARLY = "6",// 分省年度
|
|
171
|
+
OTHER = "7"
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* 缓存配置
|
|
175
|
+
*/
|
|
176
|
+
export interface CacheConfig {
|
|
177
|
+
treeTTL?: number;
|
|
178
|
+
indicatorsTTL?: number;
|
|
179
|
+
dataTTL?: number;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* API客户端配置
|
|
183
|
+
*/
|
|
184
|
+
export interface NewApiClientConfig {
|
|
185
|
+
baseUrl?: string;
|
|
186
|
+
timeout?: number;
|
|
187
|
+
cache?: CacheConfig;
|
|
188
|
+
rootId?: string;
|
|
189
|
+
}
|
|
25
190
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.js
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CategoryCode = exports.TimeFormat = exports.NEW_API_BASE_URL = void 0;
|
|
4
|
+
// ============= 新版 API 类型定义 (V2.0) =============
|
|
5
|
+
/**
|
|
6
|
+
* 新版API基础URL
|
|
7
|
+
*/
|
|
8
|
+
exports.NEW_API_BASE_URL = 'https://data.stats.gov.cn/dg/website/publicrelease/web/external';
|
|
9
|
+
/**
|
|
10
|
+
* 时间编码格式枚举
|
|
11
|
+
*/
|
|
12
|
+
var TimeFormat;
|
|
13
|
+
(function (TimeFormat) {
|
|
14
|
+
TimeFormat["MONTHLY"] = "MM";
|
|
15
|
+
TimeFormat["QUARTERLY"] = "SS";
|
|
16
|
+
TimeFormat["YEARLY"] = "YY";
|
|
17
|
+
})(TimeFormat || (exports.TimeFormat = TimeFormat = {}));
|
|
18
|
+
/**
|
|
19
|
+
* 分类代码枚举
|
|
20
|
+
*/
|
|
21
|
+
var CategoryCode;
|
|
22
|
+
(function (CategoryCode) {
|
|
23
|
+
CategoryCode["MONTHLY"] = "1";
|
|
24
|
+
CategoryCode["QUARTERLY"] = "2";
|
|
25
|
+
CategoryCode["YEARLY"] = "3";
|
|
26
|
+
CategoryCode["PROVINCE_QUARTERLY"] = "5";
|
|
27
|
+
CategoryCode["PROVINCE_YEARLY"] = "6";
|
|
28
|
+
CategoryCode["OTHER"] = "7";
|
|
29
|
+
})(CategoryCode || (exports.CategoryCode = CategoryCode = {}));
|
|
3
30
|
//# sourceMappingURL=types.js.map
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "national-stats-mcp",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "MCP server for accessing National Bureau of Statistics data",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "MCP server for accessing National Bureau of Statistics data (supports both new V2.0 and legacy API)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"national-stats-mcp": "dist/index.js"
|
package/zb.json
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"dbcode": "hgnd",
|
|
4
|
-
"id": "A01",
|
|
5
|
-
"isParent": true,
|
|
6
|
-
"name": "综合",
|
|
7
|
-
"pid": "",
|
|
8
|
-
"wdcode": "zb"
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"dbcode": "hgnd",
|
|
12
|
-
"id": "A02",
|
|
13
|
-
"isParent": true,
|
|
14
|
-
"name": "国民经济核算",
|
|
15
|
-
"pid": "",
|
|
16
|
-
"wdcode": "zb"
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"dbcode": "hgnd",
|
|
20
|
-
"id": "A03",
|
|
21
|
-
"isParent": true,
|
|
22
|
-
"name": "人口",
|
|
23
|
-
"pid": "",
|
|
24
|
-
"wdcode": "zb"
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"dbcode": "hgnd",
|
|
28
|
-
"id": "A04",
|
|
29
|
-
"isParent": true,
|
|
30
|
-
"name": "就业人员和工资",
|
|
31
|
-
"pid": "",
|
|
32
|
-
"wdcode": "zb"
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
"dbcode": "hgnd",
|
|
36
|
-
"id": "A05",
|
|
37
|
-
"isParent": true,
|
|
38
|
-
"name": "固定资产投资和房地产",
|
|
39
|
-
"pid": "",
|
|
40
|
-
"wdcode": "zb"
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"dbcode": "hgnd",
|
|
44
|
-
"id": "A06",
|
|
45
|
-
"isParent": true,
|
|
46
|
-
"name": "对外经济贸易",
|
|
47
|
-
"pid": "",
|
|
48
|
-
"wdcode": "zb"
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
"dbcode": "hgnd",
|
|
52
|
-
"id": "A07",
|
|
53
|
-
"isParent": true,
|
|
54
|
-
"name": "能源",
|
|
55
|
-
"pid": "",
|
|
56
|
-
"wdcode": "zb"
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
"dbcode": "hgnd",
|
|
60
|
-
"id": "A08",
|
|
61
|
-
"isParent": true,
|
|
62
|
-
"name": "财政",
|
|
63
|
-
"pid": "",
|
|
64
|
-
"wdcode": "zb"
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
"dbcode": "hgnd",
|
|
68
|
-
"id": "A09",
|
|
69
|
-
"isParent": true,
|
|
70
|
-
"name": "价格指数",
|
|
71
|
-
"pid": "",
|
|
72
|
-
"wdcode": "zb"
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
"dbcode": "hgnd",
|
|
76
|
-
"id": "A0A",
|
|
77
|
-
"isParent": true,
|
|
78
|
-
"name": "人民生活",
|
|
79
|
-
"pid": "",
|
|
80
|
-
"wdcode": "zb"
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
"dbcode": "hgnd",
|
|
84
|
-
"id": "A0B",
|
|
85
|
-
"isParent": true,
|
|
86
|
-
"name": "城市概况",
|
|
87
|
-
"pid": "",
|
|
88
|
-
"wdcode": "zb"
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
"dbcode": "hgnd",
|
|
92
|
-
"id": "A0C",
|
|
93
|
-
"isParent": true,
|
|
94
|
-
"name": "资源和环境",
|
|
95
|
-
"pid": "",
|
|
96
|
-
"wdcode": "zb"
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
"dbcode": "hgnd",
|
|
100
|
-
"id": "A0D",
|
|
101
|
-
"isParent": true,
|
|
102
|
-
"name": "农业",
|
|
103
|
-
"pid": "",
|
|
104
|
-
"wdcode": "zb"
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
"dbcode": "hgnd",
|
|
108
|
-
"id": "A0E",
|
|
109
|
-
"isParent": true,
|
|
110
|
-
"name": "工业",
|
|
111
|
-
"pid": "",
|
|
112
|
-
"wdcode": "zb"
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
"dbcode": "hgnd",
|
|
116
|
-
"id": "A0F",
|
|
117
|
-
"isParent": true,
|
|
118
|
-
"name": "建筑业",
|
|
119
|
-
"pid": "",
|
|
120
|
-
"wdcode": "zb"
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
"dbcode": "hgnd",
|
|
124
|
-
"id": "A0G",
|
|
125
|
-
"isParent": true,
|
|
126
|
-
"name": "运输和邮电",
|
|
127
|
-
"pid": "",
|
|
128
|
-
"wdcode": "zb"
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
"dbcode": "hgnd",
|
|
132
|
-
"id": "A0H",
|
|
133
|
-
"isParent": false,
|
|
134
|
-
"name": "社会消费品零售总额",
|
|
135
|
-
"pid": "",
|
|
136
|
-
"wdcode": "zb"
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
"dbcode": "hgnd",
|
|
140
|
-
"id": "A0I",
|
|
141
|
-
"isParent": true,
|
|
142
|
-
"name": "批发和零售业",
|
|
143
|
-
"pid": "",
|
|
144
|
-
"wdcode": "zb"
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
"dbcode": "hgnd",
|
|
148
|
-
"id": "A0J",
|
|
149
|
-
"isParent": true,
|
|
150
|
-
"name": "住宿和餐饮业",
|
|
151
|
-
"pid": "",
|
|
152
|
-
"wdcode": "zb"
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
"dbcode": "hgnd",
|
|
156
|
-
"id": "A0K",
|
|
157
|
-
"isParent": true,
|
|
158
|
-
"name": "旅游业",
|
|
159
|
-
"pid": "",
|
|
160
|
-
"wdcode": "zb"
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
"dbcode": "hgnd",
|
|
164
|
-
"id": "A0L",
|
|
165
|
-
"isParent": true,
|
|
166
|
-
"name": "金融业",
|
|
167
|
-
"pid": "",
|
|
168
|
-
"wdcode": "zb"
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
"dbcode": "hgnd",
|
|
172
|
-
"id": "A0M",
|
|
173
|
-
"isParent": true,
|
|
174
|
-
"name": "教育",
|
|
175
|
-
"pid": "",
|
|
176
|
-
"wdcode": "zb"
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
"dbcode": "hgnd",
|
|
180
|
-
"id": "A0N",
|
|
181
|
-
"isParent": true,
|
|
182
|
-
"name": "科技",
|
|
183
|
-
"pid": "",
|
|
184
|
-
"wdcode": "zb"
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
"dbcode": "hgnd",
|
|
188
|
-
"id": "A0O",
|
|
189
|
-
"isParent": true,
|
|
190
|
-
"name": "卫生",
|
|
191
|
-
"pid": "",
|
|
192
|
-
"wdcode": "zb"
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
"dbcode": "hgnd",
|
|
196
|
-
"id": "A0P",
|
|
197
|
-
"isParent": true,
|
|
198
|
-
"name": "社会服务",
|
|
199
|
-
"pid": "",
|
|
200
|
-
"wdcode": "zb"
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
"dbcode": "hgnd",
|
|
204
|
-
"id": "A0Q",
|
|
205
|
-
"isParent": true,
|
|
206
|
-
"name": "文化",
|
|
207
|
-
"pid": "",
|
|
208
|
-
"wdcode": "zb"
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
"dbcode": "hgnd",
|
|
212
|
-
"id": "A0R",
|
|
213
|
-
"isParent": true,
|
|
214
|
-
"name": "体育",
|
|
215
|
-
"pid": "",
|
|
216
|
-
"wdcode": "zb"
|
|
217
|
-
},
|
|
218
|
-
{
|
|
219
|
-
"dbcode": "hgnd",
|
|
220
|
-
"id": "A0S",
|
|
221
|
-
"isParent": true,
|
|
222
|
-
"name": "公共管理、社会保障及其他",
|
|
223
|
-
"pid": "",
|
|
224
|
-
"wdcode": "zb"
|
|
225
|
-
}
|
|
226
|
-
]
|