@liangshanli/mcp-server-project-standards 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,43 @@
2
2
 
3
3
  A MCP (Model Context Protocol) server for project standards management, designed for AI-assisted development to help teams maintain unified development standards and specifications across multiple machines.
4
4
 
5
+ ## 📋 Version Updates
6
+
7
+ ### v1.1.0 (2024-12-19)
8
+
9
+ #### 🆕 New Features
10
+ - **API Debug Tool Environment Variable Support**:
11
+ - `API_DEBUG_ALLOWED_METHODS` - Control allowed request methods (default: GET)
12
+ - `API_DEBUG_LOGIN_URL` - Set login API URL (default: /api/login)
13
+ - `API_DEBUG_LOGIN_METHOD` - Set login request method (default: POST)
14
+ - `API_DEBUG_LOGIN_BODY` - Set login request body (default: {"username":"","password":""})
15
+ - `API_DEBUG_LOGIN_DESCRIPTION` - Set login API description (default: Save returned token to common headers in debug tool, field name Authorization, field value Bearer token)
16
+
17
+ #### 🔧 Feature Improvements
18
+ - **Smart Login API Recognition**:
19
+ - Support for full URL and relative path matching
20
+ - Automatic login API recognition using environment variable configuration
21
+ - Non-login APIs strictly follow allowed method restrictions
22
+
23
+ - **Error Handling Optimization**:
24
+ - Only request-related errors are saved to api.json
25
+ - Method validation errors don't pollute execution records
26
+ - More precise error classification and handling
27
+
28
+ - **Dynamic Tool Description**:
29
+ - Display login authentication information based on environment variable configuration
30
+ - Real-time display of allowed request methods and usage instructions
31
+
32
+ #### 🛡️ Security Enhancements
33
+ - **Request Method Restrictions**: Default only allows GET requests to prevent accidental operations
34
+ - **Login API Exception**: Login APIs can use methods configured in environment variables
35
+ - **Flexible Configuration**: Can open more request methods as needed
36
+
37
+ #### 📚 Documentation Updates
38
+ - Added environment variable configuration instructions
39
+ - Updated API debug tool usage guide
40
+ - Improved login authentication flow documentation
41
+
5
42
  ## 🚀 Core Advantages
6
43
 
7
44
  ### 🎯 Solving Multi-Machine Development Chaos
@@ -73,9 +110,14 @@ The server uses the `./.setting/` directory to store configuration files by defa
73
110
 
74
111
  ### Environment Variables
75
112
 
76
- | Variable | Default | Description |
77
- |----------|---------|-------------|
78
- | CONFIG_DIR | ./.setting | Configuration file directory (contains config.json and api.json) |
113
+ | Variable | Default | Description | Example |
114
+ |----------|---------|-------------|---------|
115
+ | CONFIG_DIR | ./.setting | Configuration file directory (contains config.json and api.json) | `export CONFIG_DIR="./config"` |
116
+ | API_DEBUG_ALLOWED_METHODS | GET | Control allowed request methods (supports: GET,POST,PUT,DELETE,PATCH, etc.) | `export API_DEBUG_ALLOWED_METHODS="GET,POST"` |
117
+ | API_DEBUG_LOGIN_URL | /api/login | Set login API URL | `export API_DEBUG_LOGIN_URL="/api/auth/login"` |
118
+ | API_DEBUG_LOGIN_METHOD | POST | Set login request method | `export API_DEBUG_LOGIN_METHOD="POST"` |
119
+ | API_DEBUG_LOGIN_BODY | {"username":"","password":""} | Set login request body | `export API_DEBUG_LOGIN_BODY='{"mobile":"","password":""}'` |
120
+ | API_DEBUG_LOGIN_DESCRIPTION | Save returned token to common headers in debug tool, field name Authorization, field value Bearer token | Set login API description | `export API_DEBUG_LOGIN_DESCRIPTION="User Login API"` |
79
121
 
80
122
  ### Configuration Files
81
123
 
@@ -166,7 +208,12 @@ npm run dev
166
208
  "command": "npx",
167
209
  "args": ["@liangshanli/mcp-server-project-standards"],
