apifox-workspace-mcp 1.1.2 → 1.1.4
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 +1 -1
- package/dist/__tests__/intent.test.js.map +1 -1
- package/dist/__tests__/llms-parser.test.js.map +1 -1
- package/dist/__tests__/select-interfaces.test.js +2 -0
- package/dist/__tests__/select-interfaces.test.js.map +1 -1
- package/dist/__tests__/unified-cache-manager.test.js +2 -2
- package/dist/__tests__/unified-cache-manager.test.js.map +1 -1
- package/dist/core/cache/unified-cache-manager.d.ts +12 -3
- package/dist/core/cache/unified-cache-manager.d.ts.map +1 -1
- package/dist/core/cache/unified-cache-manager.js +97 -24
- package/dist/core/cache/unified-cache-manager.js.map +1 -1
- package/dist/core/client/apifox.js.map +1 -1
- package/dist/core/client/mcp-bridge.d.ts.map +1 -1
- package/dist/core/client/mcp-bridge.js.map +1 -1
- package/dist/core/config/manager.d.ts +6 -124
- package/dist/core/config/manager.d.ts.map +1 -1
- package/dist/core/config/manager.js +11 -288
- package/dist/core/config/manager.js.map +1 -1
- package/dist/core/generator/artifact.js +0 -1
- package/dist/core/generator/artifact.js.map +1 -1
- package/dist/core/intent.d.ts +3 -0
- package/dist/core/intent.d.ts.map +1 -1
- package/dist/core/intent.js +24 -1
- package/dist/core/intent.js.map +1 -1
- package/dist/core/parser/index.d.ts +1 -0
- package/dist/core/parser/index.d.ts.map +1 -1
- package/dist/core/parser/index.js +1 -0
- package/dist/core/parser/index.js.map +1 -1
- package/dist/core/parser/md-parser.d.ts +12 -0
- package/dist/core/parser/md-parser.d.ts.map +1 -0
- package/dist/core/parser/md-parser.js +100 -0
- package/dist/core/parser/md-parser.js.map +1 -0
- package/dist/server/handlers/assistant.d.ts.map +1 -1
- package/dist/server/handlers/assistant.js +3 -0
- package/dist/server/handlers/assistant.js.map +1 -1
- package/dist/server/handlers/get-interface-detail.d.ts +2 -0
- package/dist/server/handlers/get-interface-detail.d.ts.map +1 -1
- package/dist/server/handlers/get-interface-detail.js +83 -2
- package/dist/server/handlers/get-interface-detail.js.map +1 -1
- package/dist/server/handlers/list-projects.d.ts.map +1 -1
- package/dist/server/handlers/list-projects.js.map +1 -1
- package/dist/server/handlers/parse-and-add-project.d.ts +0 -1
- package/dist/server/handlers/parse-and-add-project.d.ts.map +1 -1
- package/dist/server/handlers/parse-and-add-project.js +104 -132
- package/dist/server/handlers/parse-and-add-project.js.map +1 -1
- package/dist/server/handlers/utils.d.ts +3 -2
- package/dist/server/handlers/utils.d.ts.map +1 -1
- package/dist/server/handlers/utils.js +10 -3
- package/dist/server/handlers/utils.js.map +1 -1
- package/dist/server/index.js +13 -33
- package/dist/server/index.js.map +1 -1
- package/dist/types/index.d.ts +6 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown 接口文档解析器
|
|
3
|
+
* 从接口的 md 文件中解析接口详情
|
|
4
|
+
*/
|
|
5
|
+
import axios from 'axios';
|
|
6
|
+
/**
|
|
7
|
+
* 从接口 md 文件读取接口详情
|
|
8
|
+
* @param docUrl 接口 md 文件的 URL
|
|
9
|
+
* @returns 接口详情
|
|
10
|
+
*/
|
|
11
|
+
export async function parseInterfaceFromMd(docUrl) {
|
|
12
|
+
try {
|
|
13
|
+
// 确保 URL 以 .md 结尾
|
|
14
|
+
const normalizedUrl = docUrl.endsWith('.md') ? docUrl : `${docUrl}.md`;
|
|
15
|
+
// 获取 md 文件内容
|
|
16
|
+
const response = await axios.get(normalizedUrl, { timeout: 10000 });
|
|
17
|
+
const content = typeof response.data === 'string' ? response.data : String(response.data);
|
|
18
|
+
// 解析接口详情
|
|
19
|
+
const detail = parseMdContent(content, normalizedUrl);
|
|
20
|
+
return detail;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
throw new Error(`从 md 文件读取接口详情失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 解析 md 文件内容,提取接口详情
|
|
28
|
+
* @param content md 文件内容
|
|
29
|
+
* @param docUrl md 文件 URL(用于提取接口 ID)
|
|
30
|
+
* @returns 接口详情
|
|
31
|
+
*/
|
|
32
|
+
function parseMdContent(content, docUrl) {
|
|
33
|
+
// 从 URL 中提取接口 ID
|
|
34
|
+
const idMatch = docUrl.match(/api-(\d+)\.md/);
|
|
35
|
+
const interfaceId = idMatch ? idMatch[1] : '';
|
|
36
|
+
// 提取接口名称(从标题或第一个 # 标题)
|
|
37
|
+
const titleMatch = content.match(/^#+\s+(.+)$/m);
|
|
38
|
+
const name = titleMatch ? titleMatch[1].trim() : '未命名接口';
|
|
39
|
+
// 提取方法(从 x-run-in-apifox 或路径中)
|
|
40
|
+
let method = 'GET';
|
|
41
|
+
const methodMatch = content.match(/method:\s*(\w+)/i) ||
|
|
42
|
+
content.match(/(?:GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD)\s+/i);
|
|
43
|
+
if (methodMatch) {
|
|
44
|
+
method = methodMatch[1]?.toUpperCase() || methodMatch[0].trim().toUpperCase();
|
|
45
|
+
}
|
|
46
|
+
// 提取路径
|
|
47
|
+
let path = '/';
|
|
48
|
+
const pathMatch = content.match(/path:\s*(.+)/i) || content.match(/\/api\/[^\s\)]+/);
|
|
49
|
+
if (pathMatch) {
|
|
50
|
+
path = pathMatch[1]?.trim() || pathMatch[0].trim();
|
|
51
|
+
}
|
|
52
|
+
// 提取描述(从第一个段落或 description 字段)
|
|
53
|
+
let description;
|
|
54
|
+
const descMatch = content.match(/description:\s*(.+)/i) || content.match(/^([^#\n]+)/m);
|
|
55
|
+
if (descMatch) {
|
|
56
|
+
description = descMatch[1]?.trim();
|
|
57
|
+
}
|
|
58
|
+
// 提取请求参数(从 request 部分或 JSON Schema)
|
|
59
|
+
let request;
|
|
60
|
+
const requestMatch = content.match(/##\s+请求[参数]*[\s\S]*?```(?:json|typescript)?\s*([\s\S]*?)```/i);
|
|
61
|
+
if (requestMatch) {
|
|
62
|
+
try {
|
|
63
|
+
const requestData = JSON.parse(requestMatch[1]);
|
|
64
|
+
request = {
|
|
65
|
+
body: {
|
|
66
|
+
json: requestData,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// 解析失败,忽略
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// 提取响应参数(从 response 部分或 JSON Schema)
|
|
75
|
+
let response;
|
|
76
|
+
const responseMatch = content.match(/##\s+响应[示例]*[\s\S]*?```(?:json|typescript)?\s*([\s\S]*?)```/i);
|
|
77
|
+
if (responseMatch) {
|
|
78
|
+
try {
|
|
79
|
+
const responseData = JSON.parse(responseMatch[1]);
|
|
80
|
+
response = {
|
|
81
|
+
body: {
|
|
82
|
+
json: responseData,
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// 解析失败,忽略
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
id: interfaceId,
|
|
92
|
+
name,
|
|
93
|
+
method,
|
|
94
|
+
path,
|
|
95
|
+
description,
|
|
96
|
+
request,
|
|
97
|
+
response,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=md-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md-parser.js","sourceRoot":"","sources":["../../../src/core/parser/md-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/assistant.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,SAAS,EACT,YAAY,EAGb,MAAM,qBAAqB,CAAC;AAQ7B,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,gBAAgB;;;;;
|
|
1
|
+
{"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/assistant.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,SAAS,EACT,YAAY,EAGb,MAAM,qBAAqB,CAAC;AAQ7B,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,gBAAgB;;;;;GAmF/E"}
|
|
@@ -35,7 +35,10 @@ export async function handleAssistant(args, ctx) {
|
|
|
35
35
|
}
|
|
36
36
|
return handleGetInterfaceDetail({
|
|
37
37
|
projectName: intent.projectName ?? lastProject?.projectName,
|
|
38
|
+
projectId: intent.projectId,
|
|
39
|
+
shareId: intent.shareId,
|
|
38
40
|
interfaceId: targetId,
|
|
41
|
+
url: intent.url,
|
|
39
42
|
}, { projectRoot, configManager, mcpBridge, contextStore });
|
|
40
43
|
}
|
|
41
44
|
case 'generateArtifacts': {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant.js","sourceRoot":"","sources":["../../../src/server/handlers/assistant.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,WAAW,GAEZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAa/C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAmB,EAAE,GAAqB;IAC9E,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,GAAG,CAAC;IAEpE,MAAM,WAAW,GAAG,YAAY,CAAC,cAAc,EAAE,CAAC;IAClD,MAAM,QAAQ,GAAG,YAAY,CAAC,oBAAoB,EAAE,CAAC;IAErD,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE;QACtC,eAAe,EAAE,WAAW,EAAE,WAAW;QACzC,sBAAsB,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;KAChE,CAAC,CAAC;IAEH,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,cAAc;YACjB,OAAO,kBAAkB,CAAC,WAAW,CAAC,CAAC;QAEzC,KAAK,kBAAkB;YACrB,OAAO,qBAAqB,CAC1B;gBACE,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,WAAW,EAAE,WAAW;gBAC3D,OAAO,EAAE,MAAM,CAAC,OAAO;aACxB,EACD,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,CACxD,CAAC;QAEJ,KAAK,oBAAoB,CAAC,CAAC,CAAC;YAC1B,IAAI,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC;YAClC,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,UAAU,IAAI,QAAQ,EAAE,CAAC;gBAC/C,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CACxC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAW,CAAC,WAAW,EAAE,CAAC,CACnE,CAAC;gBACF,QAAQ,GAAG,KAAK,EAAE,EAAE,CAAC;YACvB,CAAC;YACD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,iBAAiB,CAAC,2BAA2B,CAAC,CAAC;YACxD,CAAC;YACD,OAAO,wBAAwB,CAC7B;gBACE,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,WAAW,EAAE,WAAW;gBAC3D,WAAW,EAAE,QAAQ;
|
|
1
|
+
{"version":3,"file":"assistant.js","sourceRoot":"","sources":["../../../src/server/handlers/assistant.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,9 @@ import { ConfigManager, McpBridge, ContextStore } from '../../core/index.js';
|
|
|
2
2
|
export interface GetInterfaceDetailArgs {
|
|
3
3
|
projectName?: string;
|
|
4
4
|
projectId?: string;
|
|
5
|
+
shareId?: string;
|
|
5
6
|
interfaceId: string;
|
|
7
|
+
url?: string;
|
|
6
8
|
}
|
|
7
9
|
export interface GetInterfaceDetailContext {
|
|
8
10
|
projectRoot: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-interface-detail.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/get-interface-detail.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"get-interface-detail.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/get-interface-detail.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,SAAS,EACT,YAAY,EAMb,MAAM,qBAAqB,CAAC;AAS7B,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,sBAAsB,EAC5B,GAAG,EAAE,yBAAyB;;;;;;;;;;;;GA8K/B"}
|
|
@@ -1,14 +1,95 @@
|
|
|
1
|
-
import { generateArtifact } from '../../core/index.js';
|
|
1
|
+
import { generateArtifact, UnifiedCacheManager, parseApifoxUrl, parseInterfaceFromMd, fetchAndParseLlms, } from '../../core/index.js';
|
|
2
2
|
import { resolveProjectInfo, buildTextResponse, buildMissingTokenResponse, buildCurlSnippet, buildFetchSnippet, } from './utils.js';
|
|
3
3
|
/**
|
|
4
4
|
* 处理获取接口详情请求
|
|
5
5
|
*/
|
|
6
6
|
export async function handleGetInterfaceDetail(args, ctx) {
|
|
7
7
|
const { projectRoot, configManager, mcpBridge, contextStore } = ctx;
|
|
8
|
-
const
|
|
8
|
+
const cacheManager = new UnifiedCacheManager(projectRoot);
|
|
9
|
+
let projectInfo = resolveProjectInfo(projectRoot, contextStore, args.projectName, args.projectId, args.shareId);
|
|
10
|
+
// 如果提供了 URL,尝试从 URL 解析项目信息
|
|
11
|
+
if (!projectInfo && args.url) {
|
|
12
|
+
const parsed = await parseApifoxUrl(args.url);
|
|
13
|
+
if (parsed && parsed.interfaceId === args.interfaceId) {
|
|
14
|
+
// 检查缓存中是否有该 shareId 对应的项目
|
|
15
|
+
let cachedProject = parsed.shareId ? cacheManager.findProjectByShareId(parsed.shareId) : null;
|
|
16
|
+
if (!cachedProject && parsed.llmsUrl) {
|
|
17
|
+
// 如果缓存中没有,从 llms.txt 解析并缓存
|
|
18
|
+
try {
|
|
19
|
+
const interfaces = await fetchAndParseLlms(parsed.llmsUrl);
|
|
20
|
+
// 如果无法获取真实项目名称,使用 ${shareId}-${projectId} 作为后备
|
|
21
|
+
const projectName = parsed.projectName ||
|
|
22
|
+
(parsed.shareId ? `${parsed.shareId}-${parsed.projectId}` : parsed.projectId);
|
|
23
|
+
// 保存项目元数据和接口列表
|
|
24
|
+
cacheManager.upsertProjectMetadata(projectName, parsed.projectId, parsed.llmsUrl, parsed.shareId);
|
|
25
|
+
cacheManager.updateInterfacesFromLlms(projectName, interfaces);
|
|
26
|
+
cachedProject = cacheManager.findProjectByShareId(parsed.shareId) || null;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return buildTextResponse(`解析项目信息失败: ${error instanceof Error ? error.message : String(error)}`, true);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (cachedProject) {
|
|
33
|
+
projectInfo = {
|
|
34
|
+
projectId: cachedProject.projectId,
|
|
35
|
+
projectName: cachedProject.projectName,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
else if (parsed.projectId) {
|
|
39
|
+
// 如果无法获取真实项目名称,使用 ${shareId}-${projectId} 作为后备
|
|
40
|
+
const projectName = parsed.projectName ||
|
|
41
|
+
(parsed.shareId ? `${parsed.shareId}-${parsed.projectId}` : parsed.projectId);
|
|
42
|
+
projectInfo = {
|
|
43
|
+
projectId: parsed.projectId,
|
|
44
|
+
projectName,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
9
49
|
if (!projectInfo) {
|
|
10
50
|
return buildTextResponse('我需要知道项目名称或 ID 才能查看接口详情。');
|
|
11
51
|
}
|
|
52
|
+
// 优先从缓存的 md 文件读取接口详情
|
|
53
|
+
const cachedInterface = cacheManager.findInterface(projectInfo.projectName, args.interfaceId);
|
|
54
|
+
if (cachedInterface && cachedInterface.docUrl) {
|
|
55
|
+
try {
|
|
56
|
+
const detail = await parseInterfaceFromMd(cachedInterface.docUrl);
|
|
57
|
+
if (detail) {
|
|
58
|
+
contextStore.setLastProject(projectInfo.projectName, projectInfo.projectId);
|
|
59
|
+
const requestJson = JSON.stringify(detail.request || {}, null, 2);
|
|
60
|
+
const responseJson = JSON.stringify(detail.response || {}, null, 2);
|
|
61
|
+
const tsArtifact = generateArtifact('ts_types', {
|
|
62
|
+
interfaceDetail: detail,
|
|
63
|
+
});
|
|
64
|
+
const curlSnippet = buildCurlSnippet(detail);
|
|
65
|
+
const fetchSnippet = buildFetchSnippet(detail);
|
|
66
|
+
const description = detail.description ? `\n- 描述: ${detail.description}` : '';
|
|
67
|
+
const text = `**${detail.name || '未命名接口'}**\n` +
|
|
68
|
+
`- 方法: ${detail.method || 'N/A'}\n` +
|
|
69
|
+
`- 路径: ${detail.path || 'N/A'}\n` +
|
|
70
|
+
`- ID: ${detail.id}\n` +
|
|
71
|
+
`${description}\n\n` +
|
|
72
|
+
`### 请求参数\n\`\`\`json\n${requestJson}\n\`\`\`\n\n` +
|
|
73
|
+
`### 响应示例\n\`\`\`json\n${responseJson}\n\`\`\`\n\n` +
|
|
74
|
+
`### curl 示例\n\`\`\`bash\n${curlSnippet}\n\`\`\`\n\n` +
|
|
75
|
+
`### fetch 示例\n\`\`\`ts\n${fetchSnippet}\n\`\`\`\n\n` +
|
|
76
|
+
`### TypeScript 类型草稿\n\`\`\`ts\n${tsArtifact.content}\n\`\`\`\n\n` +
|
|
77
|
+
`如果需要,我还能继续为你生成 Mock 数据或请求封装。`;
|
|
78
|
+
return {
|
|
79
|
+
content: [
|
|
80
|
+
{
|
|
81
|
+
type: 'text',
|
|
82
|
+
text,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// 如果从 md 文件读取失败,继续使用 API 方式
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Fallback: 使用 API 方式获取接口详情
|
|
12
93
|
const accessToken = configManager.getAccessToken();
|
|
13
94
|
if (!accessToken) {
|
|
14
95
|
return buildMissingTokenResponse();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-interface-detail.js","sourceRoot":"","sources":["../../../src/server/handlers/get-interface-detail.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"get-interface-detail.js","sourceRoot":"","sources":["../../../src/server/handlers/get-interface-detail.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-projects.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/list-projects.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"list-projects.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/list-projects.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM;;;;;;GAY3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-projects.js","sourceRoot":"","sources":["../../../src/server/handlers/list-projects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"list-projects.js","sourceRoot":"","sources":["../../../src/server/handlers/list-projects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,WAAmB;IAC1D,MAAM,YAAY,GAAG,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,EAAE,CAAC;IAE7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,kBAAkB,CACvB,0DAA0D,CAC3D,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/E,OAAO,kBAAkB,CAAC,WAAW,QAAQ,CAAC,MAAM,oBAAoB,WAAW,EAAE,CAAC,CAAC;AACzF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-and-add-project.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/parse-and-add-project.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,SAAS,EAKT,YAAY,EAGb,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"parse-and-add-project.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/parse-and-add-project.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,SAAS,EAKT,YAAY,EAGb,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,sBAAsB,EAC5B,GAAG,EAAE,yBAAyB;;;;;;;;;;;;GAmP/B"}
|
|
@@ -4,38 +4,32 @@ import { ApifoxClient, isValidApifoxUrl, parseApifoxUrl, ShareLinkType, UnifiedC
|
|
|
4
4
|
*/
|
|
5
5
|
export async function handleParseAndAddProject(args, ctx) {
|
|
6
6
|
const { url } = args;
|
|
7
|
-
const { projectRoot, configManager, mcpBridge, contextStore
|
|
7
|
+
const { projectRoot, configManager, mcpBridge, contextStore } = ctx;
|
|
8
8
|
const steps = [];
|
|
9
9
|
const errors = [];
|
|
10
|
-
let projectId;
|
|
11
10
|
let projectName;
|
|
12
11
|
let fullProjectInfo = null;
|
|
13
12
|
let interfaceDetail = null;
|
|
14
|
-
// 步骤 1:
|
|
15
|
-
steps.push('📋 步骤 1:
|
|
13
|
+
// 步骤 1: 检查访问令牌
|
|
14
|
+
steps.push('📋 步骤 1: 检查访问令牌');
|
|
16
15
|
steps.push(` 📂 项目根目录: ${projectRoot}`);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
errors.push(...initResult.errors.map((e) => ` - ${e}`));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
steps.push(' ✅ apifox-mcp.json 文件存在');
|
|
37
|
-
steps.push(` 📍 文件位置: ${configManager.getApifoxConfigPath()}`);
|
|
16
|
+
const accessToken = configManager.getAccessToken();
|
|
17
|
+
if (!accessToken) {
|
|
18
|
+
return {
|
|
19
|
+
content: [
|
|
20
|
+
{
|
|
21
|
+
type: 'text',
|
|
22
|
+
text: `❌ 未找到 APIFOX_ACCESS_TOKEN\n\n` +
|
|
23
|
+
`${steps.join('\n')}\n\n` +
|
|
24
|
+
`请在 MCP 配置的 env 中配置 APIFOX_ACCESS_TOKEN:\n\n` +
|
|
25
|
+
`在 ~/.cursor/mcp.json 或项目根目录的 .cursor/mcp.json 中添加:\n\n` +
|
|
26
|
+
`\`\`\`json\n{\n "mcpServers": {\n "apifox-workspace-mcp": {\n "command": "node",\n "args": ["/path/to/dist/server/index.js"],\n "env": {\n "APIFOX_ACCESS_TOKEN": "your_token_here"\n }\n }\n }\n}\n\`\`\``,
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
isError: true,
|
|
30
|
+
};
|
|
38
31
|
}
|
|
32
|
+
steps.push(' ✅ Access Token 已配置');
|
|
39
33
|
// 步骤 2: 验证和解析 URL
|
|
40
34
|
steps.push('\n🔗 步骤 2: 验证和解析 URL');
|
|
41
35
|
if (!isValidApifoxUrl(url)) {
|
|
@@ -63,7 +57,7 @@ export async function handleParseAndAddProject(args, ctx) {
|
|
|
63
57
|
isError: true,
|
|
64
58
|
};
|
|
65
59
|
}
|
|
66
|
-
projectId = parsed.projectId;
|
|
60
|
+
const projectId = parsed.projectId;
|
|
67
61
|
projectName = parsed.projectName;
|
|
68
62
|
const linkType = parsed.linkType;
|
|
69
63
|
const llmsUrl = parsed.llmsUrl;
|
|
@@ -79,34 +73,22 @@ export async function handleParseAndAddProject(args, ctx) {
|
|
|
79
73
|
steps.push(` - 接口 ID: ${parsed.interfaceId}`);
|
|
80
74
|
}
|
|
81
75
|
steps.push(` - llms.txt URL: ${llmsUrl}`);
|
|
82
|
-
// 步骤 3:
|
|
83
|
-
steps.push('\n🔑 步骤 3: 检查 Access Token');
|
|
84
|
-
const accessToken = configManager.getAccessToken();
|
|
85
|
-
if (!accessToken) {
|
|
86
|
-
return {
|
|
87
|
-
content: [
|
|
88
|
-
{
|
|
89
|
-
type: 'text',
|
|
90
|
-
text: `❌ 未找到 APIFOX_ACCESS_TOKEN\n\n` +
|
|
91
|
-
`${steps.join('\n')}\n\n` +
|
|
92
|
-
`请在 MCP 配置的 env 中配置 APIFOX_ACCESS_TOKEN:\n\n` +
|
|
93
|
-
`在 ~/.cursor/mcp.json 或项目根目录的 .cursor/mcp.json 中添加:\n\n` +
|
|
94
|
-
`\`\`\`json\n{\n "mcpServers": {\n "apifox-workspace-mcp": {\n "command": "node",\n "args": ["/path/to/dist/server/index.js"],\n "env": {\n "APIFOX_ACCESS_TOKEN": "your_token_here"\n }\n }\n }\n}\n\`\`\``,
|
|
95
|
-
},
|
|
96
|
-
],
|
|
97
|
-
isError: true,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
steps.push(' ✅ Access Token 已配置');
|
|
101
|
-
// 步骤 4: 检查项目是否已存在
|
|
76
|
+
// 步骤 3: 检查项目是否已存在
|
|
102
77
|
steps.push('\n🔍 步骤 4: 检查项目是否已存在');
|
|
103
|
-
|
|
78
|
+
const cacheManager = new UnifiedCacheManager(projectRoot);
|
|
79
|
+
const existingProject = cacheManager.findProjectById(projectId);
|
|
80
|
+
if (existingProject) {
|
|
81
|
+
steps.push(` ℹ️ 项目已存在: ${existingProject.projectName} (${projectId})`);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
steps.push(` ✅ 项目不存在,将创建新项目`);
|
|
85
|
+
}
|
|
104
86
|
// 步骤 5: 如果是接口分享链接,获取接口详情
|
|
105
87
|
if (linkType === ShareLinkType.INTERFACE && parsed.interfaceId) {
|
|
106
88
|
steps.push('\n📡 步骤 5: 获取接口详情');
|
|
107
89
|
steps.push(` 🔄 正在获取接口 ${parsed.interfaceId} 的详细信息...`);
|
|
108
90
|
try {
|
|
109
|
-
const apifoxClient = new ApifoxClient(accessToken, getApiBaseUrl() ?? undefined);
|
|
91
|
+
const apifoxClient = new ApifoxClient(accessToken, configManager.getApiBaseUrl() ?? undefined);
|
|
110
92
|
interfaceDetail = await apifoxClient.getInterfaceDetail(projectId, parsed.interfaceId);
|
|
111
93
|
steps.push(' ✅ 成功获取接口详情');
|
|
112
94
|
}
|
|
@@ -114,29 +96,34 @@ export async function handleParseAndAddProject(args, ctx) {
|
|
|
114
96
|
steps.push(` ⚠️ 获取接口详情失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
115
97
|
}
|
|
116
98
|
}
|
|
117
|
-
// 步骤
|
|
118
|
-
steps.push('\n📡 步骤
|
|
99
|
+
// 步骤 5: 获取项目信息(通过 Apifox 官方 MCP Server,可选)
|
|
100
|
+
steps.push('\n📡 步骤 5: 获取项目信息(可选)');
|
|
119
101
|
if (!projectName) {
|
|
120
102
|
steps.push(' 🔄 通过 Apifox 官方 MCP Server 获取项目信息...');
|
|
121
103
|
try {
|
|
122
104
|
const mcpResult = await mcpBridge.getProjectInfoViaMcp(accessToken, projectId);
|
|
123
105
|
fullProjectInfo = mcpResult;
|
|
124
|
-
projectName = mcpResult.name
|
|
125
|
-
|
|
106
|
+
projectName = mcpResult.name;
|
|
107
|
+
if (projectName) {
|
|
108
|
+
steps.push(' ✅ 通过 MCP Server 成功获取项目信息');
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
steps.push(' ⚠️ MCP Server 未返回项目名称');
|
|
112
|
+
}
|
|
126
113
|
}
|
|
127
114
|
catch (mcpError) {
|
|
128
115
|
steps.push(` ⚠️ MCP Server 调用失败: ${mcpError instanceof Error ? mcpError.message : String(mcpError)}`);
|
|
129
|
-
projectName = projectName || `project-${projectId.substring(0, 8)}`;
|
|
130
|
-
steps.push(` ⚠️ 使用默认项目名称: ${projectName}`);
|
|
131
116
|
}
|
|
132
117
|
}
|
|
133
118
|
else {
|
|
134
119
|
steps.push(' ℹ️ 已从页面标题获取项目名称,跳过 MCP Server 调用');
|
|
135
120
|
}
|
|
136
|
-
// 步骤
|
|
137
|
-
steps.push('\n💾 步骤
|
|
121
|
+
// 步骤 6: 保存或更新项目信息到统一缓存
|
|
122
|
+
steps.push('\n💾 步骤 6: 保存项目信息到统一缓存');
|
|
123
|
+
// 如果无法获取真实项目名称,使用 ${shareId}-${projectId} 作为后备
|
|
138
124
|
if (!projectName) {
|
|
139
|
-
projectName =
|
|
125
|
+
projectName = shareId ? `${shareId}-${projectId}` : projectId;
|
|
126
|
+
steps.push(` ⚠️ 使用后备项目名称: ${projectName}`);
|
|
140
127
|
}
|
|
141
128
|
if (!llmsUrl) {
|
|
142
129
|
return {
|
|
@@ -150,9 +137,8 @@ export async function handleParseAndAddProject(args, ctx) {
|
|
|
150
137
|
};
|
|
151
138
|
}
|
|
152
139
|
// 使用统一缓存管理器
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
cacheManager.upsertProjectMetadata(projectName, projectId, llmsUrl);
|
|
140
|
+
// 保存项目元数据(包含 shareId)
|
|
141
|
+
cacheManager.upsertProjectMetadata(projectName, projectId, llmsUrl, shareId);
|
|
156
142
|
steps.push(' ✅ 已保存项目元数据到统一缓存');
|
|
157
143
|
// 从 llms.txt 解析接口列表
|
|
158
144
|
steps.push(' 🔄 正在从 llms.txt 解析接口列表...');
|
|
@@ -167,81 +153,67 @@ export async function handleParseAndAddProject(args, ctx) {
|
|
|
167
153
|
steps.push(` ⚠️ 解析 llms.txt 失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
168
154
|
errors.push(`解析 llms.txt 失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
169
155
|
}
|
|
170
|
-
//
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
responseText +=
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
responseText += `-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
156
|
+
// 设置最后操作的项目
|
|
157
|
+
contextStore.setLastProject(projectName, projectId);
|
|
158
|
+
// 构建返回信息
|
|
159
|
+
let responseText = '';
|
|
160
|
+
// 检查是否为新项目
|
|
161
|
+
const isNewProject = !existingProject;
|
|
162
|
+
// 根据链接类型和是否为新项目,构造不同的提示语
|
|
163
|
+
if (linkType === ShareLinkType.PROJECT) {
|
|
164
|
+
responseText = isNewProject ? `✅ 项目配置已添加!\n\n` : `✅ 项目配置已更新!\n\n`;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
responseText = isNewProject
|
|
168
|
+
? `✅ 该接口对应项目配置已添加!\n\n`
|
|
169
|
+
: `✅ 该接口对应项目配置已存在!\n\n`;
|
|
170
|
+
}
|
|
171
|
+
responseText += `**保存的信息:**\n`;
|
|
172
|
+
responseText += `- 项目 ID: ${projectId}\n`;
|
|
173
|
+
responseText += `- 项目名称: ${projectName}\n`;
|
|
174
|
+
responseText += `- 分享 ID: ${shareId}\n`;
|
|
175
|
+
if (llmsUrl) {
|
|
176
|
+
responseText += `- llms.txt URL: ${llmsUrl}\n`;
|
|
177
|
+
}
|
|
178
|
+
if (parsed.interfaceId) {
|
|
179
|
+
responseText += `- 接口 ID: ${parsed.interfaceId}\n`;
|
|
180
|
+
}
|
|
181
|
+
responseText += `\n`;
|
|
182
|
+
// 如果是接口分享链接,输出接口详情
|
|
183
|
+
if (linkType === ShareLinkType.INTERFACE && interfaceDetail) {
|
|
184
|
+
responseText += `**当前接口信息:**\n`;
|
|
185
|
+
responseText += `- 接口名称: ${interfaceDetail.name || '未命名'}\n`;
|
|
186
|
+
responseText += `- 请求方法: ${interfaceDetail.method || 'UNKNOWN'}\n`;
|
|
187
|
+
responseText += `- 接口路径: ${interfaceDetail.path || '/'}\n`;
|
|
188
|
+
if (interfaceDetail.description) {
|
|
189
|
+
responseText += `- 描述: ${interfaceDetail.description}\n`;
|
|
199
190
|
}
|
|
200
191
|
responseText += `\n`;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
responseText += `**当前接口信息:**\n`;
|
|
204
|
-
responseText += `- 接口名称: ${interfaceDetail.name || '未命名'}\n`;
|
|
205
|
-
responseText += `- 请求方法: ${interfaceDetail.method || 'UNKNOWN'}\n`;
|
|
206
|
-
responseText += `- 接口路径: ${interfaceDetail.path || '/'}\n`;
|
|
207
|
-
if (interfaceDetail.description) {
|
|
208
|
-
responseText += `- 描述: ${interfaceDetail.description}\n`;
|
|
209
|
-
}
|
|
210
|
-
responseText += `\n`;
|
|
211
|
-
responseText += `**完整接口详情:**\n`;
|
|
212
|
-
responseText += `\`\`\`json\n${JSON.stringify(interfaceDetail, null, 2)}\n\`\`\`\n\n`;
|
|
213
|
-
}
|
|
214
|
-
if (fullProjectInfo) {
|
|
215
|
-
responseText += `**项目完整信息:**\n`;
|
|
216
|
-
responseText += `\`\`\`json\n${JSON.stringify(fullProjectInfo, null, 2)}\n\`\`\`\n\n`;
|
|
217
|
-
}
|
|
218
|
-
// 根据链接类型询问用户下一步
|
|
219
|
-
if (linkType === ShareLinkType.PROJECT) {
|
|
220
|
-
responseText += `现在想要了解该项目的哪些信息?\n`;
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
responseText += `现在需要我帮助您做什么?\n`;
|
|
224
|
-
}
|
|
225
|
-
return {
|
|
226
|
-
content: [
|
|
227
|
-
{
|
|
228
|
-
type: 'text',
|
|
229
|
-
text: responseText,
|
|
230
|
-
},
|
|
231
|
-
],
|
|
232
|
-
};
|
|
192
|
+
responseText += `**完整接口详情:**\n`;
|
|
193
|
+
responseText += `\`\`\`json\n${JSON.stringify(interfaceDetail, null, 2)}\n\`\`\`\n\n`;
|
|
233
194
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
content: [
|
|
238
|
-
{
|
|
239
|
-
type: 'text',
|
|
240
|
-
text: `❌ ${upsertResult.message}\n\n**执行过程:**\n${steps.join('\n')}\n\n**错误:**\n${errors.join('\n')}`,
|
|
241
|
-
},
|
|
242
|
-
],
|
|
243
|
-
isError: true,
|
|
244
|
-
};
|
|
195
|
+
if (fullProjectInfo) {
|
|
196
|
+
responseText += `**项目完整信息:**\n`;
|
|
197
|
+
responseText += `\`\`\`json\n${JSON.stringify(fullProjectInfo, null, 2)}\n\`\`\`\n\n`;
|
|
245
198
|
}
|
|
199
|
+
// 根据链接类型询问用户下一步
|
|
200
|
+
if (linkType === ShareLinkType.PROJECT) {
|
|
201
|
+
responseText += `现在想要了解该项目的哪些信息?\n`;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
responseText += `现在需要我帮助您做什么?\n`;
|
|
205
|
+
}
|
|
206
|
+
// 如果有错误,添加错误信息
|
|
207
|
+
if (errors.length > 0) {
|
|
208
|
+
responseText += `\n**警告:**\n${errors.join('\n')}\n`;
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
content: [
|
|
212
|
+
{
|
|
213
|
+
type: 'text',
|
|
214
|
+
text: responseText,
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
};
|
|
246
218
|
}
|
|
247
219
|
//# sourceMappingURL=parse-and-add-project.js.map
|