mcp-osp-prompt 1.0.0 → 1.0.2
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 +22 -78
- package/config.js +12 -17
- package/debug-env.js +7 -0
- package/dialog/browser.js +2 -2
- package/dialog/constants.js +0 -2
- package/dialog/native.js +23 -34
- package/dialog/objc.js +2 -2
- package/fetcher.js +1 -1
- package/package.json +5 -5
- package/platform-utils.js +18 -45
- package/prompt-manager.js +89 -534
- package/server.js +58 -15
- package/test.js +2 -2
- package/tools.js +14 -147
- package/resource-manager.js +0 -358
package/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import process from 'process';
|
|
3
3
|
import { initializePrompts, getToolsConfiguration } from './prompt-manager.js';
|
|
4
|
-
import { handleDevTool, handleDevManual, handleDevFeedback
|
|
4
|
+
import { handleDevTool, handleDevManual, handleDevFeedback } from './tools.js';
|
|
5
5
|
import { CFG } from './config.js';
|
|
6
6
|
import {
|
|
7
7
|
createSuccessResponse,
|
|
@@ -43,12 +43,12 @@ if (debug) {
|
|
|
43
43
|
|
|
44
44
|
// 🔄 优雅关闭处理
|
|
45
45
|
process.on('SIGTERM', () => {
|
|
46
|
-
console.
|
|
46
|
+
console.error('📴 [MCP-Server] Received SIGTERM, shutting down gracefully');
|
|
47
47
|
process.exit(0);
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
process.on('SIGINT', () => {
|
|
51
|
-
console.
|
|
51
|
+
console.error('📴 [MCP-Server] Received SIGINT, shutting down gracefully');
|
|
52
52
|
process.exit(0);
|
|
53
53
|
});
|
|
54
54
|
|
|
@@ -58,18 +58,35 @@ let isServerReady = false;
|
|
|
58
58
|
|
|
59
59
|
// 同步初始化函数 - 阻塞式等待初始化完成
|
|
60
60
|
async function initializeServerSync() {
|
|
61
|
+
// ✅ 添加keepAlive定时器,防止客户端超时
|
|
62
|
+
let keepAliveInterval;
|
|
63
|
+
|
|
61
64
|
try {
|
|
62
65
|
console.error('[MCP-Server] Starting synchronous initialization...');
|
|
63
66
|
|
|
67
|
+
// 每10秒输出一次日志,保持连接活跃
|
|
68
|
+
keepAliveInterval = setInterval(() => {
|
|
69
|
+
console.error('[MCP-KeepAlive] Initializing tools, please wait...');
|
|
70
|
+
}, 10000);
|
|
71
|
+
|
|
64
72
|
// 同步初始化prompt管理器
|
|
65
73
|
globalToolsConfig = await initializePrompts();
|
|
66
74
|
|
|
75
|
+
// 清理keepAlive定时器
|
|
76
|
+
clearInterval(keepAliveInterval);
|
|
77
|
+
keepAliveInterval = null;
|
|
78
|
+
|
|
67
79
|
// 标记服务器就绪
|
|
68
80
|
isServerReady = true;
|
|
69
81
|
console.error(`[MCP-Server] ✅ Server ready with ${globalToolsConfig.length} tools`);
|
|
70
82
|
|
|
71
83
|
return true;
|
|
72
84
|
} catch (error) {
|
|
85
|
+
// 清理keepAlive定时器(如果还在运行)
|
|
86
|
+
if (keepAliveInterval) {
|
|
87
|
+
clearInterval(keepAliveInterval);
|
|
88
|
+
}
|
|
89
|
+
|
|
73
90
|
console.error('[MCP-Server] ❌ Initialization failed:', error.message);
|
|
74
91
|
console.error('[MCP-Server] Server will not accept requests');
|
|
75
92
|
isServerReady = false;
|
|
@@ -216,9 +233,6 @@ async function handleToolCall(req) {
|
|
|
216
233
|
⚠️ **MANDATORY NEXT STEP REMINDER:** 在完成下一个实施步骤后,必须再次调用dev-feedback工具汇报进度并获取确认。每个步骤完成后都需要调用feedback工具 - 这是强制要求!`;
|
|
217
234
|
}
|
|
218
235
|
break;
|
|
219
|
-
case 'handleLoadResource':
|
|
220
|
-
resultText = await handleLoadResource(args);
|
|
221
|
-
break;
|
|
222
236
|
default:
|
|
223
237
|
throw new Error(`Unknown handler: ${tool.handler}`);
|
|
224
238
|
}
|
|
@@ -226,15 +240,44 @@ async function handleToolCall(req) {
|
|
|
226
240
|
// Handle prompt-based tools
|
|
227
241
|
const promptResult = await handleDevTool(name, args);
|
|
228
242
|
|
|
229
|
-
//
|
|
230
|
-
|
|
243
|
+
// 根据AUTO模式附加不同的工作流指令
|
|
244
|
+
const isAutomatedMode = (process.env.AUTOMATED_MODE || 'false').toLowerCase() === 'true';
|
|
245
|
+
|
|
246
|
+
if (isAutomatedMode) {
|
|
247
|
+
// AUTO=true: 简洁提醒
|
|
248
|
+
resultText = `${promptResult}
|
|
231
249
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
250
|
+
**工作流提醒:** 按计划执行,完成后汇报结果。`;
|
|
251
|
+
} else {
|
|
252
|
+
// AUTO=false: 强制分步确认+自检
|
|
253
|
+
resultText = `${promptResult}
|
|
236
254
|
|
|
237
|
-
|
|
255
|
+
---
|
|
256
|
+
## ⚠️ **CRITICAL WORKFLOW REQUIREMENT:**
|
|
257
|
+
|
|
258
|
+
**每完成一步,必须调用 \`dev-feedback\` 并展示以下信息:**
|
|
259
|
+
|
|
260
|
+
### 展示内容
|
|
261
|
+
1. **当前阶段**:完成的步骤/阶段名称
|
|
262
|
+
2. **工作摘要**:完成的主要工作内容
|
|
263
|
+
3. **自检结果**:
|
|
264
|
+
- 是否有多方案未选择
|
|
265
|
+
- 是否有信息不明确或需要澄清的内容
|
|
266
|
+
- 是否发现冲突(代码/逻辑/信息)
|
|
267
|
+
- 是否偏离计划需要调整
|
|
268
|
+
- 是否即将执行重要操作(删除代码、修改核心逻辑、数据库变更等)
|
|
269
|
+
- 是否存在"TBD"、"待确认"、"Question"等需要用户确认的内容
|
|
270
|
+
- 是否涉及项目/系统范围确认(无论已确认还是待确认,都必须调用 dev-feedback 让用户确认)
|
|
271
|
+
4. **下一步**:下一步计划(如有)
|
|
272
|
+
|
|
273
|
+
**最后一步结束后,确认:是否满足所有需求和完成了计划?**
|
|
274
|
+
|
|
275
|
+
### 规则
|
|
276
|
+
- 宁可多确认,不可漏确认
|
|
277
|
+
- 严禁将待确认内容留到最终文档
|
|
278
|
+
|
|
279
|
+
**⚠️ 立即调用 dev-feedback 开始确认!**`;
|
|
280
|
+
}
|
|
238
281
|
} else {
|
|
239
282
|
throw new Error(`Unknown tool type: ${tool.type}`);
|
|
240
283
|
}
|
|
@@ -248,7 +291,7 @@ async function handleToolCall(req) {
|
|
|
248
291
|
|
|
249
292
|
// 特殊处理:某些"错误"实际上是正常的用户交互结果
|
|
250
293
|
if (error.message.includes('用户要求调整计划')) {
|
|
251
|
-
console.
|
|
294
|
+
console.error(`[MCP信息] 用户计划调整请求: ${error.message}`);
|
|
252
295
|
return createSuccessResponse(req.id, {
|
|
253
296
|
content: [{ type: 'text', text: error.message }]
|
|
254
297
|
});
|
|
@@ -260,7 +303,7 @@ async function handleToolCall(req) {
|
|
|
260
303
|
// 针对常见错误场景提供更清晰的信息
|
|
261
304
|
if (error.message.includes('fetch fail') || error.message.includes('API')) {
|
|
262
305
|
errorMsg = `网络请求失败 - ${error.message}`;
|
|
263
|
-
} else if (error.message.includes('
|
|
306
|
+
} else if (error.message.includes('PROMPT_PATH')) {
|
|
264
307
|
errorMsg = `配置错误 - ${error.message}`;
|
|
265
308
|
} else if (error.message.includes('Unknown prompt file')) {
|
|
266
309
|
errorMsg = `文件未找到 - ${error.message}`;
|
package/test.js
CHANGED
|
@@ -9,7 +9,7 @@ console.log('🧪 Starting comprehensive MCP server tests...');
|
|
|
9
9
|
(async () => {
|
|
10
10
|
// Set automated mode to skip GUI dialogs and required environment variables
|
|
11
11
|
process.env.AUTOMATED_MODE = 'true';
|
|
12
|
-
process.env.
|
|
12
|
+
process.env.PROMPT_PATH = '../dev-arch'; // Use local test path (parent directory)
|
|
13
13
|
process.env.GIT_TOKEN = 'test-token'; // Dummy token for testing
|
|
14
14
|
|
|
15
15
|
const proc = spawn('node', ['server.js'], {
|
|
@@ -18,7 +18,7 @@ console.log('🧪 Starting comprehensive MCP server tests...');
|
|
|
18
18
|
env: {
|
|
19
19
|
...process.env,
|
|
20
20
|
AUTOMATED_MODE: 'true',
|
|
21
|
-
|
|
21
|
+
PROMPT_PATH: '../dev-arch',
|
|
22
22
|
GIT_TOKEN: 'test-token'
|
|
23
23
|
}
|
|
24
24
|
});
|
package/tools.js
CHANGED
|
@@ -50,9 +50,6 @@ export function processPromptTemplate(content, context = {}) {
|
|
|
50
50
|
const sourceText = context.source || '';
|
|
51
51
|
processedContent = processedContent.replace(/\$\{input:source[^}]*}/g, sourceText);
|
|
52
52
|
|
|
53
|
-
// Replace requirements variable (used in design.prompt.md)
|
|
54
|
-
processedContent = processedContent.replace(/\$\{input:requirements[^}]*}/g, sourceText);
|
|
55
|
-
|
|
56
53
|
// Inject project context if available
|
|
57
54
|
if (context.projectInfo) {
|
|
58
55
|
processedContent = processedContent.replace(/\$\{project:([^}]+)}/g, (match, key) => {
|
|
@@ -84,41 +81,13 @@ export function processPromptTemplate(content, context = {}) {
|
|
|
84
81
|
export function generateStepModeInstructions(context = {}) {
|
|
85
82
|
const sourceText = context.source || '未指定需求';
|
|
86
83
|
|
|
84
|
+
// 简化版:主要逻辑已统一移到server.js handleToolCall处理
|
|
85
|
+
// 这里只提供基本的需求上下文,避免重复
|
|
87
86
|
return `
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
### 🎯 分步执行指南
|
|
93
|
-
1. **计划阶段**: 先分析需求并制定实施计划,然后调用 \`dev-feedback\` 工具请求用户确认
|
|
94
|
-
2. **实施阶段**: 每完成一个重要步骤后,使用 \`dev-feedback\` 工具询问用户是否继续
|
|
95
|
-
3. **实施阶段**: 连续出现3次执行错误,则使用 \`dev-feedback\` 工具请求用户确认是否需要继续或修改计划
|
|
96
|
-
4. **实施阶段**: 如果执行的过程中,需要使用不在计划中的新方案或新思路,则使用 \`dev-feedback\` 工具请求用户确认是否需要继续或修改计划
|
|
97
|
-
5. **确认选项**:
|
|
98
|
-
- "继续" - 按计划继续执行
|
|
99
|
-
- "修改" - 调整当前计划或步骤
|
|
100
|
-
- "暂停" - 暂停开发等待进一步指示
|
|
101
|
-
|
|
102
|
-
### 📞 如何调用确认工具
|
|
103
|
-
|
|
104
|
-
**调用方式** :
|
|
105
|
-
统一的弹窗选项,所有阶段都使用相同的简洁选择:
|
|
106
|
-
|
|
107
|
-
- **所有阶段**: 统一使用 ["继续", "修改计划"] 两个选项
|
|
108
|
-
- **用户体验**: 选择"继续"将按当前计划执行,选择"修改计划"将弹出输入框供用户提供调整意见
|
|
109
|
-
- **简化设计**: 移除了复杂的多选项,采用二元选择 + 输入框的设计模式
|
|
110
|
-
|
|
111
|
-
**示例调用**:
|
|
112
|
-
\`\`\`
|
|
113
|
-
调用 dev-feedback 工具,参数:
|
|
114
|
-
{
|
|
115
|
-
"title": "开发计划确认",
|
|
116
|
-
"message": "已分析需求并制定开发计划,包含以下步骤:1)设计数据模型 2)实现API接口 3)编写单元测试 4)集成测试。是否开始实施?",
|
|
117
|
-
"phase": "planning"
|
|
118
|
-
}
|
|
119
|
-
\`\`\`
|
|
120
|
-
|
|
121
|
-
**重要**: 在每个关键节点都要主动请求用户确认,确保开发方向正确。优先使用阶段特定的feedback调用方式。`;
|
|
88
|
+
---
|
|
89
|
+
**当前需求:** ${sourceText}
|
|
90
|
+
---`;
|
|
122
91
|
}
|
|
123
92
|
|
|
124
93
|
/**
|
|
@@ -276,8 +245,6 @@ export async function enhancedDevFeedback(feedbackInput = {}) {
|
|
|
276
245
|
// 简化逻辑:直接传入options,函数内部自动判断场景
|
|
277
246
|
const options = getStandardButtons(feedbackInput.options);
|
|
278
247
|
|
|
279
|
-
console.log('📋 [ENHANCED-FEEDBACK] Applied unified standard buttons:', options);
|
|
280
|
-
|
|
281
248
|
// Standard message processing - no version info in intermediate feedback
|
|
282
249
|
let enhancedMessage = feedbackInput.message;
|
|
283
250
|
|
|
@@ -434,7 +401,7 @@ export async function handleDevTool(toolName, args) {
|
|
|
434
401
|
let versionInfo = '';
|
|
435
402
|
try {
|
|
436
403
|
const info = await getLocalPromptInfo(fileName);
|
|
437
|
-
versionInfo = `\n\n📌
|
|
404
|
+
versionInfo = `\n\n📌 Prompt版本: ${info.version}`;
|
|
438
405
|
} catch (error) {
|
|
439
406
|
console.warn(`[Version] Failed to get version for ${fileName}:`, error.message);
|
|
440
407
|
}
|
|
@@ -501,80 +468,6 @@ When creating directories or referencing dates, always use ${currentDate}.
|
|
|
501
468
|
// Prepend date context to the beginning of the content
|
|
502
469
|
content = dateContextHeader + content;
|
|
503
470
|
|
|
504
|
-
// 🟢 GREEN: 统一注入完整的resources列表(projects + rules)
|
|
505
|
-
try {
|
|
506
|
-
// 动态导入避免循环依赖
|
|
507
|
-
const { formatResourcesList } = await import('./resource-manager.js');
|
|
508
|
-
const { UNIFIED_RESOURCES } = await import('./config.js');
|
|
509
|
-
|
|
510
|
-
// 统一加载完整的projects和rules列表
|
|
511
|
-
const resourcesList = await formatResourcesList(UNIFIED_RESOURCES);
|
|
512
|
-
|
|
513
|
-
// 构建前置内容
|
|
514
|
-
let prefixContent = '---\n\n';
|
|
515
|
-
prefixContent += resourcesList + '\n';
|
|
516
|
-
|
|
517
|
-
if (!automatedMode) {
|
|
518
|
-
// 手动模式:要求通过feedback确认资源选择
|
|
519
|
-
prefixContent += `
|
|
520
|
-
**📋 执行规则 (MANDATORY EXECUTION RULES):**
|
|
521
|
-
|
|
522
|
-
1. **每阶段完成必须反馈**: 完成每个阶段/步骤后,必须调用 \`dev-feedback\` 工具汇报进度并获取确认。
|
|
523
|
-
2. **等待用户确认**: 每次feedback后必须等待用户确认才能继续下一步。
|
|
524
|
-
3. **这是强制要求**: 不是可选项,每个阶段都必须执行。
|
|
525
|
-
|
|
526
|
-
---
|
|
527
|
-
|
|
528
|
-
**🎯 资源确认流程 (RESOURCE CONFIRMATION - auto=false 模式):**
|
|
529
|
-
|
|
530
|
-
在开始详细分析或实施工作之前:
|
|
531
|
-
|
|
532
|
-
1. **审查可用资源**: 仔细查看上方提供的projects和rules资源列表
|
|
533
|
-
2. **分析需求**: 根据需求/任务,判断需要使用哪些资源
|
|
534
|
-
3. **选择资源**:
|
|
535
|
-
- **项目文档 (Projects)**: 选择相关的系统wiki文档
|
|
536
|
-
- **开发规则 (Rules)**: 选择相关的编码规范和标准
|
|
537
|
-
4. **强制确认**: 必须调用 \`dev-feedback\` 工具向用户确认:
|
|
538
|
-
- 需求范围总结
|
|
539
|
-
- 选定的项目文档列表(说明原因)
|
|
540
|
-
- 选定的规则文档列表(说明原因)
|
|
541
|
-
- 询问:"确认范围正确吗?可以继续吗?"
|
|
542
|
-
5. **等待批准**: 在用户确认前不得继续
|
|
543
|
-
6. **加载资源**: 确认后,使用 \`load-resource\` 工具加载已批准的资源
|
|
544
|
-
|
|
545
|
-
**此确认步骤是强制性的且阻塞性的 - 不能跳过。**
|
|
546
|
-
|
|
547
|
-
---
|
|
548
|
-
|
|
549
|
-
`;
|
|
550
|
-
} else {
|
|
551
|
-
// 自动模式:AI自行选择并加载resources
|
|
552
|
-
prefixContent += `
|
|
553
|
-
**📋 AUTO 模式 - 自动资源管理:**
|
|
554
|
-
|
|
555
|
-
系统已提供完整的项目文档和开发规则列表。
|
|
556
|
-
|
|
557
|
-
**工作流程:**
|
|
558
|
-
1. 根据任务需求,自行判断并选择需要的resources
|
|
559
|
-
2. 使用 \`load-resource\` 工具加载选定的资源内容
|
|
560
|
-
3. 所有projects和rules都可用,按需加载
|
|
561
|
-
|
|
562
|
-
**可用资源:**
|
|
563
|
-
- **Projects**: 所有系统项目文档
|
|
564
|
-
- **Rules**: 所有开发规范和标准
|
|
565
|
-
|
|
566
|
-
直接开始分析和实施,根据需要使用 \`load-resource\` 工具。
|
|
567
|
-
|
|
568
|
-
---
|
|
569
|
-
|
|
570
|
-
`;
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
content = prefixContent + content;
|
|
574
|
-
} catch (error) {
|
|
575
|
-
console.warn('[handleDevTool] Failed to inject resources list:', error.message);
|
|
576
|
-
}
|
|
577
|
-
|
|
578
471
|
// 版本信息现在在弹窗中显示,不再添加到response中
|
|
579
472
|
return content;
|
|
580
473
|
}
|
|
@@ -602,9 +495,10 @@ export async function handleDevFeedback(args) {
|
|
|
602
495
|
// 简化逻辑:直接传入options,函数内部自动判断场景
|
|
603
496
|
const finalOptions = getStandardButtons(options.length > 0 ? options : null);
|
|
604
497
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
498
|
+
// 🆕 添加保活机制:在等待用户交互期间定期输出日志
|
|
499
|
+
const keepAliveInterval = setInterval(() => {
|
|
500
|
+
console.error('[MCP-KeepAlive] Waiting for user dialog interaction...');
|
|
501
|
+
}, 15000);
|
|
608
502
|
|
|
609
503
|
try {
|
|
610
504
|
const result = await showConfirmDialog({
|
|
@@ -613,9 +507,10 @@ export async function handleDevFeedback(args) {
|
|
|
613
507
|
buttons: finalOptions
|
|
614
508
|
});
|
|
615
509
|
|
|
510
|
+
clearInterval(keepAliveInterval); // 用户选择后清理定时器
|
|
511
|
+
|
|
616
512
|
// If user selects a "modify" option, automatically show input dialog
|
|
617
513
|
if (result && (result.includes('修改') || result.includes('调整') || result.includes('建议'))) {
|
|
618
|
-
console.log('📝 [INPUT REQUEST] User wants to provide input, showing input dialog...');
|
|
619
514
|
|
|
620
515
|
const userInput = await showInputDialog({
|
|
621
516
|
title: '输入修改建议',
|
|
@@ -624,8 +519,6 @@ export async function handleDevFeedback(args) {
|
|
|
624
519
|
rows: 5 // Use 5-row input for modification suggestions
|
|
625
520
|
});
|
|
626
521
|
|
|
627
|
-
console.log('✅ [USER INPUT]:', userInput);
|
|
628
|
-
|
|
629
522
|
// Return structured feedback with clear indication for AI processing
|
|
630
523
|
return {
|
|
631
524
|
action: result,
|
|
@@ -635,9 +528,9 @@ export async function handleDevFeedback(args) {
|
|
|
635
528
|
requiresAdjustment: true // Flag to indicate AI should adjust execution
|
|
636
529
|
};
|
|
637
530
|
}
|
|
638
|
-
console.log('✅ [USER RESPONSE]:', result);
|
|
639
531
|
return result;
|
|
640
532
|
} catch (error) {
|
|
533
|
+
clearInterval(keepAliveInterval); // 出错时也要清理定时器
|
|
641
534
|
console.error('❌ [FEEDBACK ERROR]:', error.message);
|
|
642
535
|
|
|
643
536
|
// Check if this is a dialog system failure
|
|
@@ -672,30 +565,4 @@ export async function handleDevFeedback(args) {
|
|
|
672
565
|
}
|
|
673
566
|
|
|
674
567
|
// handleDevReload removed - configuration now loads automatically from environment and mcp.json
|
|
675
|
-
// No manual reload needed as per user requirements
|
|
676
|
-
|
|
677
|
-
/**
|
|
678
|
-
* 🟢 GREEN: Handle load-resource tool
|
|
679
|
-
* 加载resource的完整内容
|
|
680
|
-
*/
|
|
681
|
-
export async function handleLoadResource(args) {
|
|
682
|
-
const { resourceName } = args;
|
|
683
|
-
|
|
684
|
-
if (!resourceName) {
|
|
685
|
-
return `❌ Error: resourceName is required`;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
try {
|
|
689
|
-
// 动态导入避免循环依赖
|
|
690
|
-
const { loadResourceContent } = await import('./resource-manager.js');
|
|
691
|
-
const result = await loadResourceContent(resourceName);
|
|
692
|
-
|
|
693
|
-
if (!result.success) {
|
|
694
|
-
return `❌ Error loading resource "${resourceName}": ${result.error}`;
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
return `# Resource: ${result.filename} (${result.type})\n\n${result.content}`;
|
|
698
|
-
} catch (error) {
|
|
699
|
-
return `❌ Error: ${error.message}`;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
568
|
+
// No manual reload needed as per user requirements
|