apifox-workspace-mcp 1.0.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.
Files changed (125) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/LICENSE +22 -0
  3. package/README.md +380 -0
  4. package/config/apifox-mcp.json.example +5 -0
  5. package/dist/__tests__/logger.test.d.ts +2 -0
  6. package/dist/__tests__/logger.test.d.ts.map +1 -0
  7. package/dist/__tests__/logger.test.js +42 -0
  8. package/dist/__tests__/logger.test.js.map +1 -0
  9. package/dist/__tests__/types.test.d.ts +2 -0
  10. package/dist/__tests__/types.test.d.ts.map +1 -0
  11. package/dist/__tests__/types.test.js +30 -0
  12. package/dist/__tests__/types.test.js.map +1 -0
  13. package/dist/__tests__/url-parser.test.d.ts +2 -0
  14. package/dist/__tests__/url-parser.test.d.ts.map +1 -0
  15. package/dist/__tests__/url-parser.test.js +27 -0
  16. package/dist/__tests__/url-parser.test.js.map +1 -0
  17. package/dist/core/client/apifox.d.ts +62 -0
  18. package/dist/core/client/apifox.d.ts.map +1 -0
  19. package/dist/core/client/apifox.js +87 -0
  20. package/dist/core/client/apifox.js.map +1 -0
  21. package/dist/core/client/index.d.ts +6 -0
  22. package/dist/core/client/index.d.ts.map +1 -0
  23. package/dist/core/client/index.js +6 -0
  24. package/dist/core/client/index.js.map +1 -0
  25. package/dist/core/client/mcp-bridge.d.ts +55 -0
  26. package/dist/core/client/mcp-bridge.d.ts.map +1 -0
  27. package/dist/core/client/mcp-bridge.js +345 -0
  28. package/dist/core/client/mcp-bridge.js.map +1 -0
  29. package/dist/core/config/index.d.ts +5 -0
  30. package/dist/core/config/index.d.ts.map +1 -0
  31. package/dist/core/config/index.js +5 -0
  32. package/dist/core/config/index.js.map +1 -0
  33. package/dist/core/config/manager.d.ts +132 -0
  34. package/dist/core/config/manager.d.ts.map +1 -0
  35. package/dist/core/config/manager.js +298 -0
  36. package/dist/core/config/manager.js.map +1 -0
  37. package/dist/core/context-store.d.ts +46 -0
  38. package/dist/core/context-store.d.ts.map +1 -0
  39. package/dist/core/context-store.js +82 -0
  40. package/dist/core/context-store.js.map +1 -0
  41. package/dist/core/generator/artifact.d.ts +20 -0
  42. package/dist/core/generator/artifact.d.ts.map +1 -0
  43. package/dist/core/generator/artifact.js +127 -0
  44. package/dist/core/generator/artifact.js.map +1 -0
  45. package/dist/core/generator/index.d.ts +6 -0
  46. package/dist/core/generator/index.d.ts.map +1 -0
  47. package/dist/core/generator/index.js +5 -0
  48. package/dist/core/generator/index.js.map +1 -0
  49. package/dist/core/index.d.ts +11 -0
  50. package/dist/core/index.d.ts.map +1 -0
  51. package/dist/core/index.js +16 -0
  52. package/dist/core/index.js.map +1 -0
  53. package/dist/core/intent.d.ts +14 -0
  54. package/dist/core/intent.d.ts.map +1 -0
  55. package/dist/core/intent.js +80 -0
  56. package/dist/core/intent.js.map +1 -0
  57. package/dist/core/parser/index.d.ts +6 -0
  58. package/dist/core/parser/index.d.ts.map +1 -0
  59. package/dist/core/parser/index.js +5 -0
  60. package/dist/core/parser/index.js.map +1 -0
  61. package/dist/core/parser/url.d.ts +76 -0
  62. package/dist/core/parser/url.d.ts.map +1 -0
  63. package/dist/core/parser/url.js +232 -0
  64. package/dist/core/parser/url.js.map +1 -0
  65. package/dist/lib/env.d.ts +17 -0
  66. package/dist/lib/env.d.ts.map +1 -0
  67. package/dist/lib/env.js +98 -0
  68. package/dist/lib/env.js.map +1 -0
  69. package/dist/lib/errors.d.ts +39 -0
  70. package/dist/lib/errors.d.ts.map +1 -0
  71. package/dist/lib/errors.js +59 -0
  72. package/dist/lib/errors.js.map +1 -0
  73. package/dist/lib/index.d.ts +9 -0
  74. package/dist/lib/index.d.ts.map +1 -0
  75. package/dist/lib/index.js +12 -0
  76. package/dist/lib/index.js.map +1 -0
  77. package/dist/lib/logger.d.ts +27 -0
  78. package/dist/lib/logger.d.ts.map +1 -0
  79. package/dist/lib/logger.js +79 -0
  80. package/dist/lib/logger.js.map +1 -0
  81. package/dist/lib/project-root.d.ts +8 -0
  82. package/dist/lib/project-root.d.ts.map +1 -0
  83. package/dist/lib/project-root.js +46 -0
  84. package/dist/lib/project-root.js.map +1 -0
  85. package/dist/server/handlers/assistant.d.ts +20 -0
  86. package/dist/server/handlers/assistant.d.ts.map +1 -0
  87. package/dist/server/handlers/assistant.js +71 -0
  88. package/dist/server/handlers/assistant.js.map +1 -0
  89. package/dist/server/handlers/generate-artifacts.d.ts +31 -0
  90. package/dist/server/handlers/generate-artifacts.d.ts.map +1 -0
  91. package/dist/server/handlers/generate-artifacts.js +75 -0
  92. package/dist/server/handlers/generate-artifacts.js.map +1 -0
  93. package/dist/server/handlers/get-interface-detail.d.ts +28 -0
  94. package/dist/server/handlers/get-interface-detail.d.ts.map +1 -0
  95. package/dist/server/handlers/get-interface-detail.js +59 -0
  96. package/dist/server/handlers/get-interface-detail.js.map +1 -0
  97. package/dist/server/handlers/index.d.ts +11 -0
  98. package/dist/server/handlers/index.d.ts.map +1 -0
  99. package/dist/server/handlers/index.js +13 -0
  100. package/dist/server/handlers/index.js.map +1 -0
  101. package/dist/server/handlers/list-projects.d.ts +12 -0
  102. package/dist/server/handlers/list-projects.d.ts.map +1 -0
  103. package/dist/server/handlers/list-projects.js +37 -0
  104. package/dist/server/handlers/list-projects.js.map +1 -0
  105. package/dist/server/handlers/parse-and-add-project.d.ts +28 -0
  106. package/dist/server/handlers/parse-and-add-project.d.ts.map +1 -0
  107. package/dist/server/handlers/parse-and-add-project.js +224 -0
  108. package/dist/server/handlers/parse-and-add-project.js.map +1 -0
  109. package/dist/server/handlers/query-interfaces.d.ts +30 -0
  110. package/dist/server/handlers/query-interfaces.d.ts.map +1 -0
  111. package/dist/server/handlers/query-interfaces.js +67 -0
  112. package/dist/server/handlers/query-interfaces.js.map +1 -0
  113. package/dist/server/handlers/utils.d.ts +51 -0
  114. package/dist/server/handlers/utils.d.ts.map +1 -0
  115. package/dist/server/handlers/utils.js +79 -0
  116. package/dist/server/handlers/utils.js.map +1 -0
  117. package/dist/server/index.d.ts +3 -0
  118. package/dist/server/index.d.ts.map +1 -0
  119. package/dist/server/index.js +248 -0
  120. package/dist/server/index.js.map +1 -0
  121. package/dist/types/index.d.ts +119 -0
  122. package/dist/types/index.d.ts.map +1 -0
  123. package/dist/types/index.js +19 -0
  124. package/dist/types/index.js.map +1 -0
  125. package/package.json +78 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,65 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2024-12-04