168
210
  "env": {
169
- "CONFIG_DIR": "./.setting"
211
+ "CONFIG_DIR": "./.setting",
212
+ "API_DEBUG_ALLOWED_METHODS": "GET,POST,PUT,DELETE",
213
+ "API_DEBUG_LOGIN_URL": "/api/login",
214
+ "API_DEBUG_LOGIN_METHOD": "POST",
215
+ "API_DEBUG_LOGIN_BODY": "{\"username\":\"\",\"password\":\"\"}",
216
+ "API_DEBUG_LOGIN_DESCRIPTION": "Save returned token to common headers in debug tool, field name Authorization, field value Bearer token"
170
217
  }
171
218
  }
172
219
  }
@@ -185,7 +232,12 @@ npm run dev
185
232
  "command": "npx",
186
233
  "args": ["@liangshanli/mcp-server-project-standards"],
187
234
  "env": {
188
- "CONFIG_DIR": "./.setting"
235
+ "CONFIG_DIR": "./.setting",
236
+ "API_DEBUG_ALLOWED_METHODS": "GET,POST,PUT,DELETE",
237
+ "API_DEBUG_LOGIN_URL": "/api/login",
238
+ "API_DEBUG_LOGIN_METHOD": "POST",
239
+ "API_DEBUG_LOGIN_BODY": "{\"username\":\"\",\"password\":\"\"}",
240
+ "API_DEBUG_LOGIN_DESCRIPTION": "Save returned token to common headers in debug tool, field name Authorization, field value Bearer token"
189
241
  }
190
242
  }
191
243
  }
package/README.zh-CN.md CHANGED
@@ -2,6 +2,43 @@
2
2
 
3
3
  一个基于 MCP(Model Context Protocol)协议的项目标准管理工具,专为 AI 辅助开发而设计,帮助团队在多台机器上保持统一的开发标准和规范。
4
4
 
5
+ ## 📋 版本更新说明
6
+
7
+ ### v1.1.0 (2024-12-19)
8
+
9
+ #### 🆕 新增功能
10
+ - **API 调试工具环境变量支持**:
11
+ - `API_DEBUG_ALLOWED_METHODS` - 控制允许的请求方法(默认:GET,支持:GET,POST,PUT,DELETE,PATCH等)
12
+ - `API_DEBUG_LOGIN_URL` - 设置登录接口 URL(默认:/api/login)
13
+ - `API_DEBUG_LOGIN_METHOD` - 设置登录请求方法(默认:POST)
14
+ - `API_DEBUG_LOGIN_BODY` - 设置登录请求体(默认:{"username":"","password":""})
15
+ - `API_DEBUG_LOGIN_DESCRIPTION` - 设置登录接口说明(默认:将返回的token保存到调试工具中的公共header,字段名Authorization,字段值是Bearer token)
16
+
17
+ #### 🔧 功能优化
18
+ - **登录接口智能识别**:
19
+ - 支持完整 URL 和相对路径匹配
20
+ - 自动识别登录接口并使用环境变量配置
21
+ - 非登录接口严格遵循允许的方法限制
22
+
23
+ - **错误处理优化**:
24
+ - 只有请求相关错误才保存到 api.json
25
+ - 方法验证错误不污染执行记录
26
+ - 更精确的错误分类和处理
27
+
28
+ - **工具描述动态显示**:
29
+ - 根据环境变量配置显示登录认证信息
30
+ - 实时显示允许的请求方法和使用说明
31
+
32
+ #### 🛡️ 安全增强
33
+ - **请求方法限制**:默认只允许 GET 请求,防止误操作
34
+ - **登录接口例外**:登录接口可使用环境变量中配置的方法
35
+ - **灵活配置**:可根据需要开放更多请求方法
36
+
37
+ #### 📚 文档更新
38
+ - 添加了环境变量配置说明
39
+ - 更新了 API 调试工具使用指南
40
+ - 完善了登录认证流程文档
41
+
5
42
  ## 🚀 核心优势
6
43
 
7
44
  ### 🎯 解决多机器开发混乱问题
@@ -73,9 +110,14 @@ npm install
73
110
 
74
111
  ### 环境变量
75
112
 
