openapi-docs-mcp 0.1.5 → 0.1.6
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 +291 -392
- package/dist/formatter/operation.d.ts.map +1 -1
- package/dist/formatter/operation.js +45 -12
- package/dist/formatter/operation.js.map +1 -1
- package/dist/formatter/schema.d.ts +1 -0
- package/dist/formatter/schema.d.ts.map +1 -1
- package/dist/formatter/schema.js +15 -2
- package/dist/formatter/schema.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,394 +1,293 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/yangjh0127/openapi-docs-mcp/main/assets/openapi-docs-mcp-logo.png" alt="OpenAPI Docs MCP" width="760">
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
|
-
# OpenAPI Docs MCP
|
|
6
|
-
|
|
7
|
-
> 让编码 Agent 安全、准确地搜索和理解 OpenAPI / Swagger 文档。
|
|
8
|
-
|
|
9
|
-
[](https://www.npmjs.com/package/openapi-docs-mcp)
|
|
10
|
-

|
|
11
|
-

|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
## 简介
|
|
24
|
-
|
|
25
|
-
一个厂商无关的 MCP Server,让编码 Agent 能够搜索和理解 OpenAPI/Swagger 文档。
|
|
26
|
-
|
|
27
|
-
服务只读取接口文档,不会调用文档中描述的真实后端 API。它支持本地文件和远程地址,启动后使用内存索引提供稳定、快速的查询。
|
|
28
|
-
|
|
29
|
-
## 详细描述
|
|
30
|
-
|
|
31
|
-
OpenAPI Docs MCP 支持 OpenAPI 3.0、3.1 和 Swagger 2.0,可读取 JSON、YAML、本地文件及 HTTP(S) URL。
|
|
32
|
-
|
|
33
|
-
它提供 5 个 MCP 工具:
|
|
34
|
-
|
|
35
|
-
| 工具 | 作用 |
|
|
36
|
-
| :--- | :--- |
|
|
37
|
-
| `search_api` | 按关键词、路径、Tag、描述或 `operationId` 搜索接口 |
|
|
38
|
-
| `get_api` | 获取接口参数、请求体、响应和展开后的 Schema |
|
|
39
|
-
| `get_schema` | 按名称读取组件 Schema |
|
|
40
|
-
| `list_groups` | 列出 OpenAPI Tags 及接口数量 |
|
|
41
|
-
| `reload_document` | 重新加载文档,无需重启 MCP Server |
|
|
42
|
-
|
|
43
|
-
### 核心能力
|
|
44
|
-
|
|
45
|
-
- 支持中英文接口搜索,并对 Summary、Tag、Path 等字段进行确定性加权;
|
|
46
|
-
- 按需展开本地 `$ref`,限制最大深度和属性数量;
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/yangjh0127/openapi-docs-mcp/main/assets/openapi-docs-mcp-logo.png" alt="OpenAPI Docs MCP" width="760">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# OpenAPI Docs MCP
|
|
6
|
+
|
|
7
|
+
> 让编码 Agent 安全、准确地搜索和理解 OpenAPI / Swagger 文档。
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/openapi-docs-mcp)
|
|
10
|
+