9
+
10
+ ### 🎉 Initial Release
11
+
12
+ #### ✨ Features
13
+ - **Project Management**: Multi-project workspace support
14
+ - **Interface Query**: Search and filter API interfaces
15
+ - **Code Generation**: Generate TypeScript types, Mock data, request wrappers, and test scripts
16
+ - **Natural Language Assistant**: AI-powered interface interaction
17
+ - **Smart Context**: Automatic context memory (last project, interface list)
18
+ - **URL Parser**: Intelligent parsing of Apifox share links
19
+
20
+ #### 🏗️ Architecture
21
+ - **Layered Design**: Server, Core, Lib, Types layers
22
+ - **Modular Structure**: 27 modules for high cohesion and low coupling
23
+ - **Type Safety**: 100% TypeScript, zero `any` types
24
+ - **Test Coverage**: 11 unit tests with 100% pass rate
25
+
26
+ #### 🛠️ Developer Experience
27
+ - ESLint + Prettier code standards
28
+ - Vitest testing framework
29
+ - Comprehensive documentation
30
+ - NPM scripts for common tasks
31
+
32
+ #### 📦 Infrastructure
33
+ - Unified logging system with log levels
34
+ - Custom error classes for better error handling
35
+ - Environment variable loading from MCP config
36
+ - Automatic project root detection
37
+
38
+ ### 🔧 Configuration
39
+ - MCP configuration via `~/.cursor/mcp.json` or `.cursor/mcp.json`
40
+ - Support for custom API base URL
41
+ - Automatic `apifox-mcp.json` initialization
42
+
43
+ ### 📚 Documentation
44
+ - [Architecture Guide](docs/architecture.md)
45
+ - [Setup Guide](docs/setup.md)
46
+ - [Usage Guide](docs/usage.md)
47
+ - [Refactoring Report](docs/refactoring-report.md)
48
+
49
+ ---
50
+
51
+ ## Release Notes
52
+
53
+ ### Breaking Changes
54
+ None (initial release)
55
+
56
+ ### Upgrade Guide
57
+ This is the first release. No upgrade needed.
58
+
59
+ ### Known Issues
60
+ None
61
+
62
+ ---
63
+
64
+ For more details, see the [README](README.md).
65
+
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Apifox Team
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.
22
+
package/README.md ADDED
@@ -0,0 +1,380 @@
1
+ # Apifox Workspace MCP
2
+
3
+ [![npm version](https://img.shields.io/npm/v/apifox-workspace-mcp)](https://www.npmjs.com/package/apifox-workspace-mcp)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Node Version](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org)
6
+
7
+ > 🚀 工作空间级别的 Apifox MCP Server,为 Cursor AI 提供智能 API 文档集成能力
8
+
9
+ ## ✨ 核心特性
10
+
11
+ ### 🗂️ 多项目管理
12
+ - 📋 统一管理工作空间中的所有 Apifox 项目
13
+ - 🔗 一键解析分享链接,自动添加项目配置
14
+ - 💾 智能维护项目配置文件(`apifox-mcp.json`)
15
+
16
+ ### 🔍 智能接口查询
17
+ - 🔎 关键词搜索,快速定位目标接口
18
+ - 🏷️ 标签筛选,按模块分类查看
19
+ - 📄 完整接口详情(请求参数、响应结构、示例代码)
20
+
21
+ ### 🛠️ 代码自动生成
22
+ - 📝 **TypeScript 类型定义** - 自动生成请求/响应类型
23
+ - 🎭 **Mock 数据** - 基于接口规范生成测试数据
24
+ - 🔌 **请求封装** - 生成类型安全的 API 调用函数
25
+ - 🧪 **测试脚本** - 生成单元测试模板
26
+
27
+ ### 🤖 自然语言助手
28
+ - 💬 自然语言交互,无需记忆命令
29
+ - 🧠 智能上下文记忆(项目、接口列表)
30
+ - 🎯 意图识别,自动路由到正确的功能
31
+
32
+ ## 📦 安装
33
+
34
+ ### 方式 1:通过 npx(推荐)
35
+
36
+ 最简单的使用方式,无需安装:
37
+
38
+ ```json
39
+ {
40
+ "mcpServers": {
41
+ "apifox-workspace-mcp": {
42
+ "command": "npx",
43
+ "args": ["-y", "apifox-workspace-mcp"],
44
+ "env": {
45
+ "APIFOX_ACCESS_TOKEN": "your_apifox_access_token",
46
+ "APIFOX_API_BASE_URL": "https://api.apifox.com"
47
+ }
48
+ }
49
+ }
50
+ }
51
+ ```
52
+
53
+ ### 方式 2:全局安装
54
+
55
+ ```bash
56
+ npm install -g apifox-workspace-mcp
57
+ ```
58
+
59
+ 配置示例:
60
+
61
+ ```json
62
+ {
63
+ "mcpServers": {
64
+ "apifox-workspace-mcp": {
65
+ "command": "apifox-workspace-mcp",
66
+ "env": {
67
+ "APIFOX_ACCESS_TOKEN": "your_apifox_access_token",
68
+ "APIFOX_API_BASE_URL": "https://api.apifox.com"
69
+ }
70
+ }
71
+ }
72
+ }
73
+ ```
74
+
75
+ ### 方式 3:从源码运行
76
+
77
+ ```bash
78
+ git clone https://github.com/apifox/apifox-workspace-mcp.git
79
+ cd apifox-workspace-mcp
80
+ npm install
81
+ npm run build
82
+ ```
83
+
84
+ 配置示例:
85
+
86
+ ```json
87
+ {
88
+ "mcpServers": {
89
+ "apifox-workspace-mcp": {
90
+ "command": "node",
91
+ "args": ["/path/to/apifox-workspace-mcp/dist/server/index.js"],
92
+ "env": {
93
+ "APIFOX_ACCESS_TOKEN": "your_apifox_access_token",
94
+ "APIFOX_API_BASE_URL": "https://api.apifox.com"
95
+ }
96
+ }
97
+ }
98
+ }
99
+ ```
100
+
101
+ ## ⚙️ 配置说明
102
+
103
+ ### 必需配置
104
+
105
+ - **`APIFOX_ACCESS_TOKEN`**(必需)
106
+ - 你的 Apifox Access Token
107
+ - 获取方式:Apifox → 个人设置 → Access Tokens
108
+
109
+ ### 可选配置
110
+
111
+ - **`APIFOX_API_BASE_URL`**(可选)
112
+ - 自定义 API 基础地址
113
+ - 默认:`https://api.apifox.com`
114
+ - 私有部署时需要配置
115
+
116
+ - **`LOG_LEVEL`**(可选)
117
+ - 日志级别:`debug` | `info` | `warn` | `error`
118
+ - 默认:`info`
119
+
120
+ ### 💡 工作原理
121
+
122
+ 使用 `npx apifox-workspace-mcp` 时的执行流程:
123
+
124
+ 1. ✅ npx 从 **npm 仓库**下载包(包含编译后的 `dist/` 目录)
125
+ 2. ✅ 执行 `dist/server/index.js`(无需构建)
126
+ 3. ✅ MCP Server 启动并连接到 Cursor
127
+
128
+ **无需操心**:
129
+ - ❌ 克隆 Git 仓库
130
+ - ❌ 安装 TypeScript 或构建工具
131
+ - ❌ 运行 `npm run build`
132
+
133
+ > 📝 **说明**:`dist/` 目录不在 Git 仓库中(开发者不提交编译产物),但会自动包含在 npm 包中(用户下载即用)。详见 [分发机制说明](docs/distribution.md)
134
+
135
+ 详细配置指南:[📘 docs/setup.md](docs/setup.md)
136
+
137
+ ## 🚀 快速开始
138
+
139
+ ### 1️⃣ 添加项目
140
+
141
+ ```
142
+ @apifox 添加项目:https://apifox.advai.net/apidoc/shared/xxx
143
+ ```
144
+
145
+ ### 2️⃣ 查询接口
146
+
147
+ ```
148
+ @apifox 列出所有项目
149
+ @apifox 搜索支付接口
150
+ @apifox 查询 mboss-backend 项目的退款接口
151
+ ```
152
+
153
+ ### 3️⃣ 查看详情
154
+
155
+ ```
156
+ @apifox 告诉我退款接口的详情
157
+ @apifox 显示接口 api-12345 的完整信息
158
+ ```
159
+
160
+ ### 4️⃣ 生成代码
161
+
162
+ ```typescript
163
+ // 生成 TypeScript 类型
164
+ @apifox 帮我生成退款接口的 TypeScript 类型
165
+
166
+ // 生成 Mock 数据
167
+ @apifox 生成 Mock 数据
168
+
169
+ // 生成请求封装
170
+ @apifox 生成请求封装函数
171
+
172
+ // 保存到文件
173
+ @apifox 生成类型并保存到 src/api/types.ts
174
+ ```
175
+
176
+ 更多示例:[📗 docs/usage.md](docs/usage.md)
177
+
178
+ ## 🏗️ 项目架构
179
+
180
+ 采用**清晰的分层架构**,遵循 MCP Server 最佳实践:
181
+
182
+ ```
183
+ src/
184
+ ├── server/ 🟦 MCP Server 层(协议交互)
185
+ │ ├── index.ts ↳ Server 主入口(309 行,精简 68%)
186
+ │ └── handlers/ ↳ 7 个工具处理器
187
+
188
+ ├── core/ 🟩 核心业务逻辑层(与 MCP 无关)
189
+ │ ├── config/ ↳ 配置管理
190
+ │ ├── client/ ↳ API 客户端(REST + MCP)
191
+ │ ├── parser/ ↳ URL 解析器
192
+ │ ├── generator/ ↳ 代码生成器
193
+ │ └── ... ↳ 上下文、意图识别
194
+
195
+ ├── lib/ 🟨 基础设施层(通用工具)
196
+ │ ├── logger.ts ↳ 日志系统
197
+ │ ├── errors.ts ↳ 错误类
198
+ │ └── ... ↳ 环境变量、工具函数
199
+
200
+ └── types/ 🟪 类型定义层
201
+ └── index.ts ↳ 所有共享类型
202
+ ```
203
+
204
+ ### 架构优势
205
+
206
+ - ✅ **模块化**:27 个模块文件,职责清晰,易于维护
207
+ - ✅ **类型安全**:100% TypeScript,零 `any` 类型
208
+ - ✅ **可测试**:完整的单元测试覆盖(11 个测试)
209
+ - ✅ **低耦合**:清晰的依赖方向,避免循环依赖
210
+
211
+ 详细架构:[📙 docs/architecture.md](docs/architecture.md)
212
+
213
+ ## 📚 可用工具
214
+
215
+ | 工具 | 描述 | 使用场景 |
216
+ |------|------|----------|
217
+ | `list_projects` | 列出所有集成的项目 | 查看已配置的项目列表 |
218
+ | `parse_and_add_project` | 解析分享链接并添加项目 | 快速集成新项目 |
219
+ | `query_interfaces` | 查询项目接口列表 | 搜索、浏览接口 |
220
+ | `get_interface_detail` | 获取接口详细信息 | 查看完整接口文档 |
221
+ | `generate_artifacts` | 生成代码产物 | 自动生成类型、Mock、测试 |
222
+ | `apifox_assistant` | 自然语言助手 | 对话式操作,更友好 |
223
+
224
+ ## 🧪 开发指南
225
+
226
+ ### 本地开发
227
+
228
+ ```bash
229
+ # 克隆仓库
230
+ git clone https://github.com/apifox/apifox-workspace-mcp.git
231
+ cd apifox-workspace-mcp
232
+
233
+ # 安装依赖
234
+ npm install
235
+
236
+ # 开发模式(监听文件变化)
237
+ npm run dev
238
+
239
+ # 构建项目
240
+ npm run build
241
+
242
+ # 运行测试
243
+ npm run test
244
+
245
+ # 代码检查
246
+ npm run lint
247
+
248
+ # 格式化代码
249
+ npm run format
250
+
251
+ # 类型检查
252
+ npm run typecheck
253
+ ```
254
+
255
+ ### 添加新功能
256
+
257
+ 1. **添加新的 MCP 工具**
258
+ - 在 `src/server/handlers/` 创建 handler
259
+ - 在 `src/server/handlers/index.ts` 导出
260
+ - 在 `src/server/index.ts` 注册工具
261
+
262
+ 2. **添加核心功能**
263
+ - 在 `src/core/` 相应子模块中添加
264
+ - 在子模块 `index.ts` 中导出
265
+
266
+ 3. **添加工具函数**
267
+ - 在 `src/lib/` 中添加
268
+ - 在 `src/lib/index.ts` 中导出
269
+
270
+ ### 测试覆盖
271
+
272
+ ```bash
273
+ # 运行测试
274
+ npm run test
275
+
276
+ # 监听模式
277
+ npm run test:watch
278
+
279
+ # 生成覆盖率报告
280
+ npm run test -- --coverage
281
+ ```
282
+
283
+ **当前测试状态**:
284
+ - ✅ 11/11 测试通过
285
+ - ✅ 3 个测试文件
286
+ - ✅ 覆盖 logger、types、url-parser 模块
287
+
288
+ ## 📊 项目指标
289
+
290
+ | 指标 | 数值 |
291
+ |------|------|
292
+ | **TypeScript 文件** | 30 个 |
293
+ | **主入口行数** | 309 行(精简 68%)|
294
+ | **模块数量** | 27 个 |
295
+ | **单元测试** | 11 个(100% 通过)|
296
+ | **类型安全** | 零 `any` 类型 |
297
+ | **代码规范** | ESLint + Prettier |
298
+
299
+ ## 🛠️ 技术栈
300
+
301
+ - **运行时**: Node.js >= 20
302
+ - **语言**: TypeScript 5.3+
303
+ - **协议**: Model Context Protocol (MCP) 0.5.0
304
+ - **HTTP 客户端**: Axios 1.7+
305
+ - **测试框架**: Vitest 2.1+
306
+ - **代码规范**: ESLint 9+ + Prettier 3+
307
+ - **UI 增强**: Playwright 1.57+
308
+
309
+ ## 📖 完整文档
310
+
311
+ - 📘 [配置指南](docs/setup.md) - 详细的安装和配置步骤
312
+ - 📗 [使用指南](docs/usage.md) - 各种使用场景和示例
313
+ - 📙 [架构设计](docs/architecture.md) - 项目架构和设计原则
314
+ - 📕 [发布指南](docs/publishing.md) - npm 发布流程
315
+ - 🧪 [测试文档](tests/README.md) - 测试说明和测试用例
316
+
317
+ ## 🤝 贡献指南
318
+
319
+ 欢迎提交 Issue 和 Pull Request!
320
+
321
+ ### 开发流程
322
+
323
+ 1. Fork 本仓库
324
+ 2. 创建特性分支:`git checkout -b feature/amazing-feature`
325
+ 3. 提交更改:`git commit -m 'feat: add amazing feature'`
326
+ 4. 推送分支:`git push origin feature/amazing-feature`
327
+ 5. 提交 Pull Request
328
+
329
+ ### 提交规范
330
+
331
+ 遵循 [Conventional Commits](https://www.conventionalcommits.org/):
332
+
333
+ - `feat:` - 新功能
334
+ - `fix:` - 修复 Bug
335
+ - `docs:` - 文档更新
336
+ - `style:` - 代码格式化
337
+ - `refactor:` - 重构
338
+ - `test:` - 测试相关
339
+ - `chore:` - 构建/工具相关
340
+
341
+ ### 代码规范
342
+
343
+ - ✅ 遵循 ESLint 规则
344
+ - ✅ 使用 Prettier 格式化
345
+ - ✅ 为新功能添加测试
346
+ - ✅ 更新相关文档
347
+ - ✅ 保持类型安全(避免 `any`)
348
+
349
+ ## 🐛 问题反馈
350
+
351
+ 遇到问题?请查看:
352
+
353
+ 1. [常见问题](docs/setup.md#常见问题)
354
+ 2. [Issues](https://github.com/apifox/apifox-workspace-mcp/issues)
355
+ 3. [测试文档](tests/README.md)
356
+
357
+ ## 📄 许可证
358
+
359
+ [MIT License](LICENSE) - 自由使用、修改和分发
360
+
361
+ ## 🔗 相关资源
362
+
363
+ - [Apifox 官网](https://apifox.com) - API 设计、开发、测试一体化平台
364
+ - [MCP Protocol](https://modelcontextprotocol.io) - Model Context Protocol 官方文档
365
+ - [Cursor AI](https://cursor.sh) - 智能 AI 代码编辑器
366
+ - [GitHub Repository](https://github.com/apifox/apifox-workspace-mcp) - 项目源码
367
+
368
+ ## 🌟 Star History
369
+
370
+ 如果这个项目对你有帮助,请给我们一个 ⭐️ Star!
371
+
372
+ ---
373
+
374
+ <div align="center">
375
+
376
+ **Made with ❤️ by Apifox Team**
377
+
378
+ [报告问题](https://github.com/apifox/apifox-workspace-mcp/issues) · [功能建议](https://github.com/apifox/apifox-workspace-mcp/issues) · [贡献代码](https://github.com/apifox/apifox-workspace-mcp/pulls)
379
+
380
+ </div>
@@ -0,0 +1,5 @@
1
+ {
2
+ "project-name": "project-id",
3
+ "payment-boss": "c2b11a34-d661-4a29-bbbe-04697b4f5de7"
4
+ }
5
+
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=logger.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/logger.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,42 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { logger } from '../lib/index.js';
3
+ describe('logger', () => {
4
+ let consoleErrorSpy;
5
+ beforeEach(() => {
6
+ consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
7
+ });
8
+ afterEach(() => {
9
+ consoleErrorSpy.mockRestore();
10
+ delete process.env.LOG_LEVEL;
11
+ });
12
+ describe('info', () => {
13
+ it('应该在默认级别下输出 info 日志', () => {
14
+ logger.info('测试信息');
15
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('测试信息'));
16
+ });
17
+ });
18
+ describe('warn', () => {
19
+ it('应该输出警告日志', () => {
20
+ logger.warn('警告信息');
21
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('警告信息'));
22
+ });
23
+ });
24
+ describe('error', () => {
25
+ it('应该输出错误日志', () => {
26
+ logger.error('错误信息');
27
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('错误信息'));
28
+ });
29
+ });
30
+ describe('debug', () => {
31
+ it('应该在 LOG_LEVEL=debug 时输出调试日志', () => {
32
+ process.env.LOG_LEVEL = 'debug';
33
+ logger.debug('调试信息');
34
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('调试信息'));
35
+ });
36
+ it('应该在默认级别下不输出调试日志', () => {
37
+ logger.debug('调试信息');
38
+ expect(consoleErrorSpy).not.toHaveBeenCalled();
39
+ });
40
+ });
41
+ });
42
+ //# sourceMappingURL=logger.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.test.js","sourceRoot":"","sources":["../../src/__tests__/logger.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,IAAI,eAA4C,CAAC;IAEjD,UAAU,CAAC,GAAG,EAAE;QACd,eAAe,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,eAAe,CAAC,WAAW,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;QACpB,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;YAC5B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACpB,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;QACpB,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;YAClB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACpB,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;QACrB,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;YAClB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;QACrB,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,OAAO,CAAC,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE;YACzB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACjD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { createTextResponse, createErrorResponse } from '../types/index.js';
3
+ describe('types', () => {
4
+ describe('createTextResponse', () => {
5
+ it('应该创建正常文本响应', () => {
6
+ const response = createTextResponse('测试消息');
7
+ expect(response).toEqual({
8
+ content: [{ type: 'text', text: '测试消息' }],
9
+ isError: false,
10
+ });
11
+ });
12
+ it('应该创建带错误标志的响应', () => {
13
+ const response = createTextResponse('错误消息', true);
14
+ expect(response).toEqual({
15
+ content: [{ type: 'text', text: '错误消息' }],
16
+ isError: true,
17
+ });
18
+ });
19
+ });
20
+ describe('createErrorResponse', () => {
21
+ it('应该创建错误响应', () => {
22
+ const response = createErrorResponse('发生错误');
23
+ expect(response).toEqual({
24
+ content: [{ type: 'text', text: '发生错误' }],
25
+ isError: true,
26
+ });
27
+ });
28
+ });
29
+ });
30
+ //# sourceMappingURL=types.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE5E,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;IACrB,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YACpB,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAC5C,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;gBACvB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;gBACzC,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE;YACtB,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAClD,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;gBACvB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;gBACzC,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;QACnC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;YAClB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;YAC7C,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;gBACvB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;gBACzC,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=url-parser.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-parser.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/url-parser.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { isValidApifoxUrl, ShareLinkType } from '../core/index.js';
3
+ describe('url-parser', () => {
4
+ describe('isValidApifoxUrl', () => {
5
+ it('应该识别有效的 Apifox 分享链接', () => {
6
+ expect(isValidApifoxUrl('https://apifox.com/apidoc/shared/abc123')).toBe(true);
7
+ expect(isValidApifoxUrl('https://example.apifox.com/apidoc/shared/abc123')).toBe(true);
8
+ expect(isValidApifoxUrl('https://custom.example.com/apidoc/shared/xyz789')).toBe(true);
9
+ });
10
+ it('应该拒绝无效的 URL', () => {
11
+ expect(isValidApifoxUrl('https://google.com')).toBe(false);
12
+ expect(isValidApifoxUrl('not-a-url')).toBe(false);
13
+ expect(isValidApifoxUrl('')).toBe(false);
14
+ // 非 /apidoc/shared/ 格式的链接
15
+ expect(isValidApifoxUrl('https://app.apifox.com/project/123')).toBe(false);
16
+ });
17
+ });
18
+ describe('ShareLinkType', () => {
19
+ it('应该正确定义枚举值', () => {
20
+ expect(ShareLinkType.PROJECT).toBe('project');
21
+ expect(ShareLinkType.INTERFACE).toBe('interface');
22
+ });
23
+ });
24
+ // 注意: parseApifoxUrl 是异步函数,需要网络请求,
25
+ // 完整的集成测试应该使用 mock 或在集成测试中进行
26
+ });
27
+ //# sourceMappingURL=url-parser.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-parser.test.js","sourceRoot":"","sources":["../../src/__tests__/url-parser.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEnE,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,MAAM,CAAC,gBAAgB,CAAC,yCAAyC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/E,MAAM,CAAC,gBAAgB,CAAC,iDAAiD,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvF,MAAM,CAAC,gBAAgB,CAAC,iDAAiD,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,aAAa,EAAE,GAAG,EAAE;YACrB,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3D,MAAM,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClD,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzC,0BAA0B;YAC1B,MAAM,CAAC,gBAAgB,CAAC,oCAAoC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;YACnB,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9C,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,mCAAmC;IACnC,6BAA6B;AAC/B,CAAC,CAAC,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { ApiRequestSpec, ApiResponseSpec } from '../../types/index.js';
2
+ /**
3
+ * Apifox API 客户端
4
+ * 封装 Apifox REST API 调用
5
+ */
6
+ export declare class ApifoxClient {
7
+ private client;
8
+ private accessToken;
9
+ constructor(accessToken: string, baseUrl?: string);
10
+ /**
11
+ * 获取项目信息
12
+ * @param projectId 项目 ID
13
+ * @returns 项目信息
14
+ */
15
+ getProjectInfo(projectId: string): Promise<{
16
+ id: string;
17
+ name: string;
18
+ description?: string;
19
+ }>;
20
+ /**
21
+ * 获取项目接口列表
22
+ * @param projectId 项目 ID
23
+ * @param keyword 搜索关键词(可选)
24
+ * @returns 接口列表
25
+ */
26
+ getInterfaces(projectId: string, keyword?: string): Promise<Array<{
27
+ id: string;
28
+ name: string;
29
+ method: string;
30
+ path: string;
31
+ description?: string;
32
+ }>>;
33
+ /**
34
+ * 获取接口详情
35
+ * @param projectId 项目 ID
36
+ * @param interfaceId 接口 ID
37
+ * @returns 接口详情
38
+ */
39
+ getInterfaceDetail(projectId: string, interfaceId: string): Promise<{
40
+ id: string;
41
+ name: string;
42
+ method: string;
43
+ path: string;
44
+ description?: string;
45
+ request?: ApiRequestSpec;
46
+ response?: ApiResponseSpec;
47
+ }>;
48
+ /**
49
+ * 搜索接口(根据关键词)
50
+ * @param projectId 项目 ID
51
+ * @param keyword 搜索关键词
52
+ * @returns 匹配的接口列表
53
+ */
54
+ searchInterfaces(projectId: string, keyword: string): Promise<Array<{
55
+ id: string;
56
+ name: string;
57
+ method: string;
58
+ path: string;
59
+ description?: string;
60
+ }>>;
61
+ }
62
+ //# sourceMappingURL=apifox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apifox.d.ts","sourceRoot":"","sources":["../../../src/core/client/apifox.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvE;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,WAAW,CAAS;gBAEhB,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,MAAiC;IAY3E;;;;OAIG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAC/C,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IAYF;;;;;OAKG;IACG,aAAa,CACjB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CACR,KAAK,CAAC;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CACH;IAiBD;;;;;OAKG;IACG,kBAAkB,CACtB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;QACT,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,cAAc,CAAC;QACzB,QAAQ,CAAC,EAAE,eAAe,CAAC;KAC5B,CAAC;IAYF;;;;;OAKG;IACG,gBAAgB,CACpB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CACR,KAAK,CAAC;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CACH;CAGF"}