76
- | 变量名 | 默认值 | 描述 |
77
- |--------|--------|------|
78
- | CONFIG_DIR | ./.setting | 配置文件目录(包含 config.json 和 api.json) |
113
+ | 变量名 | 默认值 | 描述 | 示例 |
114
+ |--------|--------|------|------|
115
+ | CONFIG_DIR | ./.setting | 配置文件目录(包含 config.json 和 api.json) | `export CONFIG_DIR="./config"` |
116
+ | API_DEBUG_ALLOWED_METHODS | GET | 控制允许的请求方法(支持:GET,POST,PUT,DELETE,PATCH等) | `export API_DEBUG_ALLOWED_METHODS="GET,POST"` |
117
+ | API_DEBUG_LOGIN_URL | /api/login | 设置登录接口 URL | `export API_DEBUG_LOGIN_URL="/api/auth/login"` |
118
+ | API_DEBUG_LOGIN_METHOD | POST | 设置登录请求方法 | `export API_DEBUG_LOGIN_METHOD="POST"` |
119
+ | API_DEBUG_LOGIN_BODY | {"username":"","password":""} | 设置登录请求体 | `export API_DEBUG_LOGIN_BODY='{"mobile":"","password":""}'` |
120
+ | API_DEBUG_LOGIN_DESCRIPTION | 将返回的token保存到调试工具中的公共header,字段名Authorization,字段值是Bearer token | 设置登录接口说明 | `export API_DEBUG_LOGIN_DESCRIPTION="用户登录接口"` |
79
121
 
80
122
  ### 配置文件
81
123
 
@@ -166,7 +208,12 @@ npm run dev
166
208
  "command": "npx",
167
209
  "args": ["@liangshanli/mcp-server-project-standards"],
168
210
  "env": {
169
- "CONFIG_DIR": "./.setting"
211
+ "CONFIG_DIR": "./.setting",
212
+ "API_DEBUG_ALLOWED_METHODS": "GET,POST,PUT,DELETE",
213
+ "API_DEBUG_LOGIN_URL": "/api/login",
214
+ "API_DEBUG_LOGIN_METHOD": "POST",
215
+ "API_DEBUG_LOGIN_BODY": "{\"username\":\"\",\"password\":\"\"}",
216
+ "API_DEBUG_LOGIN_DESCRIPTION": "将返回的token保存到调试工具中的公共header,字段名Authorization,字段值是Bearer token"
170
217
  }
171
218
  }
172
219
  }
@@ -185,7 +232,12 @@ npm run dev
185
232
  "command": "npx",
186
233
  "args": ["@liangshanli/mcp-server-project-standards"],
187
234
  "env": {
188
- "CONFIG_DIR": "./.setting"
235
+ "CONFIG_DIR": "./.setting",
236
+ "API_DEBUG_ALLOWED_METHODS": "GET,POST,PUT,DELETE",
237
+ "API_DEBUG_LOGIN_URL": "/api/login",
238
+ "API_DEBUG_LOGIN_METHOD": "POST",
239
+ "API_DEBUG_LOGIN_BODY": "{\"username\":\"\",\"password\":\"\"}",
240
+ "API_DEBUG_LOGIN_DESCRIPTION": "将返回的token保存到调试工具中的公共header,字段名Authorization,字段值是Bearer token"
189
241
  }
190
242
  }
191
243
  }
@@ -348,6 +400,10 @@ npm run dev
348
400
  - **执行记录**:无论成功失败都记录执行历史
349
401
  - **搜索功能**:支持按 URL 或描述搜索 API
350
402
  - **参数管理**:支持查询参数、请求体、自定义请求头等
403
+ - **环境变量控制**:通过环境变量控制允许的请求方法和登录接口配置
404
+ - **请求方法限制**:默认只允许 GET 请求,防止误操作
405
+ - **登录接口智能识别**:自动识别登录接口并使用环境变量配置
406
+ - **动态工具描述**:根据环境变量配置实时显示工具说明
351
407
 
352
408
  **🔐 特别说明 - 登录认证流程:**
353
409
 
