openapi-docs-mcp 0.1.4 → 0.1.5
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/LICENSE +21 -21
- package/README.md +392 -215
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -2
- package/dist/cli.js.map +1 -1
- package/dist/openapi/diagnostics.d.ts +3 -0
- package/dist/openapi/diagnostics.d.ts.map +1 -0
- package/dist/openapi/diagnostics.js +24 -0
- package/dist/openapi/diagnostics.js.map +1 -0
- package/dist/openapi/loader.d.ts.map +1 -1
- package/dist/openapi/loader.js +61 -45
- package/dist/openapi/loader.js.map +1 -1
- package/dist/openapi/normalize.d.ts +7 -0
- package/dist/openapi/normalize.d.ts.map +1 -0
- package/dist/openapi/normalize.js +203 -0
- package/dist/openapi/normalize.js.map +1 -0
- package/dist/openapi/operations.d.ts.map +1 -1
- package/dist/openapi/operations.js +19 -1
- package/dist/openapi/operations.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,217 +1,394 @@
|
|
|
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
|
-
**OpenAPI Docs MCP**
|
|
20
|
-
|
|
21
|
-
npm 包:[`openapi-docs-mcp`](https://www.npmjs.com/package/openapi-docs-mcp)
|
|
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
|
+
**快速导航:** [名称](#名称) · [简介](#简介) · [详细描述](#详细描述) · [项目状态](#项目状态) · [使用方法](#使用方法)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 名称
|
|
18
|
+
|
|
19
|
+
**OpenAPI Docs MCP**
|
|
20
|
+
|
|
21
|
+
npm 包:[`openapi-docs-mcp`](https://www.npmjs.com/package/openapi-docs-mcp)
|
|
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`,限制最大深度和属性数量;
|
|
47
47
|
- 检测循环引用,并标记无法解析的引用;
|
|
48
|
+
- 兼容模式可保守修复确定可解析的脏 `$ref`,并报告修复、跳过和校验诊断;
|
|
48
49
|
- 远程文档支持自定义请求头和超时;
|
|
49
|
-
- 刷新失败时保留旧文档,不影响现有查询;
|
|
50
|
-
- 通过 stdio 工作,可接入任意兼容 MCP 的 Agent 或 IDE。
|
|
51
|
-
|
|
52
|
-
## 项目状态
|
|
53
|
-
|
|
54
|
-
| 项目 | 状态 |
|
|
55
|
-
| :--- | :--- |
|
|
56
|
-
| 当前版本 | `0.1.
|
|
57
|
-
| 运行环境 | Node.js 20+ |
|
|
58
|
-
| 项目阶段 | 可用的早期版本 |
|
|
59
|
-
| 传输方式 | stdio |
|
|
60
|
-
| 许可证 | MIT |
|
|
61
|
-
|
|
62
|
-
> **说明:** 当前暂不支持外部文件或 URL `$ref`、向量搜索、Streamable HTTP 部署以及真实后端 API 调用。
|
|
63
|
-
|
|
64
|
-
## 使用方法
|
|
65
|
-
|
|
66
|
-
### 方式一:通过 npx 运行(推荐)
|
|
67
|
-
|
|
68
|
-
无需安装或克隆项目,直接在 MCP Client 中启动:
|
|
69
|
-
|
|
70
|
-
```json
|
|
71
|
-
{
|
|
72
|
-
"mcpServers": {
|
|
73
|
-
"project-api-docs": {
|
|
74
|
-
"command": "npx",
|
|
75
|
-
"args": [
|
|
76
|
-
"-y",
|
|
77
|
-
"openapi-docs-mcp@0.1.
|
|
78
|
-
"--source",
|
|
79
|
-
"https://api.example.com/v3/api-docs",
|
|
80
|
-
"--timeout",
|
|
81
|
-
"30000"
|
|
82
|
-
]
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### 方式二:全局安装
|
|
89
|
-
|
|
90
|
-
安装后可以直接使用 `openapi-docs-mcp` 命令:
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
npm install --global openapi-docs-mcp@0.1.
|
|
94
|
-
openapi-docs-mcp --source https://api.example.com/v3/api-docs --timeout 30000
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
对应的 MCP Client 配置:
|
|
98
|
-
|
|
99
|
-
```json
|
|
100
|
-
{
|
|
101
|
-
"mcpServers": {
|
|
102
|
-
"project-api-docs": {
|
|
103
|
-
"command": "openapi-docs-mcp",
|
|
104
|
-
"args": [
|
|
105
|
-
"--source",
|
|
106
|
-
"https://api.example.com/v3/api-docs",
|
|
107
|
-
"--timeout",
|
|
108
|
-
"30000"
|
|
109
|
-
]
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### 方式三:通过 mise 固定 Node.js
|
|
116
|
-
|
|
117
|
-
如果 MCP Client 使用了不兼容的 Node.js 或 `npx`,可以通过 mise 固定运行时版本:
|
|
118
|
-
|
|
119
|
-
```bash
|
|
120
|
-
mise exec node@24 -- npx --yes openapi-docs-mcp@0.1.
|
|
121
|
-
--source https://api.example.com/v3/api-docs \
|
|
122
|
-
--timeout 30000
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
在 MCP Client 中,将 `mise` 作为启动命令:
|
|
126
|
-
|
|
127
|
-
```json
|
|
128
|
-
{
|
|
129
|
-
"mcpServers": {
|
|
130
|
-
"project-api-docs": {
|
|
131
|
-
"command": "mise",
|
|
132
|
-
"args": [
|
|
133
|
-
"exec",
|
|
134
|
-
"node@24",
|
|
135
|
-
"--",
|
|
136
|
-
"npx",
|
|
137
|
-
"--yes",
|
|
138
|
-
"openapi-docs-mcp@0.1.
|
|
139
|
-
"--source",
|
|
140
|
-
"https://api.example.com/v3/api-docs",
|
|
141
|
-
"--timeout",
|
|
142
|
-
"30000"
|
|
143
|
-
]
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
> **提示:** 不同 MCP Client 的外层配置字段可能是 `mcpServers`、`servers` 或其他名称,但 `command` 和 `args` 的内容相同。如果客户端找不到 `mise`,可通过 Windows 的 `where.exe mise` 或 macOS/Linux 的 `which mise` 查询路径,并将 `command` 替换为绝对路径。
|
|
150
|
-
|
|
151
|
-
### 方式四:同时连接多个项目
|
|
152
|
-
|
|
153
|
-
为每份 OpenAPI 文档配置一个独立的 MCP 实例:
|
|
154
|
-
|
|
155
|
-
```json
|
|
156
|
-
{
|
|
157
|
-
"mcpServers": {
|
|
158
|
-
"order-api-docs": {
|
|
159
|
-
"command": "npx",
|
|
160
|
-
"args": [
|
|
161
|
-
"-y",
|
|
162
|
-
"openapi-docs-mcp@0.1.
|
|
163
|
-
"--source",
|
|
164
|
-
"https://order.example.com/v3/api-docs"
|
|
165
|
-
]
|
|
166
|
-
},
|
|
167
|
-
"user-api-docs": {
|
|
168
|
-
"command": "npx",
|
|
169
|
-
"args": [
|
|
170
|
-
"-y",
|
|
171
|
-
"openapi-docs-mcp@0.1.
|
|
172
|
-
"--source",
|
|
173
|
-
"https://user.example.com/v3/api-docs"
|
|
174
|
-
]
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
每个实例单独加载和刷新自己的文档,互不影响。
|
|
181
|
-
|
|
182
|
-
### 更多启动示例
|
|
183
|
-
|
|
184
|
-
**读取本地文档**
|
|
185
|
-
|
|
186
|
-
```bash
|
|
187
|
-
npx -y openapi-docs-mcp@0.1.
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
**读取需要鉴权的远程文档**
|
|
191
|
-
|
|
192
|
-
```bash
|
|
193
|
-
npx -y openapi-docs-mcp@0.1.
|
|
194
|
-
--source https://api.example.com/v3/api-docs \
|
|
195
|
-
--header Authorization="Bearer token" \
|
|
196
|
-
--header X-Tenant-Id=tenant-1 \
|
|
197
|
-
--timeout 30000
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### CLI 参数
|
|
201
|
-
|
|
202
|
-
| 参数 | 说明 |
|
|
203
|
-
| :--- | :--- |
|
|
204
|
-
| `-s, --source <value>` | OpenAPI 文件或 HTTP(S) URL,必填 |
|
|
205
|
-
| `--header NAME=VALUE` | 远程文档请求头,可重复使用 |
|
|
206
|
-
| `--timeout <ms>` | 远程加载超时,默认 10000 毫秒 |
|
|
207
|
-
| `--strict-validation` | 将所有 OpenAPI 校验警告视为错误 |
|
|
208
|
-
| `-h, --help` | 显示帮助 |
|
|
209
|
-
|
|
210
|
-
### 本地开发
|
|
211
|
-
|
|
212
|
-
```bash
|
|
213
|
-
pnpm install
|
|
214
|
-
pnpm test
|
|
215
|
-
pnpm build
|
|
216
|
-
node dist/cli.js --source ./openapi.json
|
|
217
|
-
```
|
|
50
|
+
- 刷新失败时保留旧文档,不影响现有查询;
|
|
51
|
+
- 通过 stdio 工作,可接入任意兼容 MCP 的 Agent 或 IDE。
|
|
52
|
+
|
|
53
|
+
## 项目状态
|
|
54
|
+
|
|
55
|
+
| 项目 | 状态 |
|
|
56
|
+
| :--- | :--- |
|
|
57
|
+
| 当前版本 | `0.1.5` |
|
|
58
|
+
| 运行环境 | Node.js 20+ |
|
|
59
|
+
| 项目阶段 | 可用的早期版本 |
|
|
60
|
+
| 传输方式 | stdio |
|
|
61
|
+
| 许可证 | MIT |
|
|
62
|
+
|
|
63
|
+
> **说明:** 当前暂不支持外部文件或 URL `$ref`、向量搜索、Streamable HTTP 部署以及真实后端 API 调用。
|
|
64
|
+
|
|
65
|
+
## 使用方法
|
|
66
|
+
|
|
67
|
+
### 方式一:通过 npx 运行(推荐)
|
|
68
|
+
|
|
69
|
+
无需安装或克隆项目,直接在 MCP Client 中启动:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"mcpServers": {
|
|
74
|
+
"project-api-docs": {
|
|
75
|
+
"command": "npx",
|
|
76
|
+
"args": [
|
|
77
|
+
"-y",
|
|
78
|
+
"openapi-docs-mcp@0.1.5",
|
|
79
|
+
"--source",
|
|
80
|
+
"https://api.example.com/v3/api-docs",
|
|
81
|
+
"--timeout",
|
|
82
|
+
"30000"
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 方式二:全局安装
|
|
90
|
+
|
|
91
|
+
安装后可以直接使用 `openapi-docs-mcp` 命令:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npm install --global openapi-docs-mcp@0.1.5
|
|
95
|
+
openapi-docs-mcp --source https://api.example.com/v3/api-docs --timeout 30000
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
对应的 MCP Client 配置:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"mcpServers": {
|
|
103
|
+
"project-api-docs": {
|
|
104
|
+
"command": "openapi-docs-mcp",
|
|
105
|
+
"args": [
|
|
106
|
+
"--source",
|
|
107
|
+
"https://api.example.com/v3/api-docs",
|
|
108
|
+
"--timeout",
|
|
109
|
+
"30000"
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 方式三:通过 mise 固定 Node.js
|
|
117
|
+
|
|
118
|
+
如果 MCP Client 使用了不兼容的 Node.js 或 `npx`,可以通过 mise 固定运行时版本:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
mise exec node@24 -- npx --yes openapi-docs-mcp@0.1.5 \
|
|
122
|
+
--source https://api.example.com/v3/api-docs \
|
|
123
|
+
--timeout 30000
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
在 MCP Client 中,将 `mise` 作为启动命令:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"mcpServers": {
|
|
131
|
+
"project-api-docs": {
|
|
132
|
+
"command": "mise",
|
|
133
|
+
"args": [
|
|
134
|
+
"exec",
|
|
135
|
+
"node@24",
|
|
136
|
+
"--",
|
|
137
|
+
"npx",
|
|
138
|
+
"--yes",
|
|
139
|
+
"openapi-docs-mcp@0.1.5",
|
|
140
|
+
"--source",
|
|
141
|
+
"https://api.example.com/v3/api-docs",
|
|
142
|
+
"--timeout",
|
|
143
|
+
"30000"
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
> **提示:** 不同 MCP Client 的外层配置字段可能是 `mcpServers`、`servers` 或其他名称,但 `command` 和 `args` 的内容相同。如果客户端找不到 `mise`,可通过 Windows 的 `where.exe mise` 或 macOS/Linux 的 `which mise` 查询路径,并将 `command` 替换为绝对路径。
|
|
151
|
+
|
|
152
|
+
### 方式四:同时连接多个项目
|
|
153
|
+
|
|
154
|
+
为每份 OpenAPI 文档配置一个独立的 MCP 实例:
|
|
155
|
+
|
|
156
|
+
```json
|
|
157
|
+
{
|
|
158
|
+
"mcpServers": {
|
|
159
|
+
"order-api-docs": {
|
|
160
|
+
"command": "npx",
|
|
161
|
+
"args": [
|
|
162
|
+
"-y",
|
|
163
|
+
"openapi-docs-mcp@0.1.5",
|
|
164
|
+
"--source",
|
|
165
|
+
"https://order.example.com/v3/api-docs"
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
"user-api-docs": {
|
|
169
|
+
"command": "npx",
|
|
170
|
+
"args": [
|
|
171
|
+
"-y",
|
|
172
|
+
"openapi-docs-mcp@0.1.5",
|
|
173
|
+
"--source",
|
|
174
|
+
"https://user.example.com/v3/api-docs"
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
每个实例单独加载和刷新自己的文档,互不影响。
|
|
182
|
+
|
|
183
|
+
### 更多启动示例
|
|
184
|
+
|
|
185
|
+
**读取本地文档**
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
npx -y openapi-docs-mcp@0.1.5 --source ./openapi.yaml
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**读取需要鉴权的远程文档**
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
npx -y openapi-docs-mcp@0.1.5 \
|
|
195
|
+
--source https://api.example.com/v3/api-docs \
|
|
196
|
+
--header Authorization="Bearer token" \
|
|
197
|
+
--header X-Tenant-Id=tenant-1 \
|
|
198
|
+
--timeout 30000
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### CLI 参数
|
|
202
|
+
|
|
203
|
+
| 参数 | 说明 |
|
|
204
|
+
| :--- | :--- |
|
|
205
|
+
| `-s, --source <value>` | OpenAPI 文件或 HTTP(S) URL,必填 |
|
|
206
|
+
| `--header NAME=VALUE` | 远程文档请求头,可重复使用 |
|
|
207
|
+
| `--timeout <ms>` | 远程加载超时,默认 10000 毫秒 |
|
|
208
|
+
| `--strict-validation` | 将所有 OpenAPI 校验警告视为错误 |
|
|
209
|
+
| `-h, --help` | 显示帮助 |
|
|
210
|
+
|
|
211
|
+
### 本地开发
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
pnpm install
|
|
215
|
+
pnpm test
|
|
216
|
+
pnpm build
|
|
217
|
+
node dist/cli.js --source ./openapi.json
|
|
218
|
+
```
|
|
219
|
+
<<<<<<< HEAD
|
|
220
|
+
|
|
221
|
+
本地 MCP 配置需要使用 `dist/cli.js` 的绝对路径:
|
|
222
|
+
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"mcpServers": {
|
|
226
|
+
"local-api-docs": {
|
|
227
|
+
"command": "node",
|
|
228
|
+
"args": [
|
|
229
|
+
"C:/absolute/path/openapi-docs-mcp/dist/cli.js",
|
|
230
|
+
"--source",
|
|
231
|
+
"C:/absolute/path/openapi.json"
|
|
232
|
+
]
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## MCP 工具
|
|
239
|
+
|
|
240
|
+
### `search_api`
|
|
241
|
+
|
|
242
|
+
根据自然语言关键词、路径、标签、描述或 `operationId` 搜索接口,返回经过排序的轻量候选结果。
|
|
243
|
+
|
|
244
|
+
正常工作流是先调用 `search_api` 找到接口,再把结果中的 `id` 传给 `get_api`。
|
|
245
|
+
|
|
246
|
+
输入参数:
|
|
247
|
+
|
|
248
|
+
| 参数 | 必填 | 说明 |
|
|
249
|
+
| -------- | ---: | ------------------------------------------------ |
|
|
250
|
+
| `query` | 否 | 搜索关键词,例如 `异常分页列表` 或 `create user` |
|
|
251
|
+
| `method` | 否 | HTTP 方法过滤条件,例如 `GET`、`POST` |
|
|
252
|
+
| `tag` | 否 | 精确匹配 OpenAPI Tag |
|
|
253
|
+
| `limit` | 否 | 返回数量,默认 10,最大 50 |
|
|
254
|
+
|
|
255
|
+
搜索字段权重:
|
|
256
|
+
|
|
257
|
+
| 字段 | 权重 |
|
|
258
|
+
| ------------- | ---: |
|
|
259
|
+
| `summary` | 10 |
|
|
260
|
+
| `tags` | 8 |
|
|
261
|
+
| `path` | 6 |
|
|
262
|
+
| `description` | 4 |
|
|
263
|
+
| `operationId` | 2 |
|
|
264
|
+
|
|
265
|
+
中文搜索不依赖空格分词,会使用标准化、包含匹配以及二元/三元字符片段进行评分。
|
|
266
|
+
|
|
267
|
+
### `get_api`
|
|
268
|
+
|
|
269
|
+
获取单个接口的完整上下文,包括:
|
|
270
|
+
|
|
271
|
+
- HTTP 方法和路径;
|
|
272
|
+
- Summary、Description 和 Tags;
|
|
273
|
+
- Path、Query、Header、Cookie 参数;
|
|
274
|
+
- Request Body 和 Content-Type;
|
|
275
|
+
- Responses;
|
|
276
|
+
- Security 和 Deprecated 元数据;
|
|
277
|
+
- 按需展开后的 Schema。
|
|
278
|
+
|
|
279
|
+
优先传入 `search_api` 返回的 `id`,也可以传入精确的 `path` 和可选的 `method`。
|
|
280
|
+
|
|
281
|
+
`maxDepth` 用于控制 Schema 最大展开深度,默认值为 5,允许范围为 1 到 12。
|
|
282
|
+
|
|
283
|
+
### `get_schema`
|
|
284
|
+
|
|
285
|
+
根据精确名称读取 `components.schemas` 中的 Schema。
|
|
286
|
+
|
|
287
|
+
本地 `$ref` 会按需展开,同时具有:
|
|
288
|
+
|
|
289
|
+
- 最大深度限制;
|
|
290
|
+
- 最大属性数量限制;
|
|
291
|
+
- 循环引用检测;
|
|
292
|
+
- 无法解析的引用标记。
|
|
293
|
+
|
|
294
|
+
### `list_groups`
|
|
295
|
+
|
|
296
|
+
列出 OpenAPI Tags 及每个 Tag 下的接口数量。
|
|
297
|
+
|
|
298
|
+
没有 Tag 的接口会归入 `untagged`。
|
|
299
|
+
|
|
300
|
+
## 推荐调用流程
|
|
301
|
+
|
|
302
|
+
```text
|
|
303
|
+
用户描述需要实现的功能
|
|
304
|
+
↓
|
|
305
|
+
search_api 搜索候选接口
|
|
306
|
+
↓
|
|
307
|
+
根据 summary、tag、path 选择接口
|
|
308
|
+
↓
|
|
309
|
+
get_api 一次获取请求和响应结构
|
|
310
|
+
↓
|
|
311
|
+
必要时再调用 get_schema
|
|
312
|
+
↓
|
|
313
|
+
生成 TypeScript 类型、API 方法和页面调用代码
|
|
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
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAOA,UAAU,UAAU;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAwBD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA2CpD"}
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
3
3
|
import { loadOpenApi } from "./openapi/loader.js";
|
|
4
|
+
import { formatDiagnosticSummary } from "./openapi/diagnostics.js";
|
|
4
5
|
import { createMcpServer } from "./mcp/server.js";
|
|
5
6
|
import { OpenApiService } from "./service.js";
|
|
6
7
|
async function main() {
|
|
@@ -14,8 +15,8 @@ async function main() {
|
|
|
14
15
|
const context = await reload();
|
|
15
16
|
const service = new OpenApiService(context, reload);
|
|
16
17
|
console.error(`Loaded ${context.operations.length} operations from ${context.source} (OpenAPI ${context.version})`);
|
|
17
|
-
for (const
|
|
18
|
-
console.error(
|
|
18
|
+
for (const line of formatDiagnosticSummary(context.diagnostics)) {
|
|
19
|
+
console.error(line);
|
|
19
20
|
}
|
|
20
21
|
serveStdio(() => createMcpServer(service), {
|
|
21
22
|
onerror: (error) => console.error(error),
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAS9C,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG;QAClB,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,cAAc,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY;KAC1D,CAAC;IACX,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,MAAM,MAAM,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,IAAI,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAEpD,OAAO,CAAC,KAAK,CACX,UAAU,OAAO,CAAC,UAAU,CAAC,MAAM,oBAAoB,OAAO,CAAC,MAAM,aAAa,OAAO,CAAC,OAAO,GAAG,CACrG,CAAC;IACF,KAAK,MAAM,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/openapi/diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAQrE,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,iBAAiB,EAAE,EAChC,WAAW,SAAI,GACd,MAAM,EAAE,CAuBV"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function formatDiagnosticSummary(diagnostics, sampleLimit = 5) {
|
|
2
|
+
const limit = Number.isFinite(sampleLimit)
|
|
3
|
+
? Math.max(0, Math.floor(sampleLimit))
|
|
4
|
+
: 0;
|
|
5
|
+
const groups = new Map();
|
|
6
|
+
for (const diagnostic of diagnostics) {
|
|
7
|
+
const group = groups.get(diagnostic.code) ?? {
|
|
8
|
+
code: diagnostic.code,
|
|
9
|
+
count: 0,
|
|
10
|
+
paths: [],
|
|
11
|
+
};
|
|
12
|
+
group.count += 1;
|
|
13
|
+
if (group.paths.length < limit)
|
|
14
|
+
group.paths.push(diagnostic.path || "document");
|
|
15
|
+
groups.set(diagnostic.code, group);
|
|
16
|
+
}
|
|
17
|
+
return [...groups.values()].map((group) => {
|
|
18
|
+
const examples = group.paths.length
|
|
19
|
+
? `; examples: ${group.paths.join(", ")}`
|
|
20
|
+
: "";
|
|
21
|
+
return `OpenAPI diagnostic ${group.code} (${group.count})${examples}`;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/openapi/diagnostics.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,uBAAuB,CACrC,WAAgC,EAChC,WAAW,GAAG,CAAC;IAEf,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC;QACxC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC,CAAC;IACN,MAAM,MAAM,GAAG,IAAI,GAAG,EAAmC,CAAC;IAE1D,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI;YAC3C,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,EAAE;SACV,CAAC;QACF,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QACjB,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK;YAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,CAAC;QAChF,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACxC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM;YACjC,CAAC,CAAC,eAAe,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACzC,CAAC,CAAC,EAAE,CAAC;QACP,OAAO,sBAAsB,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,KAAK,IAAI,QAAQ,EAAE,CAAC;IACxE,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/openapi/loader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/openapi/loader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAqB,MAAM,aAAa,CAAC;AAMjF,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,cAAc,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAC;CAC1C;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,cAAc,CAAC,CAMzB;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,GAAG,UAAU,EAC1B,MAAM,SAAW,EACjB,OAAO,GAAE,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAM,GACvD,OAAO,CAAC,cAAc,CAAC,CA2CzB"}
|
package/dist/openapi/loader.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { validate } from "@scalar/openapi-parser";
|
|
4
|
+
import { normalizeOpenApiDocument } from "./normalize.js";
|
|
4
5
|
import { extractOperations } from "./operations.js";
|
|
5
6
|
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
6
7
|
export async function loadOpenApi(source, options = {}) {
|
|
@@ -10,35 +11,80 @@ export async function loadOpenApi(source, options = {}) {
|
|
|
10
11
|
return createOpenApiContext(content, source, options);
|
|
11
12
|
}
|
|
12
13
|
export async function createOpenApiContext(input, source = "memory", options = {}) {
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
: [];
|
|
19
|
-
const fatalErrors = result.errors.filter((error) => !compatibleErrors.includes(error));
|
|
20
|
-
if (options.validationMode === "strict" || !specification || fatalErrors.length > 0) {
|
|
21
|
-
throw new Error(`Invalid OpenAPI document: ${formatValidationErrors(result.errors)}`);
|
|
14
|
+
const initial = await validateInput(input);
|
|
15
|
+
const initialErrors = initial.errors ?? [];
|
|
16
|
+
if (options.validationMode === "strict") {
|
|
17
|
+
if (!initial.valid || !initial.specification) {
|
|
18
|
+
throw invalidDocument(initialErrors);
|
|
22
19
|
}
|
|
23
|
-
const document = specification;
|
|
24
|
-
assertDocumentShape(document);
|
|
20
|
+
const document = initial.specification;
|
|
25
21
|
return {
|
|
26
22
|
document,
|
|
27
23
|
source,
|
|
28
|
-
version:
|
|
24
|
+
version: initial.version ?? getDocumentVersion(document),
|
|
29
25
|
operations: extractOperations(document),
|
|
30
|
-
validationWarnings:
|
|
26
|
+
validationWarnings: [],
|
|
27
|
+
diagnostics: [],
|
|
31
28
|
};
|
|
32
29
|
}
|
|
30
|
+
if (!initial.specification)
|
|
31
|
+
throw invalidDocument(initialErrors);
|
|
32
|
+
const parsed = initial.specification;
|
|
33
|
+
assertDocumentShape(parsed);
|
|
34
|
+
const normalized = normalizeOpenApiDocument(parsed);
|
|
35
|
+
const result = await validateInput(normalized.document);
|
|
36
|
+
const resultErrors = result.errors ?? [];
|
|
37
|
+
const fatalErrors = resultErrors.filter(isFatalValidationError);
|
|
38
|
+
if (!result.specification || fatalErrors.length > 0) {
|
|
39
|
+
throw invalidDocument(fatalErrors.length ? fatalErrors : resultErrors);
|
|
40
|
+
}
|
|
33
41
|
const document = result.specification;
|
|
42
|
+
assertDocumentShape(document);
|
|
34
43
|
return {
|
|
35
44
|
document,
|
|
36
45
|
source,
|
|
37
|
-
version: result.version,
|
|
46
|
+
version: result.version ?? getDocumentVersion(document),
|
|
38
47
|
operations: extractOperations(document),
|
|
39
|
-
validationWarnings:
|
|
48
|
+
validationWarnings: summarizeWarnings(resultErrors),
|
|
49
|
+
diagnostics: [
|
|
50
|
+
...normalized.diagnostics,
|
|
51
|
+
...resultErrors.map(toValidationDiagnostic),
|
|
52
|
+
],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
async function validateInput(input) {
|
|
56
|
+
try {
|
|
57
|
+
return await validate(input);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
61
|
+
throw new Error(`Invalid OpenAPI document: ${message}`, { cause: error });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function invalidDocument(errors) {
|
|
65
|
+
return new Error(`Invalid OpenAPI document: ${formatValidationErrors(errors)}`);
|
|
66
|
+
}
|
|
67
|
+
function isFatalValidationError(error) {
|
|
68
|
+
const path = validationPath(error);
|
|
69
|
+
return (path === "" ||
|
|
70
|
+
/^\/(?:openapi|swagger|info)(?:\/|$)/.test(path) ||
|
|
71
|
+
path === "/paths");
|
|
72
|
+
}
|
|
73
|
+
function toValidationDiagnostic(error) {
|
|
74
|
+
return {
|
|
75
|
+
severity: "warning",
|
|
76
|
+
code: "validation_warning",
|
|
77
|
+
path: validationPath(error),
|
|
78
|
+
message: error.message,
|
|
40
79
|
};
|
|
41
80
|
}
|
|
81
|
+
function validationPath(error) {
|
|
82
|
+
return Array.isArray(error.path)
|
|
83
|
+
? `/${error.path.join("/")}`
|
|
84
|
+
: typeof error.path === "string"
|
|
85
|
+
? error.path
|
|
86
|
+
: "";
|
|
87
|
+
}
|
|
42
88
|
function isHttpUrl(value) {
|
|
43
89
|
return /^https?:\/\//i.test(value);
|
|
44
90
|
}
|
|
@@ -52,36 +98,6 @@ async function fetchDocument(url, options) {
|
|
|
52
98
|
}
|
|
53
99
|
return response.text();
|
|
54
100
|
}
|
|
55
|
-
function isCompatibleUnicodeReferenceError(error, document) {
|
|
56
|
-
const messageMatches = error.message === "Property $ref is not expected to be here" ||
|
|
57
|
-
error.message.includes("contains non-ASCII characters");
|
|
58
|
-
if (!messageMatches || typeof error.path !== "string")
|
|
59
|
-
return false;
|
|
60
|
-
const value = resolveJsonPointer(document, error.path);
|
|
61
|
-
const ref = typeof value === "string"
|
|
62
|
-
? value
|
|
63
|
-
: value && typeof value === "object"
|
|
64
|
-
? value.$ref
|
|
65
|
-
: undefined;
|
|
66
|
-
if (typeof ref !== "string" || !ref.startsWith("#/") || !/[^\x00-\x7F]/.test(ref)) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
return resolveJsonPointer(document, ref.slice(1)) !== undefined;
|
|
70
|
-
}
|
|
71
|
-
function resolveJsonPointer(root, pointer) {
|
|
72
|
-
if (pointer === "")
|
|
73
|
-
return root;
|
|
74
|
-
if (!pointer.startsWith("/"))
|
|
75
|
-
return undefined;
|
|
76
|
-
let current = root;
|
|
77
|
-
for (const rawPart of pointer.slice(1).split("/")) {
|
|
78
|
-
const part = decodeURIComponent(rawPart.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
79
|
-
if (!current || typeof current !== "object" || Array.isArray(current))
|
|
80
|
-
return undefined;
|
|
81
|
-
current = current[part];
|
|
82
|
-
}
|
|
83
|
-
return current;
|
|
84
|
-
}
|
|
85
101
|
function formatValidationErrors(errors) {
|
|
86
102
|
return errors
|
|
87
103
|
.slice(0, 20)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/openapi/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGlD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAQlC,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,OAAO,GAAuB,EAAE;IAEhC,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC;QAC/B,CAAC,CAAC,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC;QACtC,CAAC,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IAE5C,OAAO,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAA0B,EAC1B,MAAM,GAAG,QAAQ,EACjB,OAAO,GAA+C,EAAE;IAExD,MAAM,
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/openapi/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { JsonObject, OpenApiDiagnostic } from "../types.js";
|
|
2
|
+
export interface NormalizeResult {
|
|
3
|
+
document: JsonObject;
|
|
4
|
+
diagnostics: OpenApiDiagnostic[];
|
|
5
|
+
}
|
|
6
|
+
export declare function normalizeOpenApiDocument(input: JsonObject): NormalizeResult;
|
|
7
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/openapi/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAQjE,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,UAAU,CAAC;IACrB,WAAW,EAAE,iBAAiB,EAAE,CAAC;CAClC;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,UAAU,GAAG,eAAe,CAQ3E"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { HTTP_METHODS, asObject } from "./operations.js";
|
|
2
|
+
export function normalizeOpenApiDocument(input) {
|
|
3
|
+
const document = structuredClone(input);
|
|
4
|
+
const diagnostics = [];
|
|
5
|
+
const targets = collectReferenceTargets(document);
|
|
6
|
+
walkAndRepairReferences(document, "", document, targets, diagnostics);
|
|
7
|
+
normalizePaths(document, diagnostics);
|
|
8
|
+
reportDuplicateOperationIds(document, diagnostics);
|
|
9
|
+
return { document, diagnostics };
|
|
10
|
+
}
|
|
11
|
+
function normalizePaths(document, diagnostics) {
|
|
12
|
+
const paths = asObject(document.paths);
|
|
13
|
+
if (!paths)
|
|
14
|
+
return;
|
|
15
|
+
for (const [path, rawPathItem] of Object.entries(paths)) {
|
|
16
|
+
const location = `/paths/${encodePointerSegment(path)}`;
|
|
17
|
+
const pathItem = asObject(rawPathItem);
|
|
18
|
+
if (!pathItem) {
|
|
19
|
+
delete paths[path];
|
|
20
|
+
diagnostics.push({
|
|
21
|
+
severity: "skipped",
|
|
22
|
+
code: "path_skipped",
|
|
23
|
+
path: location,
|
|
24
|
+
message: "Skipped path because its path item is not an object",
|
|
25
|
+
original: rawPathItem,
|
|
26
|
+
});
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
for (const method of HTTP_METHODS) {
|
|
30
|
+
if (pathItem[method] === undefined)
|
|
31
|
+
continue;
|
|
32
|
+
const operation = asObject(pathItem[method]);
|
|
33
|
+
const operationPath = `${location}/${method}`;
|
|
34
|
+
if (!operation) {
|
|
35
|
+
const original = pathItem[method];
|
|
36
|
+
delete pathItem[method];
|
|
37
|
+
diagnostics.push({
|
|
38
|
+
severity: "skipped",
|
|
39
|
+
code: "operation_skipped",
|
|
40
|
+
path: operationPath,
|
|
41
|
+
message: "Skipped operation because it is not an object",
|
|
42
|
+
original,
|
|
43
|
+
});
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (operation.responses === undefined) {
|
|
47
|
+
operation.responses = {};
|
|
48
|
+
diagnostics.push({
|
|
49
|
+
severity: "repair",
|
|
50
|
+
code: "responses_added",
|
|
51
|
+
path: `${operationPath}/responses`,
|
|
52
|
+
message: "Added an empty responses object",
|
|
53
|
+
replacement: {},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function reportDuplicateOperationIds(document, diagnostics) {
|
|
60
|
+
const paths = asObject(document.paths);
|
|
61
|
+
if (!paths)
|
|
62
|
+
return;
|
|
63
|
+
const occurrences = new Map();
|
|
64
|
+
for (const [path, rawPathItem] of Object.entries(paths)) {
|
|
65
|
+
const pathItem = asObject(rawPathItem);
|
|
66
|
+
if (!pathItem)
|
|
67
|
+
continue;
|
|
68
|
+
for (const method of HTTP_METHODS) {
|
|
69
|
+
const operation = asObject(pathItem[method]);
|
|
70
|
+
const operationId = operation?.operationId;
|
|
71
|
+
if (typeof operationId !== "string" || operationId.length === 0)
|
|
72
|
+
continue;
|
|
73
|
+
const location = `/paths/${encodePointerSegment(path)}/${method}/operationId`;
|
|
74
|
+
const locations = occurrences.get(operationId) ?? [];
|
|
75
|
+
locations.push(location);
|
|
76
|
+
occurrences.set(operationId, locations);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
for (const [operationId, locations] of occurrences) {
|
|
80
|
+
if (locations.length < 2)
|
|
81
|
+
continue;
|
|
82
|
+
for (const path of locations) {
|
|
83
|
+
diagnostics.push({
|
|
84
|
+
severity: "warning",
|
|
85
|
+
code: "duplicate_operation_id",
|
|
86
|
+
path,
|
|
87
|
+
message: `Duplicate operationId: ${operationId}`,
|
|
88
|
+
original: operationId,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function collectReferenceTargets(document) {
|
|
94
|
+
const targets = [];
|
|
95
|
+
const components = asObject(document.components);
|
|
96
|
+
for (const collection of ["schemas", "parameters", "responses", "requestBodies"]) {
|
|
97
|
+
const entries = asObject(components?.[collection]);
|
|
98
|
+
if (!entries)
|
|
99
|
+
continue;
|
|
100
|
+
for (const name of Object.keys(entries)) {
|
|
101
|
+
targets.push({
|
|
102
|
+
name,
|
|
103
|
+
pointer: `#/components/${collection}/${encodePointerSegment(name)}`,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const definitions = asObject(document.definitions);
|
|
108
|
+
if (definitions) {
|
|
109
|
+
for (const name of Object.keys(definitions)) {
|
|
110
|
+
targets.push({ name, pointer: `#/definitions/${encodePointerSegment(name)}` });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return targets;
|
|
114
|
+
}
|
|
115
|
+
function walkAndRepairReferences(value, path, document, targets, diagnostics) {
|
|
116
|
+
if (Array.isArray(value)) {
|
|
117
|
+
value.forEach((item, index) => walkAndRepairReferences(item, `${path}/${index}`, document, targets, diagnostics));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const object = asObject(value);
|
|
121
|
+
if (!object)
|
|
122
|
+
return;
|
|
123
|
+
const ref = object.$ref;
|
|
124
|
+
if (typeof ref === "string") {
|
|
125
|
+
repairReference(object, ref, `${path}/$ref`, document, targets, diagnostics);
|
|
126
|
+
}
|
|
127
|
+
for (const [key, child] of Object.entries(object)) {
|
|
128
|
+
if (key === "$ref")
|
|
129
|
+
continue;
|
|
130
|
+
walkAndRepairReferences(child, `${path}/${encodePointerSegment(key)}`, document, targets, diagnostics);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function repairReference(owner, ref, path, document, targets, diagnostics) {
|
|
134
|
+
if (isExternalReference(ref) || resolveLocalReference(document, ref) !== undefined)
|
|
135
|
+
return;
|
|
136
|
+
const name = referenceName(ref);
|
|
137
|
+
const matches = targets.filter((target) => target.name === name);
|
|
138
|
+
if (matches.length === 1) {
|
|
139
|
+
const replacement = matches[0].pointer;
|
|
140
|
+
owner.$ref = replacement;
|
|
141
|
+
diagnostics.push({
|
|
142
|
+
severity: "repair",
|
|
143
|
+
code: "ref_repaired",
|
|
144
|
+
path,
|
|
145
|
+
message: `Repaired local reference to ${replacement}`,
|
|
146
|
+
original: ref,
|
|
147
|
+
replacement,
|
|
148
|
+
});
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
diagnostics.push({
|
|
152
|
+
severity: "warning",
|
|
153
|
+
code: matches.length > 1 ? "ref_ambiguous" : "ref_unresolved",
|
|
154
|
+
path,
|
|
155
|
+
message: matches.length > 1
|
|
156
|
+
? `Local reference matches ${matches.length} component targets`
|
|
157
|
+
: "Local reference target was not found",
|
|
158
|
+
original: ref,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
function referenceName(ref) {
|
|
162
|
+
const prefixes = [
|
|
163
|
+
"#/components/schemas/",
|
|
164
|
+
"#/components/parameters/",
|
|
165
|
+
"#/components/responses/",
|
|
166
|
+
"#/components/requestBodies/",
|
|
167
|
+
"#/definitions/",
|
|
168
|
+
];
|
|
169
|
+
const prefix = prefixes.find((candidate) => ref.startsWith(candidate));
|
|
170
|
+
return decodeOnce(prefix ? ref.slice(prefix.length) : ref)
|
|
171
|
+
.replace(/~1/g, "/")
|
|
172
|
+
.replace(/~0/g, "~");
|
|
173
|
+
}
|
|
174
|
+
function isExternalReference(ref) {
|
|
175
|
+
return (/^[a-z][a-z\d+.-]*:/i.test(ref) ||
|
|
176
|
+
/^(?:\.\.?\/|\/)/.test(ref) ||
|
|
177
|
+
ref.indexOf("#") > 0 ||
|
|
178
|
+
/\.(?:json|ya?ml)$/i.test(ref));
|
|
179
|
+
}
|
|
180
|
+
function resolveLocalReference(document, ref) {
|
|
181
|
+
if (!ref.startsWith("#/"))
|
|
182
|
+
return undefined;
|
|
183
|
+
let current = document;
|
|
184
|
+
for (const rawPart of ref.slice(2).split("/")) {
|
|
185
|
+
const part = decodeOnce(rawPart).replace(/~1/g, "/").replace(/~0/g, "~");
|
|
186
|
+
current = asObject(current)?.[part];
|
|
187
|
+
if (current === undefined)
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
return current;
|
|
191
|
+
}
|
|
192
|
+
function encodePointerSegment(value) {
|
|
193
|
+
return value.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
194
|
+
}
|
|
195
|
+
function decodeOnce(value) {
|
|
196
|
+
try {
|
|
197
|
+
return decodeURIComponent(value);
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return value;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/openapi/normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/openapi/operations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE1E,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAU7C,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAG,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/openapi/operations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE1E,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAU7C,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAG,cAAc,EAAE,CAuC9E;AAgBD,wBAAgB,aAAa,CAC3B,UAAU,EAAE,cAAc,EAAE,EAC5B,KAAK,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACrD,cAAc,GAAG,SAAS,CAc5B;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAI/D;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAE3D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAEtD"}
|
|
@@ -14,6 +14,7 @@ export function extractOperations(document) {
|
|
|
14
14
|
const paths = asObject(root.paths);
|
|
15
15
|
if (!paths)
|
|
16
16
|
return [];
|
|
17
|
+
const operationIdCounts = countOperationIds(paths);
|
|
17
18
|
const operations = [];
|
|
18
19
|
for (const [path, rawPathItem] of Object.entries(paths)) {
|
|
19
20
|
const pathItem = asObject(rawPathItem);
|
|
@@ -25,7 +26,9 @@ export function extractOperations(document) {
|
|
|
25
26
|
continue;
|
|
26
27
|
const operationId = asString(operation.operationId);
|
|
27
28
|
const entry = {
|
|
28
|
-
id: operationId
|
|
29
|
+
id: operationId && operationIdCounts.get(operationId) === 1
|
|
30
|
+
? operationId
|
|
31
|
+
: `${method.toUpperCase()} ${path}`,
|
|
29
32
|
method,
|
|
30
33
|
path,
|
|
31
34
|
tags: asStringArray(operation.tags),
|
|
@@ -45,6 +48,21 @@ export function extractOperations(document) {
|
|
|
45
48
|
}
|
|
46
49
|
return operations.sort((a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method));
|
|
47
50
|
}
|
|
51
|
+
function countOperationIds(paths) {
|
|
52
|
+
const counts = new Map();
|
|
53
|
+
for (const rawPathItem of Object.values(paths)) {
|
|
54
|
+
const pathItem = asObject(rawPathItem);
|
|
55
|
+
if (!pathItem)
|
|
56
|
+
continue;
|
|
57
|
+
for (const method of HTTP_METHODS) {
|
|
58
|
+
const operation = asObject(pathItem[method]);
|
|
59
|
+
const operationId = asString(operation?.operationId);
|
|
60
|
+
if (operationId)
|
|
61
|
+
counts.set(operationId, (counts.get(operationId) ?? 0) + 1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return counts;
|
|
65
|
+
}
|
|
48
66
|
export function findOperation(operations, input) {
|
|
49
67
|
if (input.id) {
|
|
50
68
|
const exact = operations.find((entry) => entry.id === input.id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/openapi/operations.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,YAAY,GAA0B;IACjD,KAAK;IACL,KAAK;IACL,MAAM;IACN,QAAQ;IACR,SAAS;IACT,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;CACR,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,QAA0B;IAC1D,MAAM,IAAI,GAAG,QAAiC,CAAC;IAC/C,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IAEtB,MAAM,UAAU,GAAqB,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;QACvC,IAAI,CAAC,QAAQ;YAAE,SAAS;QAExB,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;YAClC,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;YAC7C,IAAI,CAAC,SAAS;gBAAE,SAAS;YAEzB,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;YACpD,MAAM,KAAK,GAAmB;gBAC5B,EAAE,
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/openapi/operations.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -38,6 +38,17 @@ export interface OpenApiContext {
|
|
|
38
38
|
message: string;
|
|
39
39
|
count: number;
|
|
40
40
|
}>;
|
|
41
|
+
diagnostics: OpenApiDiagnostic[];
|
|
42
|
+
}
|
|
43
|
+
export type DiagnosticSeverity = "repair" | "warning" | "skipped";
|
|
44
|
+
export type DiagnosticCode = "ref_repaired" | "ref_unresolved" | "ref_ambiguous" | "path_skipped" | "operation_skipped" | "responses_added" | "duplicate_operation_id" | "validation_warning";
|
|
45
|
+
export interface OpenApiDiagnostic {
|
|
46
|
+
severity: DiagnosticSeverity;
|
|
47
|
+
code: DiagnosticCode;
|
|
48
|
+
path: string;
|
|
49
|
+
message: string;
|
|
50
|
+
original?: unknown;
|
|
51
|
+
replacement?: unknown;
|
|
41
52
|
}
|
|
42
53
|
export interface SchemaFormatOptions {
|
|
43
54
|
maxDepth?: number;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACjD,MAAM,MAAM,UAAU,GAClB,KAAK,GACL,KAAK,GACL,MAAM,GACN,QAAQ,GACR,SAAS,GACT,MAAM,GACN,OAAO,GACP,OAAO,GACP,OAAO,CAAC;AAEZ,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,UAAU,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,kBAAkB,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACjD,MAAM,MAAM,UAAU,GAClB,KAAK,GACL,KAAK,GACL,MAAM,GACN,QAAQ,GACR,SAAS,GACT,MAAM,GACN,OAAO,GACP,OAAO,GACP,OAAO,CAAC;AAEZ,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,UAAU,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,kBAAkB,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9D,WAAW,EAAE,iBAAiB,EAAE,CAAC;CAClC;AAED,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAElE,MAAM,MAAM,cAAc,GACtB,cAAc,GACd,gBAAgB,GAChB,eAAe,GACf,cAAc,GACd,mBAAmB,GACnB,iBAAiB,GACjB,wBAAwB,GACxB,oBAAoB,CAAC;AAEzB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openapi-docs-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "A vendor-neutral MCP server for searching and understanding OpenAPI documents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"exports": {
|
|
10
10
|
".": "./dist/index.js"
|
|
11
11
|
},
|
|
12
|
-
"files": [
|
|
13
|
-
"dist",
|
|
14
|
-
"README.md",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md",
|
|
15
15
|
"LICENSE"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|