|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
OpenAPI Docs MCP 是一个厂商无关的 MCP Server。它读取本地或远程的 OpenAPI 文档,在内存中建立索引,让编码 Agent 能快速搜索接口并获取参数、请求体、响应和 Schema。
|
|
14
|
+
|
|
15
|
+
服务只读取接口文档,不会调用文档中描述的真实后端 API。
|
|
16
|
+
|
|
17
|
+
## 功能特性
|
|
18
|
+
|
|
19
|
+
- 支持 OpenAPI 3.0、3.1 和 Swagger 2.0;
|
|
20
|
+
- 支持 JSON、YAML、本地文件和 HTTP(S) URL;
|
|
21
|
+
- 支持中英文搜索,并对 Summary、Tag、Path 等字段进行确定性加权;
|
|
22
|
+
- 按需展开本地 `$ref`,限制最大深度和属性数量;
|
|
47
23
|
- 检测循环引用,并标记无法解析的引用;
|
|
48
|
-
-
|
|
24
|
+
- 兼容模式可保守修复能够明确解析的脏 `$ref`;
|
|
49
25
|
- 远程文档支持自定义请求头和超时;
|
|
50
|
-
-
|
|
51
|
-
- 通过 stdio
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
"
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
"
|
|
162
|
-
|
|
163
|
-
"
|
|
164
|
-
"
|
|
165
|
-
"
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
| 参数 | 说明
|
|
204
|
-
|
|
|
205
|
-
|
|
|
206
|
-
|
|
|
207
|
-
|
|
|
208
|
-
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
```bash
|
|
319
|
-
pnpm typecheck
|
|
320
|
-
pnpm test
|
|
321
|
-
pnpm build
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
当前测试覆盖:
|
|
325
|
-
|
|
326
|
-
- OpenAPI 3.0 文档加载;
|
|
327
|
-
- OpenAPI 3.1 YAML 文档加载;
|
|
328
|
-
- Swagger 2.0 文档加载;
|
|
329
|
-
- 无效文档错误处理;
|
|
330
|
-
- 中文加权搜索;
|
|
331
|
-
- Method 和 Tag 过滤;
|
|
332
|
-
- 接口请求与响应 Schema 展开;
|
|
333
|
-
- 循环引用保护;
|
|
334
|
-
- MCP 工具发现与调用。
|
|
335
|
-
|
|
336
|
-
## 当前版本边界
|
|
337
|
-
|
|
338
|
-
第一版有意保持较小的功能范围。
|
|
339
|
-
|
|
340
|
-
已经支持:
|
|
341
|
-
|
|
342
|
-
- OpenAPI 3.0、3.1;
|
|
343
|
-
- Swagger 2.0;
|
|
344
|
-
- JSON 和 YAML;
|
|
345
|
-
- 本地文件和 HTTP(S) URL;
|
|
346
|
-
- 本地 `$ref` 按需展开;
|
|
347
|
-
- 通过 `reload_document` 手动重新加载文档;
|
|
348
|
-
- stdio MCP 传输。
|
|
349
|
-
|
|
350
|
-
暂不支持:
|
|
351
|
-
|
|
352
|
-
- 调用真实后端 API;
|
|
353
|
-
- 保存或管理后端鉴权凭证;
|
|
354
|
-
- 展开其他文件或 URL 中的外部 `$ref`;
|
|
355
|
-
- 向量数据库或 Embedding 搜索;
|
|
356
|
-
- Streamable HTTP MCP 部署;
|
|
357
|
-
- OpenAPI 文档自动轮询或文件监听;
|
|
358
|
-
- 模型厂商私有能力。
|
|
359
|
-
|
|
360
|
-
当 OpenAPI 文档发生变化时,可以调用 `reload_document` 重新加载;也可以重启 MCP Server。
|
|
361
|
-
|
|
362
|
-
## 设计原则
|
|
363
|
-
|
|
364
|
-
```text
|
|
365
|
-
OpenAPI / Swagger
|
|
366
|
-
↓
|
|
367
|
-
解析、保守归一化与校验
|
|
368
|
-
↓
|
|
369
|
-
标准 OpenAPI Document
|
|
370
|
-
↓
|
|
371
|
-
内存 Operation 索引
|
|
372
|
-
↓
|
|
373
|
-
Search + Formatter
|
|
374
|
-
↓
|
|
375
|
-
标准 MCP Tools
|
|
376
|
-
↓
|
|
377
|
-
任意支持 MCP 的 Agent 或 IDE
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
项目不会把 OpenAPI 数据重新转换成一套重复的核心模型。OpenAPI Document 始终是事实来源,自定义类型只用于搜索结果和 MCP 输出。
|
|
381
|
-
|
|
382
|
-
Formatter 不会改写已经加载的 OpenAPI 声明。兼容模式只在加载阶段修复能够唯一确定目标的局部缺陷,避免工具凭相似度猜测后端含义。
|
|
383
|
-
|
|
384
|
-
默认使用兼容校验模式。部分 Springdoc 文档会生成包含中文名称、缺少本地前缀或未转义 JSON Pointer 字符的 `$ref`。只要引用目标能够唯一确定,项目会修复内存副本并输出诊断;不会修改源文件。
|
|
385
|
-
|
|
386
|
-
### 兼容模式诊断
|
|
387
|
-
|
|
388
|
-
兼容模式会跳过无法表示为对象的 path item 或 operation,并为缺少 `responses` 的 operation 补充空对象。每一次修复、跳过、未解析引用或歧义引用都会通过 stderr 输出有界摘要,不会污染 MCP 使用的 stdout。
|
|
389
|
-
|
|
390
|
-
未解析或存在多个精确候选的引用会保持原值,项目不会进行模糊、忽略大小写或裁剪空白后的匹配,也不会加载外部 URL 或文件引用。只有无法解析文档、缺少顶层版本、`info` 或 `paths` 等整体不可用情况才会阻止兼容模式启动。
|
|
391
|
-
|
|
392
|
-
需要禁用所有修复并让任意 OpenAPI 校验错误阻止启动时,可添加 `--strict-validation`。
|
|
393
|
-
=======
|
|
394
|
-
>>>>>>> a3b93fdd98548eef1c651dab869bc76ce05e0938
|
|
26
|
+
- 支持运行时重新加载,失败时继续保留旧文档;
|
|
27
|
+
- 通过 stdio 接入任意兼容 MCP 的 Agent 或 IDE。
|
|
28
|
+
|
|
29
|
+
## 快速开始
|
|
30
|
+
|
|
31
|
+
要求 Node.js 20 或更高版本。无需安装或克隆项目,直接把以下配置加入 MCP Client:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"mcpServers": {
|
|
36
|
+
"project-api-docs": {
|
|
37
|
+
"command": "npx",
|
|
38
|
+
"args": [
|
|
39
|
+
"-y",
|
|
40
|
+
"openapi-docs-mcp",
|
|
41
|
+
"--source",
|
|
42
|
+
"https://api.example.com/v3/api-docs"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
不同客户端的外层字段可能是 `mcpServers`、`servers` 或其他名称,但 `command` 和 `args` 的内容相同。
|
|
50
|
+
|
|
51
|
+
### 读取本地文档
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx -y openapi-docs-mcp --source ./openapi.yaml
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
MCP Client 中使用本地文件时,建议将文档路径写成绝对路径。
|
|
58
|
+
|
|
59
|
+
### 读取需要鉴权的远程文档
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx -y openapi-docs-mcp \
|
|
63
|
+
--source https://api.example.com/v3/api-docs \
|
|
64
|
+
--header Authorization="Bearer token" \
|
|
65
|
+
--header X-Tenant-Id=tenant-1 \
|
|
66
|
+
--timeout 30000
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 同时连接多个项目
|
|
70
|
+
|
|
71
|
+
每份 OpenAPI 文档对应一个独立实例:
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"mcpServers": {
|
|
76
|
+
"order-api-docs": {
|
|
77
|
+
"command": "npx",
|
|
78
|
+
"args": [
|
|
79
|
+
"-y",
|
|
80
|
+
"openapi-docs-mcp",
|
|
81
|
+
"--source",
|
|
82
|
+
"https://order.example.com/v3/api-docs"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
"user-api-docs": {
|
|
86
|
+
"command": "npx",
|
|
87
|
+
"args": [
|
|
88
|
+
"-y",
|
|
89
|
+
"openapi-docs-mcp",
|
|
90
|
+
"--source",
|
|
91
|
+
"https://user.example.com/v3/api-docs"
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
各实例独立加载和刷新自己的文档,互不影响。
|
|
99
|
+
|
|
100
|
+
## 其他安装方式
|
|
101
|
+
|
|
102
|
+
### 全局安装
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npm install --global openapi-docs-mcp
|
|
106
|
+
openapi-docs-mcp --source https://api.example.com/v3/api-docs
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
全局安装后的 MCP 配置:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"mcpServers": {
|
|
114
|
+
"project-api-docs": {
|
|
115
|
+
"command": "openapi-docs-mcp",
|
|
116
|
+
"args": ["--source", "https://api.example.com/v3/api-docs"]
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 使用 mise 固定 Node.js 版本
|
|
123
|
+
|
|
124
|
+
如果 MCP Client 使用的 Node.js 或 `npx` 不兼容,可以通过 mise 固定运行时:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
mise exec node@24 -- npx --yes openapi-docs-mcp \
|
|
128
|
+
--source https://api.example.com/v3/api-docs
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
对应的 MCP 配置:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"mcpServers": {
|
|
136
|
+
"project-api-docs": {
|
|
137
|
+
"command": "mise",
|
|
138
|
+
"args": [
|
|
139
|
+
"exec",
|
|
140
|
+
"node@24",
|
|
141
|
+
"--",
|
|
142
|
+
"npx",
|
|
143
|
+
"--yes",
|
|
144
|
+
"openapi-docs-mcp",
|
|
145
|
+
"--source",
|
|
146
|
+
"https://api.example.com/v3/api-docs"
|
|
147
|
+
]
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
如果客户端找不到 `mise`,可使用 Windows 的 `where.exe mise` 或 macOS/Linux 的 `which mise` 查询路径,并将 `command` 替换为绝对路径。
|
|
154
|
+
|
|
155
|
+
## CLI 参数
|
|
156
|
+
|
|
157
|
+
| 参数 | 说明 |
|
|
158
|
+
| :--------------------- | :---------------------------------------------- |
|
|
159
|
+
| `-s, --source <value>` | OpenAPI JSON/YAML 文件或 HTTP(S) URL,必填 |
|
|
160
|
+
| `--header NAME=VALUE` | 加载远程文档时使用的请求头,可重复传入 |
|
|
161
|
+
| `--timeout <ms>` | 远程加载超时,默认 10000 毫秒 |
|
|
162
|
+
| `--strict-validation` | 禁用兼容修复,并将所有 OpenAPI 校验警告视为错误 |
|
|
163
|
+
| `-h, --help` | 显示帮助 |
|
|
164
|
+
|
|
165
|
+
## MCP 工具
|
|
166
|
+
|
|
167
|
+
| 工具 | 作用 |
|
|
168
|
+
| :---------------- | :------------------------------------------------- |
|
|
169
|
+
| `search_api` | 按关键词、路径、Tag、描述或 `operationId` 搜索接口 |
|
|
170
|
+
| `get_api` | 获取接口参数、请求体、响应和展开后的 Schema |
|
|
171
|
+
| `get_schema` | 按名称读取组件 Schema |
|
|
172
|
+
| `list_groups` | 列出 OpenAPI Tags 及接口数量 |
|
|
173
|
+
| `reload_document` | 重新加载文档,无需重启 MCP Server |
|
|
174
|
+
|
|
175
|
+
### `search_api`
|
|
176
|
+
|
|
177
|
+
返回经过排序的轻量候选结果。推荐先搜索,再把结果中的 `id` 传给 `get_api`。
|
|
178
|
+
|
|
179
|
+
| 参数 | 必填 | 说明 |
|
|
180
|
+
| :------- | :--: | :----------------------------------------------- |
|
|
181
|
+
| `query` | 否 | 搜索关键词,例如 `异常分页列表` 或 `create user` |
|
|
182
|
+
| `method` | 否 | HTTP 方法过滤条件,例如 `GET`、`POST` |
|
|
183
|
+
| `tag` | 否 | 精确匹配 OpenAPI Tag |
|
|
184
|
+
| `limit` | 否 | 返回数量,默认 10,最大 50 |
|
|
185
|
+
|
|
186
|
+
搜索依次侧重 `summary`、`tags`、`path`、`description` 和 `operationId`。中文搜索不依赖空格分词,会结合标准化、包含匹配和字符片段进行评分。
|
|
187
|
+
|
|
188
|
+
### `get_api`
|
|
189
|
+
|
|
190
|
+
获取单个接口的完整上下文,包括 HTTP 方法、路径、参数、请求体、响应、Tags、Security、Deprecated 元数据和展开后的 Schema。
|
|
191
|
+
|
|
192
|
+
优先传入 `search_api` 返回的 `id`;也可以传入精确的 `path` 和可选的 `method`。`maxDepth` 控制 Schema 最大展开深度,默认 5,范围为 1–12。
|
|
193
|
+
|
|
194
|
+
### `get_schema`
|
|
195
|
+
|
|
196
|
+
按精确名称读取 `components.schemas` 中的 Schema。`maxDepth` 同样默认为 5,范围为 1–12。本地 `$ref` 展开具有深度、属性数量和循环引用保护。
|
|
197
|
+
|
|
198
|
+
### `list_groups`
|
|
199
|
+
|
|
200
|
+
列出 OpenAPI Tags 及每个 Tag 下的接口数量。没有 Tag 的接口归入 `untagged`。
|
|
201
|
+
|
|
202
|
+
### `reload_document`
|
|
203
|
+
|
|
204
|
+
重新加载并校验启动时指定的文档,然后原子替换内存索引。加载失败时返回错误,并继续使用上一次成功加载的文档。
|
|
205
|
+
|
|
206
|
+
## 推荐调用流程
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
用户描述需要实现的功能
|
|
210
|
+
↓
|
|
211
|
+
search_api 搜索候选接口
|
|
212
|
+
↓
|
|
213
|
+
根据 summary、tag、path 选择接口
|
|
214
|
+
↓
|
|
215
|
+
get_api 获取请求和响应结构
|
|
216
|
+
↓
|
|
217
|
+
必要时调用 get_schema
|
|
218
|
+
↓
|
|
219
|
+
生成类型、API 方法或业务代码
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## 文档兼容与校验
|
|
223
|
+
|
|
224
|
+
默认使用兼容校验模式。部分 Springdoc 文档会生成包含中文名称、缺少本地前缀或未转义 JSON Pointer 字符的 `$ref`。只要目标能够唯一确定,项目就会修复内存副本并输出诊断,但不会修改源文件。
|
|
225
|
+
|
|
226
|
+
兼容模式还会跳过无法表示为对象的 path item 或 operation,并为缺少 `responses` 的 operation 补充空对象。修复、跳过、未解析引用和歧义引用会通过 stderr 输出有界摘要,不会污染 MCP 使用的 stdout。
|
|
227
|
+
|
|
228
|
+
无法解析或存在多个精确候选的引用会保留原值。项目不会进行模糊、忽略大小写或裁剪空白后的匹配,也不会加载外部 URL 或文件引用。无法解析文档,或缺少顶层版本、`info`、`paths` 等整体不可用的情况,仍会阻止服务启动。
|
|
229
|
+
|
|
230
|
+
如需禁用所有兼容修复,请使用 `--strict-validation`。
|
|
231
|
+
|
|
232
|
+
## 当前限制
|
|
233
|
+
|
|
234
|
+
- 不调用真实后端 API;
|
|
235
|
+
- 不保存或管理后端鉴权凭证;
|
|
236
|
+
- 不展开其他文件或 URL 中的外部 `$ref`;
|
|
237
|
+
- 不提供向量数据库或 Embedding 搜索;
|
|
238
|
+
- 不支持 Streamable HTTP 部署;
|
|
239
|
+
- 不自动轮询 OpenAPI 文档或监听文件变化;
|
|
240
|
+
- 不依赖模型厂商私有能力。
|
|
241
|
+
|
|
242
|
+
文档发生变化时,可调用 `reload_document`,也可以重启 MCP Server。
|
|
243
|
+
|
|
244
|
+
## 本地开发
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
pnpm install
|
|
248
|
+
pnpm typecheck
|
|
249
|
+
pnpm test
|
|
250
|
+
pnpm build
|
|
251
|
+
node dist/cli.js --source ./openapi.json
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
本地 MCP 配置需要使用 `dist/cli.js` 和 OpenAPI 文档的绝对路径:
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"mcpServers": {
|
|
259
|
+
"local-api-docs": {
|
|
260
|
+
"command": "node",
|
|
261
|
+
"args": [
|
|
262
|
+
"C:/absolute/path/openapi-docs-mcp/dist/cli.js",
|
|
263
|
+
"--source",
|
|
264
|
+
"C:/absolute/path/openapi.json"
|
|
265
|
+
]
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## 设计原则
|
|
272
|
+
|
|
273
|
+
```text
|
|
274
|
+
OpenAPI / Swagger
|
|
275
|
+
↓
|
|
276
|
+
解析、保守归一化与校验
|
|
277
|
+
↓
|
|
278
|
+
标准 OpenAPI Document
|
|
279
|
+
↓
|
|
280
|
+
内存 Operation 索引
|
|
281
|
+
↓
|
|
282
|
+
Search + Formatter
|
|
283
|
+
↓
|
|
284
|
+
标准 MCP Tools
|
|
285
|
+
↓
|
|
286
|
+
任意支持 MCP 的 Agent 或 IDE
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
OpenAPI Document 始终是事实来源,自定义类型只用于搜索结果和 MCP 输出。Formatter 不会改写已加载的 OpenAPI 声明;兼容模式只在加载阶段修复能够唯一确定目标的局部缺陷,避免根据相似度猜测后端含义。
|
|
290
|
+
|
|
291
|
+
## License
|
|
292
|
+
|
|
293
|
+
[MIT](LICENSE)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operation.d.ts","sourceRoot":"","sources":["../../src/formatter/operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"operation.d.ts","sourceRoot":"","sources":["../../src/formatter/operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAanF,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAC1B,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,mBAAwB,GAChC,UAAU,CAuCZ"}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { asObject, asString } from "../openapi/operations.js";
|
|
2
|
-
import { formatSchema, resolveLocalReference } from "./schema.js";
|
|
2
|
+
import { decodeReferenceName, formatSchema, resolveLocalReference, } from "./schema.js";
|
|
3
3
|
export function formatOperation(document, entry, options = {}) {
|
|
4
4
|
const operation = entry.operation;
|
|
5
5
|
const parameters = [
|
|
6
6
|
...asArray(entry.pathItem.parameters),
|
|
7
7
|
...asArray(operation.parameters),
|
|
8
|
-
].map((parameter) => formatParameter(document, parameter, options));
|
|
8
|
+
].map((parameter) => formatParameter(document, parameter, options, initialReferenceState()));
|
|
9
9
|
const result = {
|
|
10
10
|
id: entry.id,
|
|
11
11
|
method: entry.method.toUpperCase(),
|
|
12
12
|
path: entry.path,
|
|
13
13
|
tags: entry.tags,
|
|
14
14
|
parameters,
|
|
15
|
-
responses: formatResponses(document, operation.responses, options),
|
|
15
|
+
responses: formatResponses(document, operation.responses, options, initialReferenceState()),
|
|
16
16
|
};
|
|
17
17
|
copyIfDefined(result, "summary", entry.summary);
|
|
18
18
|
copyIfDefined(result, "description", entry.description);
|
|
@@ -20,20 +20,24 @@ export function formatOperation(document, entry, options = {}) {
|
|
|
20
20
|
copyIfDefined(result, "deprecated", operation.deprecated);
|
|
21
21
|
copyIfDefined(result, "security", operation.security);
|
|
22
22
|
const requestBody = asObject(operation.requestBody);
|
|
23
|
-
if (requestBody)
|
|
24
|
-
result.requestBody = formatRequestBody(document, requestBody, options);
|
|
23
|
+
if (requestBody) {
|
|
24
|
+
result.requestBody = formatRequestBody(document, requestBody, options, initialReferenceState());
|
|
25
|
+
}
|
|
25
26
|
return result;
|
|
26
27
|
}
|
|
27
|
-
function formatParameter(document, rawParameter, options) {
|
|
28
|
+
function formatParameter(document, rawParameter, options, state) {
|
|
28
29
|
const parameter = asObject(rawParameter);
|
|
29
30
|
if (!parameter)
|
|
30
31
|
return rawParameter;
|
|
31
32
|
const ref = asString(parameter.$ref);
|
|
32
33
|
if (ref) {
|
|
34
|
+
const boundary = referenceBoundary(ref, options, state);
|
|
35
|
+
if (boundary)
|
|
36
|
+
return boundary;
|
|
33
37
|
const resolved = resolveLocalReference(document, ref);
|
|
34
38
|
return referenceEnvelope(ref, resolved === undefined
|
|
35
39
|
? undefined
|
|
36
|
-
: formatParameter(document, withoutSameReference(resolved, ref), options), "parameter");
|
|
40
|
+
: formatParameter(document, withoutSameReference(resolved, ref), options, nextReferenceState(state, ref)), "parameter");
|
|
37
41
|
}
|
|
38
42
|
const result = {};
|
|
39
43
|
for (const key of ["name", "in", "required", "description", "deprecated", "style", "explode"]) {
|
|
@@ -47,12 +51,17 @@ function formatParameter(document, rawParameter, options) {
|
|
|
47
51
|
}
|
|
48
52
|
return result;
|
|
49
53
|
}
|
|
50
|
-
function formatRequestBody(document, requestBody, options) {
|
|
54
|
+
function formatRequestBody(document, requestBody, options, state) {
|
|
51
55
|
const ref = asString(requestBody.$ref);
|
|
52
56
|
if (ref) {
|
|
57
|
+
const boundary = referenceBoundary(ref, options, state);
|
|
58
|
+
if (boundary)
|
|
59
|
+
return boundary;
|
|
53
60
|
const resolved = resolveLocalReference(document, ref);
|
|
54
61
|
const body = asObject(withoutSameReference(resolved, ref));
|
|
55
|
-
return referenceEnvelope(ref, body
|
|
62
|
+
return referenceEnvelope(ref, body
|
|
63
|
+
? formatRequestBody(document, body, options, nextReferenceState(state, ref))
|
|
64
|
+
: undefined, "requestBody");
|
|
56
65
|
}
|
|
57
66
|
const result = {
|
|
58
67
|
required: requestBody.required === true,
|
|
@@ -61,7 +70,7 @@ function formatRequestBody(document, requestBody, options) {
|
|
|
61
70
|
copyIfDefined(result, "description", requestBody.description);
|
|
62
71
|
return result;
|
|
63
72
|
}
|
|
64
|
-
function formatResponses(document, rawResponses, options) {
|
|
73
|
+
function formatResponses(document, rawResponses, options, state) {
|
|
65
74
|
const responses = asObject(rawResponses);
|
|
66
75
|
if (!responses)
|
|
67
76
|
return {};
|
|
@@ -71,11 +80,14 @@ function formatResponses(document, rawResponses, options) {
|
|
|
71
80
|
return [status, rawResponse];
|
|
72
81
|
const ref = asString(response.$ref);
|
|
73
82
|
if (ref) {
|
|
83
|
+
const boundary = referenceBoundary(ref, options, state);
|
|
84
|
+
if (boundary)
|
|
85
|
+
return [status, boundary];
|
|
74
86
|
const resolved = asObject(withoutSameReference(resolveLocalReference(document, ref), ref));
|
|
75
87
|
return [
|
|
76
88
|
status,
|
|
77
89
|
referenceEnvelope(ref, resolved
|
|
78
|
-
? formatResponses(document, { resolved }, options).resolved
|
|
90
|
+
? formatResponses(document, { resolved }, options, nextReferenceState(state, ref)).resolved
|
|
79
91
|
: undefined, "response"),
|
|
80
92
|
];
|
|
81
93
|
}
|
|
@@ -120,7 +132,7 @@ function copyIfDefined(target, key, value) {
|
|
|
120
132
|
function referenceEnvelope(ref, value, key) {
|
|
121
133
|
const result = {
|
|
122
134
|
$ref: ref,
|
|
123
|
-
name:
|
|
135
|
+
name: decodeReferenceName(ref),
|
|
124
136
|
};
|
|
125
137
|
if (value === undefined)
|
|
126
138
|
result.unresolved = true;
|
|
@@ -128,6 +140,27 @@ function referenceEnvelope(ref, value, key) {
|
|
|
128
140
|
result[key] = value;
|
|
129
141
|
return result;
|
|
130
142
|
}
|
|
143
|
+
function referenceBoundary(ref, options, state) {
|
|
144
|
+
if (state.references.has(ref)) {
|
|
145
|
+
return { $ref: ref, name: decodeReferenceName(ref), circular: true };
|
|
146
|
+
}
|
|
147
|
+
if (state.depth >= (options.maxDepth ?? 5)) {
|
|
148
|
+
return {
|
|
149
|
+
$ref: ref,
|
|
150
|
+
name: decodeReferenceName(ref),
|
|
151
|
+
truncated: "maxDepth",
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
function initialReferenceState() {
|
|
157
|
+
return { depth: 0, references: new Set() };
|
|
158
|
+
}
|
|
159
|
+
function nextReferenceState(state, ref) {
|
|
160
|
+
const references = new Set(state.references);
|
|
161
|
+
references.add(ref);
|
|
162
|
+
return { depth: state.depth + 1, references };
|
|
163
|
+
}
|
|
131
164
|
function withoutSameReference(value, ref) {
|
|
132
165
|
const object = asObject(value);
|
|
133
166
|
return object?.$ref === ref ? undefined : value;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operation.js","sourceRoot":"","sources":["../../src/formatter/operation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,
|
|
1
|
+
{"version":3,"file":"operation.js","sourceRoot":"","sources":["../../src/formatter/operation.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,4 +4,5 @@ export declare function formatSchema(document: OpenAPI.Document, schema: unknown
|
|
|
4
4
|
export declare function listSchemaNames(document: OpenAPI.Document): string[];
|
|
5
5
|
export declare function findSchema(document: OpenAPI.Document, name: string): unknown;
|
|
6
6
|
export declare function resolveLocalReference(document: OpenAPI.Document, ref: string): unknown;
|
|
7
|
+
export declare function decodeReferenceName(ref: string): string;
|
|
7
8
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/formatter/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAc,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAQnE,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAC1B,MAAM,EAAE,OAAO,EACf,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAKT;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAG,MAAM,EAAE,CAKpE;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAK5E;AAwHD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAYtF"}
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/formatter/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAc,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAQnE,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAC1B,MAAM,EAAE,OAAO,EACf,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAKT;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAG,MAAM,EAAE,CAKpE;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAK5E;AAwHD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAYtF;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIvD"}
|
package/dist/formatter/schema.js
CHANGED
|
@@ -25,7 +25,7 @@ function formatSchemaNode(document, rawSchema, options, state) {
|
|
|
25
25
|
return rawSchema ?? null;
|
|
26
26
|
const ref = asString(schema.$ref);
|
|
27
27
|
if (ref) {
|
|
28
|
-
const refName =
|
|
28
|
+
const refName = decodeReferenceName(ref);
|
|
29
29
|
if (state.references.has(ref)) {
|
|
30
30
|
return { $ref: ref, name: refName, circular: true };
|
|
31
31
|
}
|
|
@@ -124,7 +124,7 @@ export function resolveLocalReference(document, ref) {
|
|
|
124
124
|
const parts = ref
|
|
125
125
|
.slice(2)
|
|
126
126
|
.split("/")
|
|
127
|
-
.map((part) => part.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
127
|
+
.map((part) => safeDecodeURIComponent(part).replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
128
128
|
let current = document;
|
|
129
129
|
for (const part of parts) {
|
|
130
130
|
current = asObject(current)?.[part];
|
|
@@ -133,6 +133,19 @@ export function resolveLocalReference(document, ref) {
|
|
|
133
133
|
}
|
|
134
134
|
return current;
|
|
135
135
|
}
|
|
136
|
+
export function decodeReferenceName(ref) {
|
|
137
|
+
return safeDecodeURIComponent(ref.split("/").at(-1) ?? ref)
|
|
138
|
+
.replace(/~1/g, "/")
|
|
139
|
+
.replace(/~0/g, "~");
|
|
140
|
+
}
|
|
141
|
+
function safeDecodeURIComponent(value) {
|
|
142
|
+
try {
|
|
143
|
+
return decodeURIComponent(value);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return value;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
136
149
|
function copyKnownValues(source, target, keys) {
|
|
137
150
|
for (const key of keys) {
|
|
138
151
|
if (source[key] !== undefined)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/formatter/schema.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAO9D,MAAM,UAAU,YAAY,CAC1B,QAA0B,EAC1B,MAAe,EACf,OAAO,GAAwB,EAAE;IAEjC,OAAO,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE;QACxC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC;QAC/B,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,GAAG;KAC5C,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAA0B;IACxD,MAAM,IAAI,GAAG,QAAiC,CAAC;IAC/C,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5E,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAA0B,EAAE,IAAY;IACjE,MAAM,IAAI,GAAG,QAAiC,CAAC;IAC/C,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5E,OAAO,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,gBAAgB,CACvB,QAA0B,EAC1B,SAAkB,EAClB,OAAsC,EACtC,KAAkB;IAElB,IAAI,OAAO,SAAS,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACrD,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,IAAI,IAAI,CAAC;IAEtC,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/formatter/schema.ts"],"names":[],"mappings":"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"}
|