package/bin/cli.js CHANGED
@@ -28,9 +28,20 @@ function startServer() {
28
28
  const env = {
29
29
  ...process.env,
30
30
  // Set CONFIG_DIR if specified, otherwise use default
31
- CONFIG_DIR: process.env.CONFIG_DIR || './.setting'
31
+ CONFIG_DIR: process.env.CONFIG_DIR || './.setting',
32
+ // API Debug environment variables
33
+ API_DEBUG_ALLOWED_METHODS: process.env.API_DEBUG_ALLOWED_METHODS || 'GET',
34
+ API_DEBUG_LOGIN_URL: process.env.API_DEBUG_LOGIN_URL || '/api/login',
35
+ API_DEBUG_LOGIN_METHOD: process.env.API_DEBUG_LOGIN_METHOD || 'POST',
36
+ API_DEBUG_LOGIN_BODY: process.env.API_DEBUG_LOGIN_BODY || '{"username":"","password":""}',
37
+ API_DEBUG_LOGIN_DESCRIPTION: process.env.API_DEBUG_LOGIN_DESCRIPTION || 'Save returned token to common headers in debug tool, field name Authorization, field value Bearer token'
32
38
  };
33
39
 
40
+ // Convert allowed methods to uppercase if specified
41
+ if (env.API_DEBUG_ALLOWED_METHODS) {
42
+ env.API_DEBUG_ALLOWED_METHODS = env.API_DEBUG_ALLOWED_METHODS.toUpperCase();
43
+ }
44
+
34
45
  writeLog('INFO', 'Starting MCP Project Standards server');
35
46
 
36
47
  server = spawn('node', [serverPath], {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liangshanli/mcp-server-project-standards",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "MCP Project Standards server with project info, structure, API standards, development standards and custom tools",
5
5
  "main": "bin/cli.js",
6
6
  "bin": {
@@ -54,7 +54,7 @@ console.error('==============================================');
54
54
  class ProjectStandardsMCPServer {
55
55
  constructor() {
56
56
  this.name = 'project-standards-mcp-server';
57
- this.version = '1.0.0';
57
+ this.version = '1.2.0';
58
58
  this.initialized = false;
59
59
  this.config = getConfig();
60
60
  this.needsProjectFolder = this.config === null;
@@ -498,16 +498,48 @@ class ProjectStandardsMCPServer {
498
498
  }
499
499
  );
500
500
 
501
+ // 构建 API 调试工具描述
502
+ let apiDebugDescription = 'API debugging tool for testing and executing API requests. Use URL to identify APIs instead of index numbers.';
503
+
504
+ // 检查是否设置了登录接口环境变量
505
+ const loginUrl = process.env.API_DEBUG_LOGIN_URL;
506
+ const loginMethod = process.env.API_DEBUG_LOGIN_METHOD;
507
+ const loginDescription = process.env.API_DEBUG_LOGIN_DESCRIPTION;
508
+ const allowedMethods = process.env.API_DEBUG_ALLOWED_METHODS;
509
+
510
+ if (loginUrl || loginMethod || allowedMethods) {
511
+ apiDebugDescription += '\n\n🔐 Login Authentication Configuration:';
512
+
513
+ if (loginUrl) {
514
+ apiDebugDescription += `\n- Login URL: ${loginUrl}`;
515
+ }
516
+ if (loginMethod) {
517
+ apiDebugDescription += `\n- Login Method: ${loginMethod}`;
518
+ }
519
+ if (loginDescription) {
520
+ apiDebugDescription += `\n- Login Description: ${loginDescription}`;
521
+ }
522
+ if (allowedMethods) {
523
+ apiDebugDescription += `\n- Allowed Methods: ${allowedMethods}`;
524
+ }
525
+
526
+ apiDebugDescription += '\n\n💡 Usage Instructions:';
527
+ apiDebugDescription += '\n- Use URL to identify APIs for execute and delete operations (not index numbers)';
528
+ apiDebugDescription += '\n- Login API automatically uses environment variable configuration';
529
+ apiDebugDescription += '\n- Non-login APIs must use allowed methods only';
530
+ apiDebugDescription += '\n- Common request headers are automatically updated after successful login';
531
+ }
532
+
501
533
  tools.push({
502
534
  name: 'api_debug',
503
- description: 'API debugging tool for testing and executing API requests',
535
+ description: apiDebugDescription,
504
536
  inputSchema: {
505
537
  type: 'object',
506
538
  properties: {
507
539
  action: {
508
540
  type: 'string',
509
541
  enum: ['get', 'set', 'delete', 'execute', 'updateBaseUrl', 'updateHeaders', 'deleteHeader', 'search'],
510
- description: 'Action to perform: "get" to retrieve config, "set" to update config, "delete" to delete API, "execute" to execute API, "updateBaseUrl" to update base URL, "updateHeaders" to update headers, "deleteHeader" to delete specific header, "search" to search APIs by URL or description'
542
+ description: 'Action to perform: "get" to retrieve config, "set" to update config, "delete" to delete API by URL, "execute" to execute API by URL, "updateBaseUrl" to update base URL, "updateHeaders" to update headers, "deleteHeader" to delete specific header, "search" to search APIs by URL or description'
511
543
  },
512
544
  config: {
513
545
  type: 'object',
@@ -561,9 +593,9 @@ class ProjectStandardsMCPServer {
561
593
  }
562
594
  }
563
595
  },
564
- index: {
565
- type: 'number',
566
- description: 'Index of API to delete or execute (required for "delete" and "execute" actions)'
596
+ url: {
597
+ type: 'string',
598
+ description: 'URL of API to delete or execute (required for "delete" and "execute" actions)'
567
599
  },
568
600
  baseUrl: {
569
601
  type: 'string',
@@ -599,16 +631,16 @@ class ProjectStandardsMCPServer {
599
631
  {
600
632
  properties: {
601
633
  action: { const: 'delete' },
602
- index: { type: 'number' }
634
+ url: { type: 'string' }
603
635
  },
604
- required: ['index']
636
+ required: ['url']
605
637
  },
606
638
  {
607
639
  properties: {
608
640
  action: { const: 'execute' },
609
- index: { type: 'number' }
641
+ url: { type: 'string' }
610
642
  },
611
- required: ['index']
643
+ required: ['url']
612
644
  },
613
645
  {
614
646
  properties: {
@@ -1,6 +1,32 @@
1
1
  const fs = require('fs-extra');
2
2
  const path = require('path');
3
3
 
4
+ // Get allowed methods from environment variable
5
+ const getAllowedMethods = () => {
6
+ const allowedMethods = process.env.API_DEBUG_ALLOWED_METHODS || 'GET';
7
+ return allowedMethods.split(',').map(method => method.trim().toUpperCase());
8
+ };
9
+
10
+ // Get login URL from environment variable
11
+ const getLoginUrl = () => {
12
+ return process.env.API_DEBUG_LOGIN_URL || '/api/login';
13
+ };
14
+
15
+ // Get login method from environment variable
16
+ const getLoginMethod = () => {
17
+ return (process.env.API_DEBUG_LOGIN_METHOD || 'POST').toUpperCase();
18
+ };
19
+
20
+ // Get login body from environment variable
21
+ const getLoginBody = () => {
22
+ return process.env.API_DEBUG_LOGIN_BODY || '{"username":"","password":""}';
23
+ };
24
+
25
+ // Get login description from environment variable
26
+ const getLoginDescription = () => {
27
+ return process.env.API_DEBUG_LOGIN_DESCRIPTION || 'Save returned token to common headers in debug tool, field name Authorization, field value Bearer token';
28
+ };
29
+
4
30
  // Get API debug config file path
5
31
  const getApiConfigPath = () => {
6
32
  const configDir = process.env.CONFIG_DIR || './.setting';
@@ -93,7 +119,7 @@ const detectContentType = (body) => {
93
119
  * @param {string} params.config.baseUrl - API 基础 URL
94
120
  * @param {Object} params.config.headers - 公共请求头
95
121
  * @param {Array} params.config.list - API 接口列表
96
- * @param {string} params.index - 要执行的接口索引(执行时必需)
122
+ * @param {string} params.url - 要执行的接口URL(执行时必需)
97
123
  * @param {string} params.baseUrl - 新的基础 URL(updateBaseUrl 时必需)
98
124
  * @param {Object} params.headers - 新的公共请求头(updateHeaders 时必需)
99
125
  * @param {string} params.headerName - 要删除的请求头名称(deleteHeader 时必需)
@@ -103,7 +129,7 @@ const detectContentType = (body) => {
103
129
  * @returns {Object} API 调试结果
104
130
  */
105
131
  async function api_debug(params, config, saveConfig) {
106
- const { action, config: apiConfig, index } = params || {};
132
+ const { action, config: apiConfig, url } = params || {};
107
133
 
108
134
  if (!action) {
109
135
  throw new Error('Missing action parameter. Must be "get", "set", "delete", "execute", "updateBaseUrl", "updateHeaders", "deleteHeader", or "search"');
@@ -173,8 +199,8 @@ async function api_debug(params, config, saveConfig) {
173
199
  throw new Error(`Failed to update API debug config: ${err.message}`);
174
200
  }
175
201
  } else if (action === 'delete') {
176
- if (!index && index !== 0) {
177
- throw new Error('Missing index parameter for delete action');
202
+ if (!url) {
203
+ throw new Error('Missing url parameter for delete action');
178
204
  }
179
205
 
180
206
  try {
@@ -185,31 +211,36 @@ async function api_debug(params, config, saveConfig) {
185
211
  apiDebugConfig.list = [];
186
212
  }
187
213
 
188
- // 删除指定索引的接口
189
- if (index >= 0 && index < apiDebugConfig.list.length) {
190
- const deletedItem = apiDebugConfig.list.splice(index, 1)[0];
191
-
192
- // 保存配置
193
- const saved = saveApiConfig(apiDebugConfig);
194
- if (!saved) {
195
- throw new Error('Failed to save API configuration');
196
- }
197
-
214
+ // 查找并删除指定URL的接口
215
+ const originalLength = apiDebugConfig.list.length;
216
+ apiDebugConfig.list = apiDebugConfig.list.filter(item => item.url !== url);
217
+
218
+ if (apiDebugConfig.list.length === originalLength) {
198
219
  return {
199
- success: true,
200
- message: `Successfully deleted API at index ${index}`,
201
- deletedItem: deletedItem,
220
+ success: false,
221
+ message: `API with URL "${url}" not found`,
202
222
  timestamp: new Date().toISOString()
203
223
  };
204
- } else {
205
- throw new Error(`Invalid index: ${index}. Must be between 0 and ${apiDebugConfig.list.length - 1}`);
206
224
  }
225
+
226
+ // 保存配置
227
+ const saved = saveApiConfig(apiDebugConfig);
228
+ if (!saved) {
229
+ throw new Error('Failed to save API configuration');
230
+ }
231
+
232
+ return {
233
+ success: true,
234
+ message: `Successfully deleted API with URL: ${url}`,
235
+ deletedUrl: url,
236
+ timestamp: new Date().toISOString()
237
+ };
207
238
  } catch (err) {
208
239
  throw new Error(`Failed to delete API: ${err.message}`);
209
240
  }
210
241
  } else if (action === 'execute') {
211
- if (!index && index !== 0) {
212
- throw new Error('Missing index parameter for execute action');
242
+ if (!url) {
243
+ throw new Error('Missing url parameter for execute action');
213
244
  }
214
245
 
215
246
  try {
@@ -220,14 +251,54 @@ async function api_debug(params, config, saveConfig) {
220
251
  throw new Error('API list not found or invalid');
221
252
  }
222
253
 
223
- if (index < 0 || index >= apiDebugConfig.list.length) {
224
- throw new Error(`Invalid index: ${index}. Must be between 0 and ${apiDebugConfig.list.length - 1}`);
254
+ // 查找指定URL的接口
255
+ const apiItem = apiDebugConfig.list.find(item => item.url === url);
256
+ if (!apiItem) {
257
+ throw new Error(`API with URL "${url}" not found`);
225
258
  }
226
259
 
227
- const apiItem = apiDebugConfig.list[index];
260
+ // 获取接口在列表中的索引(用于更新数据)
261
+ const itemIndex = apiDebugConfig.list.findIndex(item => item.url === url);
228
262
  const baseUrl = apiDebugConfig.baseUrl || '';
229
263
  const commonHeaders = apiDebugConfig.headers || {};
230
264
 
265
+ // 验证请求方法是否被允许
266
+ const allowedMethods = getAllowedMethods();
267
+ const requestMethod = (apiItem.method || 'GET').toUpperCase();
268
+ const loginUrl = getLoginUrl();
269
+
270
+ // 判断是否为登录接口 - 支持完整 URL 和相对路径匹配
271
+ const isLoginRequest = (() => {
272
+ const apiUrl = apiItem.url;
273
+ const loginUrlPattern = loginUrl;
274
+
275
+ // 如果登录 URL 是完整 URL,提取路径部分进行匹配
276
+ if (loginUrlPattern.startsWith('http://') || loginUrlPattern.startsWith('https://')) {
277
+ try {
278
+ const url = new URL(loginUrlPattern);
279
+ const loginPath = url.pathname;
280
+ // 匹配完整路径或去掉前导斜杠的路径
281
+ return apiUrl === loginPath || apiUrl === loginPath.replace(/^\//, '') || apiUrl === loginUrlPattern;
282
+ } catch (e) {
283
+ // 如果 URL 解析失败,回退到字符串匹配
284
+ return apiUrl === loginUrlPattern;
285
+ }
286
+ } else {
287
+ // 相对路径匹配
288
+ return apiUrl === loginUrlPattern ||
289
+ apiUrl === loginUrlPattern.replace(/^\//, '') ||
290
+ apiUrl.endsWith(loginUrlPattern) ||
291
+ apiUrl.endsWith(loginUrlPattern.replace(/^\//, ''));
292
+ }
293
+ })();
294
+
295
+ if (!allowedMethods.includes(requestMethod)) {
296
+ // 如果是登录接口,继续执行;否则返回错误
297
+ if (!isLoginRequest) {
298
+ throw new Error(`Method ${requestMethod} is not allowed. Allowed methods: ${allowedMethods.join(', ')}`);
299
+ }
300
+ }
301
+
231
302
  // 构建完整 URL
232
303
  const fullUrl = baseUrl + apiItem.url;
233
304
 
@@ -291,64 +362,113 @@ async function api_debug(params, config, saveConfig) {
291
362
 
292
363
  const finalUrl = queryString ? `${fullUrl}?${queryString}` : fullUrl;
293
364
 
365
+ let success = true;
294
366
  let response;
295
367
  let responseData;
296
368
  let error = null;
297
- let success = true;
298
369
 
370
+ // 请求处理部分 - 只有这部分出错才会保存到 api.json
299
371
  try {
300
- // 执行请求
301
- response = await fetch(finalUrl, {
302
- method: apiItem.method || 'GET',
303
- headers: headers,
304
- body: body
305
- });
306
372
 
307
- // 获取响应数据
308
- const contentType = response.headers.get('content-type');
373
+ // 如果是登录接口且方法不被允许,使用环境变量中的登录配置
374
+ if (isLoginRequest && !allowedMethods.includes(requestMethod)) {
375
+ const loginMethod = getLoginMethod();
376
+ const loginBody = getLoginBody();
377
+
378
+ // 更新请求方法和请求体
379
+ apiItem.method = loginMethod;
380
+ if (loginBody) {
381
+ apiItem.body = loginBody;
382
+ }
383
+
384
+ // 更新最终 URL 和方法
385
+ const updatedFinalUrl = queryString ? `${fullUrl}?${queryString}` : fullUrl;
386
+
387
+ try {
388
+ response = await fetch(updatedFinalUrl, {
389
+ method: loginMethod,
390
+ headers: headers,
391
+ body: loginBody
392
+ });
393
+ } catch (fetchError) {
394
+ error = fetchError.message;
395
+ success = false;
396
+ response = null;
397
+ }
398
+ } else {
399
+ try {
400
+ // 执行请求
401
+ response = await fetch(finalUrl, {
402
+ method: apiItem.method || 'GET',
403
+ headers: headers,
404
+ body: body
405
+ });
406
+ } catch (fetchError) {
407
+ error = fetchError.message;
408
+ success = false;
409
+ response = null;
410
+ }
411
+ }
309
412
 
310
- if (contentType && contentType.includes('application/json')) {
311
- responseData = await response.json();
413
+ if (response) {
414
+ // 获取响应数据
415
+ const contentType = response.headers.get('content-type');
416
+
417
+ if (contentType && contentType.includes('application/json')) {
418
+ responseData = await response.json();
419
+ } else {
420
+ responseData = await response.text();
421
+ }
422
+
423
+ // 判断请求是否成功(HTTP 状态码 200-299 为成功)
424
+ const isHttpSuccess = response.status >= 200 && response.status < 300;
425
+ success = isHttpSuccess;
426
+
427
+ // 记录响应信息
428
+ apiDebugConfig.list[itemIndex].data = responseData;
429
+ apiDebugConfig.list[itemIndex].status = response.status;
430
+ apiDebugConfig.list[itemIndex].statusText = response.statusText;
431
+ apiDebugConfig.list[itemIndex].responseHeaders = Object.fromEntries(response.headers.entries());
432
+ apiDebugConfig.list[itemIndex].lastExecuted = new Date().toISOString();
433
+ apiDebugConfig.list[itemIndex].success = isHttpSuccess;
434
+ apiDebugConfig.list[itemIndex].error = isHttpSuccess ? null : `HTTP ${response.status}: ${response.statusText}`;
312
435
  } else {
313
- responseData = await response.text();
436
+ // 记录失败信息
437
+ success = false;
438
+ apiDebugConfig.list[itemIndex].data = null;
439
+ apiDebugConfig.list[itemIndex].status = null;
440
+ apiDebugConfig.list[itemIndex].statusText = null;
441
+ apiDebugConfig.list[itemIndex].responseHeaders = null;
442
+ apiDebugConfig.list[itemIndex].lastExecuted = new Date().toISOString();
443
+ apiDebugConfig.list[itemIndex].success = false;
444
+ apiDebugConfig.list[itemIndex].error = error;
314
445
  }
315
446
 
316
- // 记录成功信息
317
- apiDebugConfig.list[index].data = responseData;
318
- apiDebugConfig.list[index].status = response.status;
319
- apiDebugConfig.list[index].statusText = response.statusText;
320
- apiDebugConfig.list[index].responseHeaders = Object.fromEntries(response.headers.entries());
321
- apiDebugConfig.list[index].lastExecuted = new Date().toISOString();
322
- apiDebugConfig.list[index].success = true;
323
- apiDebugConfig.list[index].error = null;
447
+ // 去重处理:相同的 URL 只保留一份(保留最新的执行结果)
448
+ const urlMap = new Map();
449
+ apiDebugConfig.list.forEach(item => {
450
+ if (item.url) {
451
+ urlMap.set(item.url, item);
452
+ }
453
+ });
454
+ apiDebugConfig.list = Array.from(urlMap.values());
324
455
 
325
- } catch (fetchError) {
326
- // 记录失败信息
327
- error = fetchError.message;
328
- success = false;
456
+ // 无论成功还是失败,都保存配置
457
+ saveApiConfig(apiDebugConfig);
329
458
 
330
- apiDebugConfig.list[index].data = null;
331
- apiDebugConfig.list[index].status = null;
332
- apiDebugConfig.list[index].statusText = null;
333
- apiDebugConfig.list[index].responseHeaders = null;
334
- apiDebugConfig.list[index].lastExecuted = new Date().toISOString();
335
- apiDebugConfig.list[index].success = false;
336
- apiDebugConfig.list[index].error = error;
337
- }
338
-
339
- // 去重处理:相同的 URL 只保留一份(保留最新的执行结果)
340
- const urlMap = new Map();
341
- apiDebugConfig.list.forEach(item => {
342
- if (item.url) {
343
- urlMap.set(item.url, item);
459
+ } catch (requestError) {
460
+ // 只有请求相关的错误才保存到 api.json
461
+ try {
462
+ apiDebugConfig.list[itemIndex].lastExecuted = new Date().toISOString();
463
+ apiDebugConfig.list[itemIndex].success = false;
464
+ apiDebugConfig.list[itemIndex].error = requestError.message;
465
+ saveApiConfig(apiDebugConfig);
466
+ } catch (saveErr) {
467
+ console.error('Failed to save request error information:', saveErr.message);
344
468
  }
345
- });
346
- apiDebugConfig.list = Array.from(urlMap.values());
347
-
348
- // 无论成功还是失败,都保存配置
349
- saveApiConfig(apiDebugConfig);
469
+ }
350
470
 
351
- if (success) {
471
+ if (success && response) {
352
472
  return {
353
473
  success: true,
354
474
  message: `Successfully executed API: ${apiItem.description || apiItem.url}`,
@@ -376,7 +496,7 @@ async function api_debug(params, config, saveConfig) {
376
496
  headers: headers,
377
497
  body: body
378
498
  },
379
- error: error,
499
+ error: error || (response ? `HTTP ${response.status}: ${response.statusText}` : 'Request failed'),
380
500
  timestamp: new Date().toISOString()
381
501
  };
382
502
  }
@@ -384,10 +504,11 @@ async function api_debug(params, config, saveConfig) {
384
504
  // 如果是在保存配置时出错,也要尝试记录错误信息
385
505
  try {
386
506
  const apiDebugConfig = loadApiConfig();
387
- if (apiDebugConfig.list && apiDebugConfig.list[index]) {
388
- apiDebugConfig.list[index].lastExecuted = new Date().toISOString();
389
- apiDebugConfig.list[index].success = false;
390
- apiDebugConfig.list[index].error = err.message;
507
+ const itemIndex = apiDebugConfig.list.findIndex(item => item.url === url);
508
+ if (apiDebugConfig.list && itemIndex >= 0) {
509
+ apiDebugConfig.list[itemIndex].lastExecuted = new Date().toISOString();
510
+ apiDebugConfig.list[itemIndex].success = false;
511
+ apiDebugConfig.list[itemIndex].error = err.message;
391
512
  saveApiConfig(apiDebugConfig);
392
513
  }
393
514
  } catch (saveErr) {