lhwapi-mcp-server 1.0.7 → 1.0.9

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/dist/bundle.js CHANGED
@@ -30088,15 +30088,27 @@ var StdioServerTransport = class {
30088
30088
  };
30089
30089
 
30090
30090
  // src/index.ts
30091
+ console.error("LHW API MCP Server \u542F\u52A8\u4E2D...");
30091
30092
  var APIFOX_BASE_URL = "https://api.apifox.com";
30092
30093
  var args = process.argv.slice(2);
30093
30094
  var projectId;
30095
+ var token;
30094
30096
  for (let i = 0; i < args.length; i++) {
30095
30097
  if (args[i] === "--project-id" && args[i + 1]) {
30096
30098
  projectId = args[i + 1];
30099
+ } else if (args[i].startsWith("--project-id=")) {
30100
+ projectId = args[i].split("=")[1];
30101
+ }
30102
+ if (args[i] === "--token" && args[i + 1]) {
30103
+ token = args[i + 1];
30104
+ } else if (args[i].startsWith("--token=")) {
30105
+ token = args[i].split("=")[1];
30097
30106
  }
30098
30107
  }
30099
- var token = process.env.APIFOX_ACCESS_TOKEN;
30108
+ token = token || process.env.APIFOX_ACCESS_TOKEN;
30109
+ projectId = projectId || process.env.APIFOX_PROJECT_ID;
30110
+ console.error("Project ID:", projectId || "\u672A\u8BBE\u7F6E");
30111
+ console.error("Token:", token ? "\u5DF2\u8BBE\u7F6E" : "\u672A\u8BBE\u7F6E");
30100
30112
  async function fetchApifox(endpoint, authToken, options) {
30101
30113
  const response = await fetch(`${APIFOX_BASE_URL}${endpoint}`, {
30102
30114
  method: options?.method || "GET",
@@ -30119,241 +30131,139 @@ var server = new McpServer({
30119
30131
  version: "1.0.0"
30120
30132
  });
30121
30133
  server.registerTool(
30122
- "listProjects",
30134
+ "export_openapi",
30123
30135
  {
30124
- description: "\u83B7\u53D6 Apifox \u9879\u76EE\u5217\u8868",
30136
+ description: "\u5BFC\u51FA\u9879\u76EE\u7684 OpenAPI (Swagger) \u683C\u5F0F\u6570\u636E\uFF0C\u652F\u6301 JSON \u6216 YAML \u683C\u5F0F",
30125
30137
  inputSchema: external_exports3.object({
30126
- token: external_exports3.string().optional().describe("Apifox \u8BBF\u95EE\u4EE4\u724C (\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u73AF\u5883\u53D8\u91CF)")
30138
+ oasVersion: external_exports3.string().optional().describe("OpenAPI \u7248\u672C: 3.0, 3.1, 2.0\uFF0C\u9ED8\u8BA4 3.1"),
30139
+ exportFormat: external_exports3.string().optional().describe("\u5BFC\u51FA\u683C\u5F0F: JSON \u6216 YAML\uFF0C\u9ED8\u8BA4 JSON")
30127
30140
  }).shape
30128
30141
  },
30129
- async ({ token: inputToken }) => {
30130
- const authToken = inputToken || token;
30131
- if (!authToken) {
30142
+ async ({ oasVersion, exportFormat }) => {
30143
+ console.error("\u8C03\u7528 export_openapi \u5DE5\u5177");
30144
+ console.error("projectId:", projectId);
30145
+ if (!token) {
30132
30146
  return {
30133
- content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u8BBE\u7F6E APIFOX_ACCESS_TOKEN \u73AF\u5883\u53D8\u91CF\u6216\u4F20\u5165 token \u53C2\u6570" }],
30147
+ content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u8BBE\u7F6E APIFOX_ACCESS_TOKEN \u73AF\u5883\u53D8\u91CF" }],
30134
30148
  isError: true
30135
30149
  };
30136
30150
  }
30137
- const projects = await fetchApifox("/v1/projects", authToken);
30138
- const text = projects.map((p) => `\u9879\u76EE: ${p.name} (ID: ${p.id})
30139
- \u63CF\u8FF0: ${p.description || "\u65E0"}`).join("\n\n");
30140
- return {
30141
- content: [{ type: "text", text: text || "\u6682\u65E0\u9879\u76EE" }]
30142
- };
30143
- }
30144
- );
30145
- server.registerTool(
30146
- "listApis",
30147
- {
30148
- description: "\u83B7\u53D6\u6307\u5B9A\u9879\u76EE\u4E0B\u7684 API \u5217\u8868",
30149
- inputSchema: external_exports3.object({
30150
- projectId: external_exports3.string().optional().describe("\u9879\u76EE ID (\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u547D\u4EE4\u884C\u53C2\u6570)"),
30151
- token: external_exports3.string().optional().describe("Apifox \u8BBF\u95EE\u4EE4\u724C (\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u73AF\u5883\u53D8\u91CF)")
30152
- }).shape
30153
- },
30154
- async ({ projectId: inputProjectId, token: inputToken }) => {
30155
- const authToken = inputToken || token;
30156
- const authProjectId = inputProjectId || projectId;
30157
- if (!authToken) {
30151
+ if (!projectId) {
30158
30152
  return {
30159
- content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u8BBE\u7F6E APIFOX_ACCESS_TOKEN \u73AF\u5883\u53D8\u91CF\u6216\u4F20\u5165 token \u53C2\u6570" }],
30153
+ content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u901A\u8FC7 --project-id \u53C2\u6570\u6307\u5B9A\u9879\u76EE ID" }],
30160
30154
  isError: true
30161
30155
  };
30162
30156
  }
30163
- if (!authProjectId) {
30157
+ try {
30158
+ const result = await fetchApifox(
30159
+ `/v1/projects/${projectId}/export-openapi`,
30160
+ token,
30161
+ {
30162
+ method: "POST",
30163
+ body: {
30164
+ scope: { type: "ALL" },
30165
+ oasVersion: oasVersion || "3.1",
30166
+ exportFormat: exportFormat || "JSON"
30167
+ }
30168
+ }
30169
+ );
30170
+ const format = exportFormat || "JSON";
30171
+ let output;
30172
+ if (format.toUpperCase() === "YAML") {
30173
+ output = result.openapi || "";
30174
+ } else {
30175
+ output = JSON.stringify(result, null, 2);
30176
+ }
30177
+ console.error("\u5BFC\u51FA\u6210\u529F");
30164
30178
  return {
30165
- content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u901A\u8FC7 --project-id \u53C2\u6570\u6307\u5B9A\u9879\u76EE ID" }],
30179
+ content: [{ type: "text", text: output }]
30180
+ };
30181
+ } catch (error48) {
30182
+ console.error("\u5BFC\u51FA\u9519\u8BEF:", error48);
30183
+ return {
30184
+ content: [{ type: "text", text: `\u5BFC\u51FA\u5931\u8D25: ${error48 instanceof Error ? error48.message : String(error48)}` }],
30166
30185
  isError: true
30167
30186
  };
30168
30187
  }
30169
- const apis = await fetchApifox(
30170
- `/v1/projects/${authProjectId}/apis`,
30171
- authToken
30172
- );
30173
- const text = apis.map((api) => `[${api.method.toUpperCase()}] ${api.path} - ${api.name}`).join("\n");
30174
- return {
30175
- content: [{ type: "text", text: text || "\u6682\u65E0 API" }]
30176
- };
30177
30188
  }
30178
30189
  );
30179
30190
  server.registerTool(
30180
- "getApiDetail",
30191
+ "refresh_oas",
30181
30192
  {
30182
- description: "\u83B7\u53D6\u5355\u4E2A API \u7684\u8BE6\u7EC6\u4FE1\u606F",
30183
- inputSchema: external_exports3.object({
30184
- apiId: external_exports3.string().describe("API ID"),
30185
- projectId: external_exports3.string().optional().describe("\u9879\u76EE ID (\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u547D\u4EE4\u884C\u53C2\u6570)"),
30186
- token: external_exports3.string().optional().describe("Apifox \u8BBF\u95EE\u4EE4\u724C (\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u73AF\u5883\u53D8\u91CF)")
30187
- }).shape
30193
+ description: "\u5237\u65B0\u9879\u76EE\u7684 OpenAPI \u7F13\u5B58",
30194
+ inputSchema: external_exports3.object({}).shape
30188
30195
  },
30189
- async ({ apiId, projectId: inputProjectId, token: inputToken }) => {
30190
- const authToken = inputToken || token;
30191
- const authProjectId = inputProjectId || projectId;
30192
- if (!authToken) {
30196
+ async () => {
30197
+ console.error("\u8C03\u7528 refresh_oas \u5DE5\u5177");
30198
+ if (!token) {
30193
30199
  return {
30194
- content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u8BBE\u7F6E APIFOX_ACCESS_TOKEN \u73AF\u5883\u53D8\u91CF\u6216\u4F20\u5165 token \u53C2\u6570" }],
30200
+ content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u8BBE\u7F6E APIFOX_ACCESS_TOKEN \u73AF\u5883\u53D8\u91CF" }],
30195
30201
  isError: true
30196
30202
  };
30197
30203
  }
30198
- if (!authProjectId) {
30204
+ if (!projectId) {
30199
30205
  return {
30200
30206
  content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u901A\u8FC7 --project-id \u53C2\u6570\u6307\u5B9A\u9879\u76EE ID" }],
30201
30207
  isError: true
30202
30208
  };
30203
30209
  }
30204
- const api = await fetchApifox(
30205
- `/v1/projects/${authProjectId}/apis/${apiId}`,
30206
- authToken
30207
- );
30208
- let detail = `# ${api.name}
30209
-
30210
- `;
30211
- detail += `**\u65B9\u6CD5**: ${api.method.toUpperCase()}
30212
- `;
30213
- detail += `**\u8DEF\u5F84**: ${api.path}
30214
-
30215
- `;
30216
- if (api.description) {
30217
- detail += `## \u63CF\u8FF0
30218
-
30219
- ${api.description}
30220
-
30221
- `;
30222
- }
30223
- if (api.requestParams?.query?.length) {
30224
- detail += `## Query \u53C2\u6570
30225
-
30226
- `;
30227
- api.requestParams.query.forEach((param) => {
30228
- detail += `- ${param.name}: ${param.type || "string"} ${param.required ? "(\u5FC5\u586B)" : "(\u53EF\u9009)"}
30229
- `;
30230
- });
30231
- detail += "\n";
30232
- }
30233
- if (api.requestBody?.schema) {
30234
- detail += `## \u8BF7\u6C42\u4F53
30235
-
30236
- \`\`\`json
30237
- ${JSON.stringify(api.requestBody.schema, null, 2)}
30238
- \`\`\`
30239
-
30240
- `;
30241
- }
30242
- if (api.responseList?.length) {
30243
- detail += `## \u54CD\u5E94
30244
-
30245
- `;
30246
- api.responseList.forEach((resp) => {
30247
- detail += `### ${resp.statusCode}
30248
- `;
30249
- if (resp.responseBodySchema) {
30250
- detail += `\`\`\`json
30251
- ${JSON.stringify(resp.responseBodySchema, null, 2)}
30252
- \`\`\`
30253
- `;
30254
- }
30255
- });
30256
- }
30257
- return {
30258
- content: [{ type: "text", text: detail }]
30259
- };
30260
- }
30261
- );
30262
- server.registerTool(
30263
- "searchApis",
30264
- {
30265
- description: "\u641C\u7D22 API",
30266
- inputSchema: external_exports3.object({
30267
- keyword: external_exports3.string().describe("\u641C\u7D22\u5173\u952E\u8BCD"),
30268
- projectId: external_exports3.string().optional().describe("\u9879\u76EE ID (\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u547D\u4EE4\u884C\u53C2\u6570)"),
30269
- token: external_exports3.string().optional().describe("Apifox \u8BBF\u95EE\u4EE4\u724C (\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u73AF\u5883\u53D8\u91CF)")
30270
- }).shape
30271
- },
30272
- async ({ keyword, projectId: inputProjectId, token: inputToken }) => {
30273
- const authToken = inputToken || token;
30274
- const authProjectId = inputProjectId || projectId;
30275
- if (!authToken) {
30210
+ try {
30211
+ await fetchApifox(
30212
+ `/v1/projects/${projectId}/refresh-openapi-cache`,
30213
+ token,
30214
+ { method: "POST" }
30215
+ );
30216
+ console.error("\u5237\u65B0\u6210\u529F");
30276
30217
  return {
30277
- content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u8BBE\u7F6E APIFOX_ACCESS_TOKEN \u73AF\u5883\u53D8\u91CF\u6216\u4F20\u5165 token \u53C2\u6570" }],
30278
- isError: true
30218
+ content: [{ type: "text", text: "OpenAPI \u7F13\u5B58\u5DF2\u5237\u65B0" }]
30279
30219
  };
30280
- }
30281
- if (!authProjectId) {
30220
+ } catch (error48) {
30221
+ console.error("\u5237\u65B0\u9519\u8BEF:", error48);
30282
30222
  return {
30283
- content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u901A\u8FC7 --project-id \u53C2\u6570\u6307\u5B9A\u9879\u76EE ID" }],
30223
+ content: [{ type: "text", text: `\u5237\u65B0\u5931\u8D25: ${error48 instanceof Error ? error48.message : String(error48)}` }],
30284
30224
  isError: true
30285
30225
  };
30286
30226
  }
30287
- const apis = await fetchApifox(
30288
- `/v1/projects/${authProjectId}/apis`,
30289
- authToken
30290
- );
30291
- const filtered = apis.filter(
30292
- (api) => api.name.toLowerCase().includes(keyword.toLowerCase()) || api.path.toLowerCase().includes(keyword.toLowerCase())
30293
- );
30294
- const text = filtered.map((api) => `[${api.method.toUpperCase()}] ${api.path} - ${api.name}`).join("\n");
30295
- return {
30296
- content: [{ type: "text", text: text || "\u672A\u627E\u5230\u5339\u914D\u7684 API" }]
30297
- };
30298
30227
  }
30299
30228
  );
30300
30229
  server.registerTool(
30301
- "exportOpenApi",
30230
+ "list_apis",
30302
30231
  {
30303
- description: "\u5BFC\u51FA OpenAPI/Swagger \u683C\u5F0F\u6570\u636E",
30304
- inputSchema: external_exports3.object({
30305
- oasVersion: external_exports3.string().optional().describe("OpenAPI \u7248\u672C: 3.0, 3.1, 2.0"),
30306
- exportFormat: external_exports3.string().optional().describe("\u5BFC\u51FA\u683C\u5F0F: JSON \u6216 YAML"),
30307
- projectId: external_exports3.string().optional().describe("\u9879\u76EE ID (\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u547D\u4EE4\u884C\u53C2\u6570)"),
30308
- token: external_exports3.string().optional().describe("Apifox \u8BBF\u95EE\u4EE4\u724C (\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u73AF\u5883\u53D8\u91CF)")
30309
- }).shape
30232
+ description: "\u83B7\u53D6\u9879\u76EE\u4E0B\u7684 API \u63A5\u53E3\u5217\u8868",
30233
+ inputSchema: external_exports3.object({}).shape
30310
30234
  },
30311
- async ({ oasVersion, exportFormat, projectId: inputProjectId, token: inputToken }) => {
30312
- const authToken = inputToken || token;
30313
- const authProjectId = inputProjectId || projectId;
30314
- if (!authToken) {
30235
+ async () => {
30236
+ console.error("\u8C03\u7528 list_apis \u5DE5\u5177");
30237
+ if (!token) {
30315
30238
  return {
30316
- content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u8BBE\u7F6E APIFOX_ACCESS_TOKEN \u73AF\u5883\u53D8\u91CF\u6216\u4F20\u5165 token \u53C2\u6570" }],
30239
+ content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u8BBE\u7F6E APIFOX_ACCESS_TOKEN \u73AF\u5883\u53D8\u91CF" }],
30317
30240
  isError: true
30318
30241
  };
30319
30242
  }
30320
- if (!authProjectId) {
30243
+ if (!projectId) {
30321
30244
  return {
30322
30245
  content: [{ type: "text", text: "\u9519\u8BEF: \u8BF7\u901A\u8FC7 --project-id \u53C2\u6570\u6307\u5B9A\u9879\u76EE ID" }],
30323
30246
  isError: true
30324
30247
  };
30325
30248
  }
30326
- const result = await fetchApifox(
30327
- `/v1/projects/${authProjectId}/export-openapi`,
30328
- authToken,
30329
- {
30330
- method: "POST",
30331
- body: {
30332
- scope: { type: "ALL" },
30333
- oasVersion: oasVersion || "3.1",
30334
- exportFormat: exportFormat || "JSON"
30335
- }
30336
- }
30337
- );
30338
- const format = exportFormat || "JSON";
30339
- let output;
30340
- if (format.toUpperCase() === "YAML") {
30341
- output = result.openapi || "";
30342
- } else {
30343
- output = JSON.stringify(result, null, 2);
30249
+ try {
30250
+ const apis = await fetchApifox(`/v1/projects/${projectId}/apis`, token);
30251
+ const text = apis.map((api) => `[${api.method?.toUpperCase() || "GET"}] ${api.path} - ${api.name}`).join("\n");
30252
+ console.error("\u83B7\u53D6 API \u5217\u8868\u6210\u529F\uFF0C\u6570\u91CF:", apis.length);
30253
+ return {
30254
+ content: [{ type: "text", text: text || "\u6682\u65E0 API" }]
30255
+ };
30256
+ } catch (error48) {
30257
+ console.error("\u83B7\u53D6 API \u5217\u8868\u9519\u8BEF:", error48);
30258
+ return {
30259
+ content: [{ type: "text", text: `\u83B7\u53D6\u5931\u8D25: ${error48 instanceof Error ? error48.message : String(error48)}` }],
30260
+ isError: true
30261
+ };
30344
30262
  }
30345
- return {
30346
- content: [{ type: "text", text: output }]
30347
- };
30348
30263
  }
30349
30264
  );
30350
30265
  async function main() {
30351
- if (!projectId) {
30352
- console.error("\u8B66\u544A: \u672A\u6307\u5B9A --project-id \u53C2\u6570");
30353
- }
30354
- if (!token) {
30355
- console.error("\u8B66\u544A: \u672A\u8BBE\u7F6E APIFOX_ACCESS_TOKEN \u73AF\u5883\u53D8\u91CF");
30356
- }
30266
+ console.error("MCP Server \u521D\u59CB\u5316\u5B8C\u6210\uFF0C\u7B49\u5F85\u8FDE\u63A5...");
30357
30267
  const transport = new StdioServerTransport();
30358
30268
  await server.connect(transport);
30359
30269
  }
package/dist/index.js CHANGED
@@ -1,15 +1,29 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
  import { z } from "zod";
4
+ console.error("LHW API MCP Server 启动中...");
4
5
  const APIFOX_BASE_URL = "https://api.apifox.com";
5
6
  const args = process.argv.slice(2);
6
7
  let projectId;
8
+ let token;
7
9
  for (let i = 0; i < args.length; i++) {
8
10
  if (args[i] === "--project-id" && args[i + 1]) {
9
11
  projectId = args[i + 1];
10
12
  }
13
+ else if (args[i].startsWith("--project-id=")) {
14
+ projectId = args[i].split("=")[1];
15
+ }
16
+ if (args[i] === "--token" && args[i + 1]) {
17
+ token = args[i + 1];
18
+ }
19
+ else if (args[i].startsWith("--token=")) {
20
+ token = args[i].split("=")[1];
21
+ }
11
22
  }
12
- const token = process.env.APIFOX_ACCESS_TOKEN;
23
+ token = token || process.env.APIFOX_ACCESS_TOKEN;
24
+ projectId = projectId || process.env.APIFOX_PROJECT_ID;
25
+ console.error("Project ID:", projectId || "未设置");
26
+ console.error("Token:", token ? "已设置" : "未设置");
13
27
  async function fetchApifox(endpoint, authToken, options) {
14
28
  const response = await fetch(`${APIFOX_BASE_URL}${endpoint}`, {
15
29
  method: options?.method || "GET",
@@ -31,190 +45,126 @@ const server = new McpServer({
31
45
  name: "lhwapi-mcp-server",
32
46
  version: "1.0.0",
33
47
  });
34
- server.registerTool("listProjects", {
35
- description: "获取 Apifox 项目列表",
48
+ server.registerTool("export_openapi", {
49
+ description: "导出项目的 OpenAPI (Swagger) 格式数据,支持 JSON 或 YAML 格式",
36
50
  inputSchema: z.object({
37
- token: z.string().optional().describe("Apifox 访问令牌 (可选,默认使用环境变量)"),
51
+ oasVersion: z.string().optional().describe("OpenAPI 版本: 3.0, 3.1, 2.0,默认 3.1"),
52
+ exportFormat: z.string().optional().describe("导出格式: JSON 或 YAML,默认 JSON"),
38
53
  }).shape,
39
- }, async ({ token: inputToken }) => {
40
- const authToken = inputToken || token;
41
- if (!authToken) {
54
+ }, async ({ oasVersion, exportFormat }) => {
55
+ console.error("调用 export_openapi 工具");
56
+ console.error("projectId:", projectId);
57
+ if (!token) {
42
58
  return {
43
- content: [{ type: "text", text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量或传入 token 参数" }],
59
+ content: [{ type: "text", text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量" }],
44
60
  isError: true,
45
61
  };
46
62
  }
47
- const projects = await fetchApifox("/v1/projects", authToken);
48
- const text = projects
49
- .map((p) => `项目: ${p.name} (ID: ${p.id})\n描述: ${p.description || "无"}`)
50
- .join("\n\n");
51
- return {
52
- content: [{ type: "text", text: text || "暂无项目" }],
53
- };
54
- });
55
- server.registerTool("listApis", {
56
- description: "获取指定项目下的 API 列表",
57
- inputSchema: z.object({
58
- projectId: z.string().optional().describe("项目 ID (可选,默认使用命令行参数)"),
59
- token: z.string().optional().describe("Apifox 访问令牌 (可选,默认使用环境变量)"),
60
- }).shape,
61
- }, async ({ projectId: inputProjectId, token: inputToken }) => {
62
- const authToken = inputToken || token;
63
- const authProjectId = inputProjectId || projectId;
64
- if (!authToken) {
63
+ if (!projectId) {
65
64
  return {
66
- content: [{ type: "text", text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量或传入 token 参数" }],
65
+ content: [{ type: "text", text: "错误: 请通过 --project-id 参数指定项目 ID" }],
67
66
  isError: true,
68
67
  };
69
68
  }
70
- if (!authProjectId) {
69
+ try {
70
+ const result = await fetchApifox(`/v1/projects/${projectId}/export-openapi`, token, {
71
+ method: "POST",
72
+ body: {
73
+ scope: { type: "ALL" },
74
+ oasVersion: oasVersion || "3.1",
75
+ exportFormat: exportFormat || "JSON",
76
+ },
77
+ });
78
+ const format = exportFormat || "JSON";
79
+ let output;
80
+ if (format.toUpperCase() === "YAML") {
81
+ output = result.openapi || "";
82
+ }
83
+ else {
84
+ output = JSON.stringify(result, null, 2);
85
+ }
86
+ console.error("导出成功");
71
87
  return {
72
- content: [{ type: "text", text: "错误: 请通过 --project-id 参数指定项目 ID" }],
88
+ content: [{ type: "text", text: output }],
89
+ };
90
+ }
91
+ catch (error) {
92
+ console.error("导出错误:", error);
93
+ return {
94
+ content: [{ type: "text", text: `导出失败: ${error instanceof Error ? error.message : String(error)}` }],
73
95
  isError: true,
74
96
  };
75
97
  }
76
- const apis = await fetchApifox(`/v1/projects/${authProjectId}/apis`, authToken);
77
- const text = apis
78
- .map((api) => `[${api.method.toUpperCase()}] ${api.path} - ${api.name}`)
79
- .join("\n");
80
- return {
81
- content: [{ type: "text", text: text || "暂无 API" }],
82
- };
83
98
  });
84
- server.registerTool("getApiDetail", {
85
- description: "获取单个 API 的详细信息",
86
- inputSchema: z.object({
87
- apiId: z.string().describe("API ID"),
88
- projectId: z.string().optional().describe("项目 ID (可选,默认使用命令行参数)"),
89
- token: z.string().optional().describe("Apifox 访问令牌 (可选,默认使用环境变量)"),
90
- }).shape,
91
- }, async ({ apiId, projectId: inputProjectId, token: inputToken }) => {
92
- const authToken = inputToken || token;
93
- const authProjectId = inputProjectId || projectId;
94
- if (!authToken) {
99
+ server.registerTool("refresh_oas", {
100
+ description: "刷新项目的 OpenAPI 缓存",
101
+ inputSchema: z.object({}).shape,
102
+ }, async () => {
103
+ console.error("调用 refresh_oas 工具");
104
+ if (!token) {
95
105
  return {
96
- content: [{ type: "text", text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量或传入 token 参数" }],
106
+ content: [{ type: "text", text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量" }],
97
107
  isError: true,
98
108
  };
99
109
  }
100
- if (!authProjectId) {
110
+ if (!projectId) {
101
111
  return {
102
112
  content: [{ type: "text", text: "错误: 请通过 --project-id 参数指定项目 ID" }],
103
113
  isError: true,
104
114
  };
105
115
  }
106
- const api = await fetchApifox(`/v1/projects/${authProjectId}/apis/${apiId}`, authToken);
107
- let detail = `# ${api.name}\n\n`;
108
- detail += `**方法**: ${api.method.toUpperCase()}\n`;
109
- detail += `**路径**: ${api.path}\n\n`;
110
- if (api.description) {
111
- detail += `## 描述\n\n${api.description}\n\n`;
112
- }
113
- if (api.requestParams?.query?.length) {
114
- detail += `## Query 参数\n\n`;
115
- api.requestParams.query.forEach((param) => {
116
- detail += `- ${param.name}: ${param.type || "string"} ${param.required ? "(必填)" : "(可选)"}\n`;
117
- });
118
- detail += "\n";
119
- }
120
- if (api.requestBody?.schema) {
121
- detail += `## 请求体\n\n\`\`\`json\n${JSON.stringify(api.requestBody.schema, null, 2)}\n\`\`\`\n\n`;
122
- }
123
- if (api.responseList?.length) {
124
- detail += `## 响应\n\n`;
125
- api.responseList.forEach((resp) => {
126
- detail += `### ${resp.statusCode}\n`;
127
- if (resp.responseBodySchema) {
128
- detail += `\`\`\`json\n${JSON.stringify(resp.responseBodySchema, null, 2)}\n\`\`\`\n`;
129
- }
130
- });
131
- }
132
- return {
133
- content: [{ type: "text", text: detail }],
134
- };
135
- });
136
- server.registerTool("searchApis", {
137
- description: "搜索 API",
138
- inputSchema: z.object({
139
- keyword: z.string().describe("搜索关键词"),
140
- projectId: z.string().optional().describe("项目 ID (可选,默认使用命令行参数)"),
141
- token: z.string().optional().describe("Apifox 访问令牌 (可选,默认使用环境变量)"),
142
- }).shape,
143
- }, async ({ keyword, projectId: inputProjectId, token: inputToken }) => {
144
- const authToken = inputToken || token;
145
- const authProjectId = inputProjectId || projectId;
146
- if (!authToken) {
116
+ try {
117
+ await fetchApifox(`/v1/projects/${projectId}/refresh-openapi-cache`, token, { method: "POST" });
118
+ console.error("刷新成功");
147
119
  return {
148
- content: [{ type: "text", text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量或传入 token 参数" }],
149
- isError: true,
120
+ content: [{ type: "text", text: "OpenAPI 缓存已刷新" }],
150
121
  };
151
122
  }
152
- if (!authProjectId) {
123
+ catch (error) {
124
+ console.error("刷新错误:", error);
153
125
  return {
154
- content: [{ type: "text", text: "错误: 请通过 --project-id 参数指定项目 ID" }],
126
+ content: [{ type: "text", text: `刷新失败: ${error instanceof Error ? error.message : String(error)}` }],
155
127
  isError: true,
156
128
  };
157
129
  }
158
- const apis = await fetchApifox(`/v1/projects/${authProjectId}/apis`, authToken);
159
- const filtered = apis.filter((api) => api.name.toLowerCase().includes(keyword.toLowerCase()) ||
160
- api.path.toLowerCase().includes(keyword.toLowerCase()));
161
- const text = filtered
162
- .map((api) => `[${api.method.toUpperCase()}] ${api.path} - ${api.name}`)
163
- .join("\n");
164
- return {
165
- content: [{ type: "text", text: text || "未找到匹配的 API" }],
166
- };
167
130
  });
168
- server.registerTool("exportOpenApi", {
169
- description: "导出 OpenAPI/Swagger 格式数据",
170
- inputSchema: z.object({
171
- oasVersion: z.string().optional().describe("OpenAPI 版本: 3.0, 3.1, 2.0"),
172
- exportFormat: z.string().optional().describe("导出格式: JSON 或 YAML"),
173
- projectId: z.string().optional().describe("项目 ID (可选,默认使用命令行参数)"),
174
- token: z.string().optional().describe("Apifox 访问令牌 (可选,默认使用环境变量)"),
175
- }).shape,
176
- }, async ({ oasVersion, exportFormat, projectId: inputProjectId, token: inputToken }) => {
177
- const authToken = inputToken || token;
178
- const authProjectId = inputProjectId || projectId;
179
- if (!authToken) {
131
+ server.registerTool("list_apis", {
132
+ description: "获取项目下的 API 接口列表",
133
+ inputSchema: z.object({}).shape,
134
+ }, async () => {
135
+ console.error("调用 list_apis 工具");
136
+ if (!token) {
180
137
  return {
181
- content: [{ type: "text", text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量或传入 token 参数" }],
138
+ content: [{ type: "text", text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量" }],
182
139
  isError: true,
183
140
  };
184
141
  }
185
- if (!authProjectId) {
142
+ if (!projectId) {
186
143
  return {
187
144
  content: [{ type: "text", text: "错误: 请通过 --project-id 参数指定项目 ID" }],
188
145
  isError: true,
189
146
  };
190
147
  }
191
- const result = await fetchApifox(`/v1/projects/${authProjectId}/export-openapi`, authToken, {
192
- method: "POST",
193
- body: {
194
- scope: { type: "ALL" },
195
- oasVersion: oasVersion || "3.1",
196
- exportFormat: exportFormat || "JSON",
197
- },
198
- });
199
- const format = exportFormat || "JSON";
200
- let output;
201
- if (format.toUpperCase() === "YAML") {
202
- output = result.openapi || "";
148
+ try {
149
+ const apis = await fetchApifox(`/v1/projects/${projectId}/apis`, token);
150
+ const text = apis
151
+ .map((api) => `[${api.method?.toUpperCase() || 'GET'}] ${api.path} - ${api.name}`)
152
+ .join("\n");
153
+ console.error("获取 API 列表成功,数量:", apis.length);
154
+ return {
155
+ content: [{ type: "text", text: text || "暂无 API" }],
156
+ };
203
157
  }
204
- else {
205
- output = JSON.stringify(result, null, 2);
158
+ catch (error) {
159
+ console.error("获取 API 列表错误:", error);
160
+ return {
161
+ content: [{ type: "text", text: `获取失败: ${error instanceof Error ? error.message : String(error)}` }],
162
+ isError: true,
163
+ };
206
164
  }
207
- return {
208
- content: [{ type: "text", text: output }],
209
- };
210
165
  });
211
166
  async function main() {
212
- if (!projectId) {
213
- console.error("警告: 未指定 --project-id 参数");
214
- }
215
- if (!token) {
216
- console.error("警告: 未设置 APIFOX_ACCESS_TOKEN 环境变量");
217
- }
167
+ console.error("MCP Server 初始化完成,等待连接...");
218
168
  const transport = new StdioServerTransport();
219
169
  await server.connect(transport);
220
170
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lhwapi-mcp-server",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "MCP server for API documentation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/index.ts CHANGED
@@ -2,48 +2,32 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
  import { z } from "zod";
4
4
 
5
+ console.error("LHW API MCP Server 启动中...");
6
+
5
7
  const APIFOX_BASE_URL = "https://api.apifox.com";
6
8
 
7
9
  const args = process.argv.slice(2);
8
10
  let projectId: string | undefined;
11
+ let token: string | undefined;
12
+
9
13
  for (let i = 0; i < args.length; i++) {
10
14
  if (args[i] === "--project-id" && args[i + 1]) {
11
15
  projectId = args[i + 1];
16
+ } else if (args[i].startsWith("--project-id=")) {
17
+ projectId = args[i].split("=")[1];
18
+ }
19
+ if (args[i] === "--token" && args[i + 1]) {
20
+ token = args[i + 1];
21
+ } else if (args[i].startsWith("--token=")) {
22
+ token = args[i].split("=")[1];
12
23
  }
13
24
  }
14
25
 
15
- const token = process.env.APIFOX_ACCESS_TOKEN;
16
-
17
- interface ApifoxResponse<T> {
18
- data: T;
19
- message?: string;
20
- }
21
-
22
- interface Project {
23
- id: string;
24
- name: string;
25
- description?: string;
26
- }
26
+ token = token || process.env.APIFOX_ACCESS_TOKEN;
27
+ projectId = projectId || process.env.APIFOX_PROJECT_ID;
27
28
 
28
- interface ApiDetail {
29
- id: string;
30
- name: string;
31
- path: string;
32
- method: string;
33
- description?: string;
34
- requestParams?: {
35
- query?: any[];
36
- path?: any[];
37
- header?: any[];
38
- };
39
- requestBody?: {
40
- schema?: any;
41
- };
42
- responseList?: {
43
- statusCode: number;
44
- responseBodySchema?: any;
45
- }[];
46
- }
29
+ console.error("Project ID:", projectId || "未设置");
30
+ console.error("Token:", token ? "已设置" : "未设置");
47
31
 
48
32
  async function fetchApifox<T>(endpoint: string, authToken: string, options?: {
49
33
  method?: string;
@@ -64,7 +48,7 @@ async function fetchApifox<T>(endpoint: string, authToken: string, options?: {
64
48
  throw new Error(`Apifox API error: ${response.status} - ${error}`);
65
49
  }
66
50
 
67
- const data = await response.json() as ApifoxResponse<T>;
51
+ const data = await response.json() as { data: T };
68
52
  return data.data;
69
53
  }
70
54
 
@@ -74,256 +58,155 @@ const server = new McpServer({
74
58
  });
75
59
 
76
60
  server.registerTool(
77
- "listProjects",
61
+ "export_openapi",
78
62
  {
79
- description: "获取 Apifox 项目列表",
63
+ description: "导出项目的 OpenAPI (Swagger) 格式数据,支持 JSON 或 YAML 格式",
80
64
  inputSchema: z.object({
81
- token: z.string().optional().describe("Apifox 访问令牌 (可选,默认使用环境变量)"),
65
+ oasVersion: z.string().optional().describe("OpenAPI 版本: 3.0, 3.1, 2.0,默认 3.1"),
66
+ exportFormat: z.string().optional().describe("导出格式: JSON 或 YAML,默认 JSON"),
82
67
  }).shape,
83
68
  },
84
- async ({ token: inputToken }: { token?: string }) => {
85
- const authToken = inputToken || token;
86
- if (!authToken) {
87
- return {
88
- content: [{ type: "text" as const, text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量或传入 token 参数" }],
89
- isError: true,
90
- };
91
- }
92
- const projects = await fetchApifox<Project[]>("/v1/projects", authToken);
93
- const text = projects
94
- .map((p) => `项目: ${p.name} (ID: ${p.id})\n描述: ${p.description || "无"}`)
95
- .join("\n\n");
96
- return {
97
- content: [{ type: "text" as const, text: text || "暂无项目" }],
98
- };
99
- }
100
- );
101
-
102
- server.registerTool(
103
- "listApis",
104
- {
105
- description: "获取指定项目下的 API 列表",
106
- inputSchema: z.object({
107
- projectId: z.string().optional().describe("项目 ID (可选,默认使用命令行参数)"),
108
- token: z.string().optional().describe("Apifox 访问令牌 (可选,默认使用环境变量)"),
109
- }).shape,
110
- },
111
- async ({ projectId: inputProjectId, token: inputToken }: { projectId?: string; token?: string }) => {
112
- const authToken = inputToken || token;
113
- const authProjectId = inputProjectId || projectId;
69
+ async ({ oasVersion, exportFormat }: {
70
+ oasVersion?: string;
71
+ exportFormat?: string;
72
+ }) => {
73
+ console.error("调用 export_openapi 工具");
74
+ console.error("projectId:", projectId);
114
75
 
115
- if (!authToken) {
76
+ if (!token) {
116
77
  return {
117
- content: [{ type: "text" as const, text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量或传入 token 参数" }],
78
+ content: [{ type: "text" as const, text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量" }],
118
79
  isError: true,
119
80
  };
120
81
  }
121
- if (!authProjectId) {
82
+ if (!projectId) {
122
83
  return {
123
84
  content: [{ type: "text" as const, text: "错误: 请通过 --project-id 参数指定项目 ID" }],
124
85
  isError: true,
125
86
  };
126
87
  }
127
88
 
128
- const apis = await fetchApifox<ApiDetail[]>(
129
- `/v1/projects/${authProjectId}/apis`,
130
- authToken
131
- );
132
- const text = apis
133
- .map((api) => `[${api.method.toUpperCase()}] ${api.path} - ${api.name}`)
134
- .join("\n");
135
- return {
136
- content: [{ type: "text" as const, text: text || "暂无 API" }],
137
- };
138
- }
139
- );
89
+ try {
90
+ const result = await fetchApifox<any>(
91
+ `/v1/projects/${projectId}/export-openapi`,
92
+ token,
93
+ {
94
+ method: "POST",
95
+ body: {
96
+ scope: { type: "ALL" },
97
+ oasVersion: oasVersion || "3.1",
98
+ exportFormat: exportFormat || "JSON",
99
+ },
100
+ }
101
+ );
102
+
103
+ const format = exportFormat || "JSON";
104
+ let output: string;
105
+ if (format.toUpperCase() === "YAML") {
106
+ output = result.openapi || "";
107
+ } else {
108
+ output = JSON.stringify(result, null, 2);
109
+ }
140
110
 
141
- server.registerTool(
142
- "getApiDetail",
143
- {
144
- description: "获取单个 API 的详细信息",
145
- inputSchema: z.object({
146
- apiId: z.string().describe("API ID"),
147
- projectId: z.string().optional().describe("项目 ID (可选,默认使用命令行参数)"),
148
- token: z.string().optional().describe("Apifox 访问令牌 (可选,默认使用环境变量)"),
149
- }).shape,
150
- },
151
- async ({ apiId, projectId: inputProjectId, token: inputToken }: { apiId: string; projectId?: string; token?: string }) => {
152
- const authToken = inputToken || token;
153
- const authProjectId = inputProjectId || projectId;
154
-
155
- if (!authToken) {
111
+ console.error("导出成功");
156
112
  return {
157
- content: [{ type: "text" as const, text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量或传入 token 参数" }],
158
- isError: true,
113
+ content: [{ type: "text" as const, text: output }],
159
114
  };
160
- }
161
- if (!authProjectId) {
115
+ } catch (error) {
116
+ console.error("导出错误:", error);
162
117
  return {
163
- content: [{ type: "text" as const, text: "错误: 请通过 --project-id 参数指定项目 ID" }],
118
+ content: [{ type: "text" as const, text: `导出失败: ${error instanceof Error ? error.message : String(error)}` }],
164
119
  isError: true,
165
120
  };
166
121
  }
167
-
168
- const api = await fetchApifox<ApiDetail>(
169
- `/v1/projects/${authProjectId}/apis/${apiId}`,
170
- authToken
171
- );
172
-
173
- let detail = `# ${api.name}\n\n`;
174
- detail += `**方法**: ${api.method.toUpperCase()}\n`;
175
- detail += `**路径**: ${api.path}\n\n`;
176
-
177
- if (api.description) {
178
- detail += `## 描述\n\n${api.description}\n\n`;
179
- }
180
-
181
- if (api.requestParams?.query?.length) {
182
- detail += `## Query 参数\n\n`;
183
- api.requestParams.query.forEach((param: any) => {
184
- detail += `- ${param.name}: ${param.type || "string"} ${
185
- param.required ? "(必填)" : "(可选)"
186
- }\n`;
187
- });
188
- detail += "\n";
189
- }
190
-
191
- if (api.requestBody?.schema) {
192
- detail += `## 请求体\n\n\`\`\`json\n${JSON.stringify(api.requestBody.schema, null, 2)}\n\`\`\`\n\n`;
193
- }
194
-
195
- if (api.responseList?.length) {
196
- detail += `## 响应\n\n`;
197
- api.responseList.forEach((resp) => {
198
- detail += `### ${resp.statusCode}\n`;
199
- if (resp.responseBodySchema) {
200
- detail += `\`\`\`json\n${JSON.stringify(resp.responseBodySchema, null, 2)}\n\`\`\`\n`;
201
- }
202
- });
203
- }
204
-
205
- return {
206
- content: [{ type: "text" as const, text: detail }],
207
- };
208
122
  }
209
123
  );
210
124
 
211
125
  server.registerTool(
212
- "searchApis",
126
+ "refresh_oas",
213
127
  {
214
- description: "搜索 API",
215
- inputSchema: z.object({
216
- keyword: z.string().describe("搜索关键词"),
217
- projectId: z.string().optional().describe("项目 ID (可选,默认使用命令行参数)"),
218
- token: z.string().optional().describe("Apifox 访问令牌 (可选,默认使用环境变量)"),
219
- }).shape,
128
+ description: "刷新项目的 OpenAPI 缓存",
129
+ inputSchema: z.object({}).shape,
220
130
  },
221
- async ({ keyword, projectId: inputProjectId, token: inputToken }: { keyword: string; projectId?: string; token?: string }) => {
222
- const authToken = inputToken || token;
223
- const authProjectId = inputProjectId || projectId;
131
+ async () => {
132
+ console.error("调用 refresh_oas 工具");
224
133
 
225
- if (!authToken) {
134
+ if (!token) {
226
135
  return {
227
- content: [{ type: "text" as const, text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量或传入 token 参数" }],
136
+ content: [{ type: "text" as const, text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量" }],
228
137
  isError: true,
229
138
  };
230
139
  }
231
- if (!authProjectId) {
140
+ if (!projectId) {
232
141
  return {
233
142
  content: [{ type: "text" as const, text: "错误: 请通过 --project-id 参数指定项目 ID" }],
234
143
  isError: true,
235
144
  };
236
145
  }
237
146
 
238
- const apis = await fetchApifox<ApiDetail[]>(
239
- `/v1/projects/${authProjectId}/apis`,
240
- authToken
241
- );
242
-
243
- const filtered = apis.filter(
244
- (api) =>
245
- api.name.toLowerCase().includes(keyword.toLowerCase()) ||
246
- api.path.toLowerCase().includes(keyword.toLowerCase())
247
- );
248
-
249
- const text = filtered
250
- .map((api) => `[${api.method.toUpperCase()}] ${api.path} - ${api.name}`)
251
- .join("\n");
252
-
253
- return {
254
- content: [{ type: "text" as const, text: text || "未找到匹配的 API" }],
255
- };
147
+ try {
148
+ await fetchApifox<any>(
149
+ `/v1/projects/${projectId}/refresh-openapi-cache`,
150
+ token,
151
+ { method: "POST" }
152
+ );
153
+ console.error("刷新成功");
154
+ return {
155
+ content: [{ type: "text" as const, text: "OpenAPI 缓存已刷新" }],
156
+ };
157
+ } catch (error) {
158
+ console.error("刷新错误:", error);
159
+ return {
160
+ content: [{ type: "text" as const, text: `刷新失败: ${error instanceof Error ? error.message : String(error)}` }],
161
+ isError: true,
162
+ };
163
+ }
256
164
  }
257
165
  );
258
166
 
259
167
  server.registerTool(
260
- "exportOpenApi",
168
+ "list_apis",
261
169
  {
262
- description: "导出 OpenAPI/Swagger 格式数据",
263
- inputSchema: z.object({
264
- oasVersion: z.string().optional().describe("OpenAPI 版本: 3.0, 3.1, 2.0"),
265
- exportFormat: z.string().optional().describe("导出格式: JSON 或 YAML"),
266
- projectId: z.string().optional().describe("项目 ID (可选,默认使用命令行参数)"),
267
- token: z.string().optional().describe("Apifox 访问令牌 (可选,默认使用环境变量)"),
268
- }).shape,
170
+ description: "获取项目下的 API 接口列表",
171
+ inputSchema: z.object({}).shape,
269
172
  },
270
- async ({ oasVersion, exportFormat, projectId: inputProjectId, token: inputToken }: {
271
- oasVersion?: string;
272
- exportFormat?: string;
273
- projectId?: string;
274
- token?: string
275
- }) => {
276
- const authToken = inputToken || token;
277
- const authProjectId = inputProjectId || projectId;
173
+ async () => {
174
+ console.error("调用 list_apis 工具");
278
175
 
279
- if (!authToken) {
176
+ if (!token) {
280
177
  return {
281
- content: [{ type: "text" as const, text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量或传入 token 参数" }],
178
+ content: [{ type: "text" as const, text: "错误: 请设置 APIFOX_ACCESS_TOKEN 环境变量" }],
282
179
  isError: true,
283
180
  };
284
181
  }
285
- if (!authProjectId) {
182
+ if (!projectId) {
286
183
  return {
287
184
  content: [{ type: "text" as const, text: "错误: 请通过 --project-id 参数指定项目 ID" }],
288
185
  isError: true,
289
186
  };
290
187
  }
291
188
 
292
- const result = await fetchApifox<any>(
293
- `/v1/projects/${authProjectId}/export-openapi`,
294
- authToken,
295
- {
296
- method: "POST",
297
- body: {
298
- scope: { type: "ALL" },
299
- oasVersion: oasVersion || "3.1",
300
- exportFormat: exportFormat || "JSON",
301
- },
302
- }
303
- );
304
-
305
- const format = exportFormat || "JSON";
306
- let output: string;
307
- if (format.toUpperCase() === "YAML") {
308
- output = result.openapi || "";
309
- } else {
310
- output = JSON.stringify(result, null, 2);
189
+ try {
190
+ const apis = await fetchApifox<any[]>(`/v1/projects/${projectId}/apis`, token);
191
+ const text = apis
192
+ .map((api) => `[${api.method?.toUpperCase() || 'GET'}] ${api.path} - ${api.name}`)
193
+ .join("\n");
194
+ console.error("获取 API 列表成功,数量:", apis.length);
195
+ return {
196
+ content: [{ type: "text" as const, text: text || "暂无 API" }],
197
+ };
198
+ } catch (error) {
199
+ console.error("获取 API 列表错误:", error);
200
+ return {
201
+ content: [{ type: "text" as const, text: `获取失败: ${error instanceof Error ? error.message : String(error)}` }],
202
+ isError: true,
203
+ };
311
204
  }
312
-
313
- return {
314
- content: [{ type: "text" as const, text: output }],
315
- };
316
205
  }
317
206
  );
318
207
 
319
208
  async function main() {
320
- if (!projectId) {
321
- console.error("警告: 未指定 --project-id 参数");
322
- }
323
- if (!token) {
324
- console.error("警告: 未设置 APIFOX_ACCESS_TOKEN 环境变量");
325
- }
326
-
209
+ console.error("MCP Server 初始化完成,等待连接...");
327
210
  const transport = new StdioServerTransport();
328
211
  await server.connect(transport);
329
212
  }