@zzp123/mcp-zentao 1.15.0 → 1.17.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.
@@ -0,0 +1,214 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ // 角色工具配置
5
+ const TOOL_CATEGORIES = {
6
+ init: ['initZentao'],
7
+ story: ['createStory', 'getStoryDetail', 'changeStory', 'deleteStory', 'getProductStories', 'addStoryComment'],
8
+ storyReadonly: ['getStoryDetail', 'getProductStories'],
9
+ product: ['getProducts', 'getProductDetail', 'createProduct', 'updateProduct', 'deleteProduct'],
10
+ plan: ['getProductPlans', 'getPlanDetail', 'createPlan', 'updatePlan', 'deletePlan', 'linkStoriesToPlan', 'unlinkStoriesFromPlan', 'linkBugsToPlan', 'unlinkBugsFromPlan'],
11
+ program: ['getPrograms', 'getProgramDetail', 'createProgram', 'updateProgram', 'deleteProgram'],
12
+ feedback: ['getFeedbacks', 'getFeedbackDetail', 'createFeedback', 'updateFeedback', 'deleteFeedback', 'assignFeedback', 'closeFeedback'],
13
+ bug: ['getMyBugs', 'getProductBugs', 'getBugDetail', 'createBug', 'updateBug', 'deleteBug', 'resolveBug', 'addBugComment'],
14
+ bugResolve: ['getMyBugs', 'getBugDetail', 'resolveBug', 'addBugComment'],
15
+ bugReadonly: ['getMyBugs', 'getProductBugs', 'getBugDetail'],
16
+ testcase: ['getProductTestCases', 'getTestCaseDetail', 'createTestCase', 'updateTestCase', 'deleteTestCase'],
17
+ task: ['getMyTasks', 'getTaskDetail', 'createTask', 'updateTask', 'finishTask', 'deleteTask', 'addTaskComment'],
18
+ taskReadonly: ['getMyTasks', 'getTaskDetail'],
19
+ project: ['getProjects', 'getProjectDetail', 'createProject', 'updateProject', 'deleteProject', 'getProjectReleases', 'getProjectExecutions', 'getProjectBuilds'],
20
+ execution: ['getExecutionDetail', 'createExecution', 'updateExecution', 'deleteExecution', 'getExecutionBuilds'],
21
+ build: ['getBuildDetail', 'createBuild', 'updateBuild', 'deleteBuild'],
22
+ ticket: ['getTickets', 'getTicketDetail', 'createTicket', 'updateTicket', 'deleteTicket'],
23
+ comment: ['getComments', 'getCommentDetail', 'addComment', 'updateComment', 'deleteComment', 'addTaskComment', 'addBugComment', 'addStoryComment'],
24
+ utility: ['getModules', 'uploadFile', 'uploadImageFromClipboard', 'downloadFile'],
25
+ user: ['getUsers', 'getUserDetail', 'getMyProfile', 'createUser', 'updateUser', 'deleteUser']
26
+ };
27
+
28
+ const ROLE_PERMISSIONS = {
29
+ pm: [
30
+ ...TOOL_CATEGORIES.init,
31
+ ...TOOL_CATEGORIES.story,
32
+ ...TOOL_CATEGORIES.product,
33
+ ...TOOL_CATEGORIES.plan,
34
+ ...TOOL_CATEGORIES.program,
35
+ ...TOOL_CATEGORIES.feedback,
36
+ ...TOOL_CATEGORIES.bugReadonly,
37
+ ...TOOL_CATEGORIES.taskReadonly,
38
+ ...TOOL_CATEGORIES.comment,
39
+ ...TOOL_CATEGORIES.ticket,
40
+ ...TOOL_CATEGORIES.utility
41
+ ],
42
+ qa: [
43
+ ...TOOL_CATEGORIES.init,
44
+ ...TOOL_CATEGORIES.bug,
45
+ ...TOOL_CATEGORIES.testcase,
46
+ ...TOOL_CATEGORIES.build,
47
+ ...TOOL_CATEGORIES.storyReadonly,
48
+ ...TOOL_CATEGORIES.taskReadonly,
49
+ ...TOOL_CATEGORIES.comment,
50
+ ...TOOL_CATEGORIES.ticket,
51
+ ...TOOL_CATEGORIES.utility
52
+ ],
53
+ dev: [
54
+ ...TOOL_CATEGORIES.init,
55
+ ...TOOL_CATEGORIES.task,
56
+ ...TOOL_CATEGORIES.bugResolve,
57
+ ...TOOL_CATEGORIES.project,
58
+ ...TOOL_CATEGORIES.execution,
59
+ ...TOOL_CATEGORIES.build,
60
+ ...TOOL_CATEGORIES.storyReadonly,
61
+ ...TOOL_CATEGORIES.comment,
62
+ ...TOOL_CATEGORIES.ticket,
63
+ ...TOOL_CATEGORIES.utility
64
+ ]
65
+ };
66
+
67
+ const ROLE_NAMES = {
68
+ pm: '产品经理',
69
+ qa: '测试工程师',
70
+ dev: '开发工程师'
71
+ };
72
+
73
+ // 读取完整的 index.ts
74
+ const indexPath = path.join(__dirname, 'src', 'index.ts');
75
+ const indexContent = fs.readFileSync(indexPath, 'utf8');
76
+
77
+ // 提取工具注册块的函数
78
+ function extractToolBlocks(content) {
79
+ const lines = content.split('\n');
80
+ const blocks = [];
81
+ let currentBlock = null;
82
+ let braceDepth = 0;
83
+ let parenDepth = 0;
84
+
85
+ for (let i = 0; i < lines.length; i++) {
86
+ const line = lines[i];
87
+ const trimmed = line.trim();
88
+
89
+ // 检测 server.tool 的开始
90
+ if (trimmed.startsWith('server.tool(')) {
91
+ // 提取工具名
92
+ const match = trimmed.match(/server\.tool\("([^"]+)"/);
93
+ if (match) {
94
+ currentBlock = {
95
+ toolName: match[1],
96
+ startLine: i,
97
+ lines: [line],
98
+ braceDepth: 0,
99
+ parenDepth: 0
100
+ };
101
+
102
+ // 计算当前行的括号和大括号
103
+ currentBlock.parenDepth += (line.match(/\(/g) || []).length - (line.match(/\)/g) || []).length;
104
+ currentBlock.braceDepth += (line.match(/\{/g) || []).length - (line.match(/\}/g) || []).length;
105
+ }
106
+ } else if (currentBlock) {
107
+ // 在工具块内
108
+ currentBlock.lines.push(line);
109
+ currentBlock.parenDepth += (line.match(/\(/g) || []).length - (line.match(/\)/g) || []).length;
110
+ currentBlock.braceDepth += (line.match(/\{/g) || []).length - (line.match(/\}/g) || []).length;
111
+
112
+ // 检查是否到达块的结束(圆括号和大括号都平衡,且以 ); 结尾)
113
+ if (currentBlock.parenDepth === 0 && currentBlock.braceDepth === 0 && trimmed.endsWith(');')) {
114
+ currentBlock.endLine = i;
115
+ blocks.push(currentBlock);
116
+ currentBlock = null;
117
+ }
118
+ }
119
+ }
120
+
121
+ return blocks;
122
+ }
123
+
124
+ // 为每个角色生成文件
125
+ ['pm', 'qa', 'dev'].forEach(role => {
126
+ console.log(`\n正在生成 ${ROLE_NAMES[role]} (${role}) 版本...`);
127
+
128
+ const allowedTools = new Set(ROLE_PERMISSIONS[role]);
129
+ console.log(` 允许的工具: ${Array.from(allowedTools).join(', ')}`);
130
+
131
+ // 提取所有工具块
132
+ const toolBlocks = extractToolBlocks(indexContent);
133
+ console.log(` 总工具数: ${toolBlocks.length}`);
134
+
135
+ // 过滤出允许的工具
136
+ const allowedBlocks = toolBlocks.filter(block => allowedTools.has(block.toolName));
137
+ console.log(` ${ROLE_NAMES[role]}可用工具数: ${allowedBlocks.length}`);
138
+
139
+ // 构建新文件内容
140
+ const lines = indexContent.split('\n');
141
+ const outputLines = [];
142
+ const includedLines = new Set();
143
+
144
+ // 标记所有要包含的行
145
+ allowedBlocks.forEach(block => {
146
+ for (let i = block.startLine; i <= block.endLine; i++) {
147
+ includedLines.add(i);
148
+ }
149
+ // 如果前一行是注释,也包含进来
150
+ if (block.startLine > 0 && lines[block.startLine - 1].trim().startsWith('//')) {
151
+ includedLines.add(block.startLine - 1);
152
+ }
153
+ });
154
+
155
+ // 找到第一个 server.tool 的位置
156
+ let firstToolLine = toolBlocks.length > 0 ? toolBlocks[0].startLine : lines.length;
157
+
158
+ // 输出文件头部(到第一个工具之前)
159
+ for (let i = 0; i < firstToolLine; i++) {
160
+ outputLines.push(lines[i]);
161
+ }
162
+
163
+ // 更新服务器名称和版本
164
+ const headerContent = outputLines.join('\n');
165
+ let updatedHeader = headerContent
166
+ .replace(/name: "Zentao API"/, `name: "Zentao API (${ROLE_NAMES[role]})"`)
167
+ .replace(/version: "1\.16\.0"/, `version: "1.17.0"`);
168
+
169
+ // 输出更新后的头部
170
+ const finalLines = updatedHeader.split('\n');
171
+
172
+ // 添加所有允许的工具块
173
+ let lastEndLine = firstToolLine - 1;
174
+ allowedBlocks.forEach((block, index) => {
175
+ // 添加空行分隔(如果需要)
176
+ if (block.startLine > lastEndLine + 1) {
177
+ finalLines.push('');
178
+ }
179
+
180
+ // 添加工具块
181
+ for (let i = block.startLine; i <= block.endLine; i++) {
182
+ finalLines.push(lines[i]);
183
+ }
184
+
185
+ lastEndLine = block.endLine;
186
+ });
187
+
188
+ // 添加文件尾部(服务器启动代码)
189
+ const lastToolBlock = toolBlocks[toolBlocks.length - 1];
190
+ if (lastToolBlock) {
191
+ for (let i = lastToolBlock.endLine + 1; i < lines.length; i++) {
192
+ finalLines.push(lines[i]);
193
+ }
194
+ }
195
+
196
+ // 写入文件
197
+ const output = finalLines.join('\n');
198
+ const outputPath = path.join(__dirname, 'src', `index-${role}.ts`);
199
+ fs.writeFileSync(outputPath, output, 'utf8');
200
+
201
+ console.log(` ✓ 已生成: ${outputPath}`);
202
+
203
+ // 统计文件大小
204
+ const stats = fs.statSync(outputPath);
205
+ const originalStats = fs.statSync(indexPath);
206
+ const reduction = ((1 - stats.size / originalStats.size) * 100).toFixed(1);
207
+ console.log(` 文件大小: ${(stats.size / 1024).toFixed(1)} KB (原始: ${(originalStats.size / 1024).toFixed(1)} KB, 减少 ${reduction}%)`);
208
+ });
209
+
210
+ console.log('\n✓ 所有角色版本生成完成!');
211
+ console.log('\n下一步:');
212
+ console.log('1. 运行 npx tsc 编译所有版本');
213
+ console.log('2. 配置 package.json 的构建脚本');
214
+ console.log('3. 测试各个版本');