openspec-mcp 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +83 -35
  2. package/README.zh.md +81 -33
  3. package/dist/api/routes/changes.d.ts.map +1 -1
  4. package/dist/api/routes/changes.js +54 -0
  5. package/dist/api/routes/changes.js.map +1 -1
  6. package/dist/api/routes/project.d.ts +7 -0
  7. package/dist/api/routes/project.d.ts.map +1 -0
  8. package/dist/api/routes/project.js +14 -0
  9. package/dist/api/routes/project.js.map +1 -0
  10. package/dist/api/routes/specs.d.ts.map +1 -1
  11. package/dist/api/routes/specs.js +100 -1
  12. package/dist/api/routes/specs.js.map +1 -1
  13. package/dist/api/routes/tasks.d.ts.map +1 -1
  14. package/dist/api/routes/tasks.js +33 -0
  15. package/dist/api/routes/tasks.js.map +1 -1
  16. package/dist/api/server.d.ts +5 -1
  17. package/dist/api/server.d.ts.map +1 -1
  18. package/dist/api/server.js +107 -14
  19. package/dist/api/server.js.map +1 -1
  20. package/dist/core/approval-manager.test.d.ts +5 -0
  21. package/dist/core/approval-manager.test.d.ts.map +1 -0
  22. package/dist/core/approval-manager.test.js +114 -0
  23. package/dist/core/approval-manager.test.js.map +1 -0
  24. package/dist/core/file-watcher.d.ts.map +1 -1
  25. package/dist/core/file-watcher.js +13 -0
  26. package/dist/core/file-watcher.js.map +1 -1
  27. package/dist/core/hooks-manager.d.ts +43 -0
  28. package/dist/core/hooks-manager.d.ts.map +1 -0
  29. package/dist/core/hooks-manager.js +194 -0
  30. package/dist/core/hooks-manager.js.map +1 -0
  31. package/dist/core/openspec-cli.d.ts +12 -0
  32. package/dist/core/openspec-cli.d.ts.map +1 -1
  33. package/dist/core/openspec-cli.js +85 -0
  34. package/dist/core/openspec-cli.js.map +1 -1
  35. package/dist/core/proposal-generator.d.ts +46 -0
  36. package/dist/core/proposal-generator.d.ts.map +1 -0
  37. package/dist/core/proposal-generator.js +155 -0
  38. package/dist/core/proposal-generator.js.map +1 -0
  39. package/dist/core/review-manager.d.ts +147 -0
  40. package/dist/core/review-manager.d.ts.map +1 -0
  41. package/dist/core/review-manager.js +235 -0
  42. package/dist/core/review-manager.js.map +1 -0
  43. package/dist/core/spec-parser.d.ts +51 -0
  44. package/dist/core/spec-parser.d.ts.map +1 -0
  45. package/dist/core/spec-parser.js +130 -0
  46. package/dist/core/spec-parser.js.map +1 -0
  47. package/dist/core/task-parser.test.d.ts +5 -0
  48. package/dist/core/task-parser.test.d.ts.map +1 -0
  49. package/dist/core/task-parser.test.js +124 -0
  50. package/dist/core/task-parser.test.js.map +1 -0
  51. package/dist/core/template-manager.d.ts +48 -0
  52. package/dist/core/template-manager.d.ts.map +1 -0
  53. package/dist/core/template-manager.js +268 -0
  54. package/dist/core/template-manager.js.map +1 -0
  55. package/dist/index.js +17 -1
  56. package/dist/index.js.map +1 -1
  57. package/dist/server/tools/generator.d.ts +8 -0
  58. package/dist/server/tools/generator.d.ts.map +1 -0
  59. package/dist/server/tools/generator.js +121 -0
  60. package/dist/server/tools/generator.js.map +1 -0
  61. package/dist/server/tools/hooks.d.ts +8 -0
  62. package/dist/server/tools/hooks.d.ts.map +1 -0
  63. package/dist/server/tools/hooks.js +86 -0
  64. package/dist/server/tools/hooks.js.map +1 -0
  65. package/dist/server/tools/management.d.ts.map +1 -1
  66. package/dist/server/tools/management.js +37 -2
  67. package/dist/server/tools/management.js.map +1 -1
  68. package/dist/server/tools/reviews.d.ts +8 -0
  69. package/dist/server/tools/reviews.d.ts.map +1 -0
  70. package/dist/server/tools/reviews.js +178 -0
  71. package/dist/server/tools/reviews.js.map +1 -0
  72. package/dist/server/tools/tasks.d.ts.map +1 -1
  73. package/dist/server/tools/tasks.js +38 -0
  74. package/dist/server/tools/tasks.js.map +1 -1
  75. package/dist/server/tools/templates.d.ts +8 -0
  76. package/dist/server/tools/templates.d.ts.map +1 -0
  77. package/dist/server/tools/templates.js +89 -0
  78. package/dist/server/tools/templates.js.map +1 -0
  79. package/dist/utils/constants.d.ts +54 -0
  80. package/dist/utils/constants.d.ts.map +1 -0
  81. package/dist/utils/constants.js +54 -0
  82. package/dist/utils/constants.js.map +1 -0
  83. package/dist/utils/version.d.ts +13 -0
  84. package/dist/utils/version.d.ts.map +1 -0
  85. package/dist/utils/version.js +26 -0
  86. package/dist/utils/version.js.map +1 -0
  87. package/package.json +2 -6
  88. package/web/dist/assets/index-BGNTCJhf.css +1 -0
  89. package/web/dist/assets/index-DKBVRb7-.js +99 -0
  90. package/web/dist/index.html +2 -2
  91. package/web/dist/assets/index--LppUKpS.js +0 -67
  92. package/web/dist/assets/index-DdJQfs9Z.css +0 -1
@@ -0,0 +1,124 @@
1
+ /**
2
+ * TaskParser 单元测试
3
+ */
4
+ import { describe, it, expect } from 'vitest';
5
+ import { TaskParser } from './task-parser.js';
6
+ describe('TaskParser', () => {
7
+ const parser = new TaskParser();
8
+ describe('parseTasksFromContent', () => {
9
+ it('should parse tasks with ID format', () => {
10
+ const content = `
11
+ ## Implementation
12
+
13
+ - [x] **1.1** Complete the first task
14
+ - [ ] **1.2** Do the second task
15
+ - [-] **1.3** Working on third task
16
+ `;
17
+ const tasks = parser.parseTasksFromContent(content);
18
+ expect(tasks).toHaveLength(3);
19
+ expect(tasks[0]).toMatchObject({
20
+ id: '1.1',
21
+ section: 'Implementation',
22
+ title: 'Complete the first task',
23
+ status: 'done',
24
+ });
25
+ expect(tasks[1]).toMatchObject({
26
+ id: '1.2',
27
+ section: 'Implementation',
28
+ title: 'Do the second task',
29
+ status: 'pending',
30
+ });
31
+ expect(tasks[2]).toMatchObject({
32
+ id: '1.3',
33
+ section: 'Implementation',
34
+ title: 'Working on third task',
35
+ status: 'in_progress',
36
+ });
37
+ });
38
+ it('should parse simple tasks without ID', () => {
39
+ const content = `
40
+ ## Tasks
41
+
42
+ - [x] First simple task
43
+ - [ ] Second simple task
44
+ `;
45
+ const tasks = parser.parseTasksFromContent(content);
46
+ expect(tasks).toHaveLength(2);
47
+ expect(tasks[0].title).toBe('First simple task');
48
+ expect(tasks[0].status).toBe('done');
49
+ expect(tasks[0].id).toMatch(/^line-\d+$/);
50
+ expect(tasks[1].title).toBe('Second simple task');
51
+ expect(tasks[1].status).toBe('pending');
52
+ });
53
+ it('should handle nested task IDs', () => {
54
+ const content = `
55
+ ## Phase 1
56
+
57
+ - [x] **1.1** Main task
58
+ - [ ] **1.1.1** Sub task
59
+ - [ ] **1.1.2** Another sub task
60
+ `;
61
+ const tasks = parser.parseTasksFromContent(content);
62
+ expect(tasks).toHaveLength(3);
63
+ expect(tasks[0].id).toBe('1.1');
64
+ expect(tasks[1].id).toBe('1.1.1');
65
+ expect(tasks[2].id).toBe('1.1.2');
66
+ });
67
+ it('should handle multiple sections', () => {
68
+ const content = `
69
+ ## Phase 1
70
+
71
+ - [x] **1.1** Task in phase 1
72
+
73
+ ## Phase 2
74
+
75
+ - [ ] **2.1** Task in phase 2
76
+ `;
77
+ const tasks = parser.parseTasksFromContent(content);
78
+ expect(tasks).toHaveLength(2);
79
+ expect(tasks[0].section).toBe('Phase 1');
80
+ expect(tasks[1].section).toBe('Phase 2');
81
+ });
82
+ it('should return empty array for content with no tasks', () => {
83
+ const content = `
84
+ # Just a title
85
+
86
+ Some text without any tasks.
87
+ `;
88
+ const tasks = parser.parseTasksFromContent(content);
89
+ expect(tasks).toHaveLength(0);
90
+ });
91
+ });
92
+ describe('calculateProgress', () => {
93
+ it('should calculate progress correctly', () => {
94
+ const tasks = [
95
+ { id: '1.1', section: '', title: 'Task 1', status: 'done', line: 1 },
96
+ { id: '1.2', section: '', title: 'Task 2', status: 'done', line: 2 },
97
+ { id: '1.3', section: '', title: 'Task 3', status: 'in_progress', line: 3 },
98
+ { id: '1.4', section: '', title: 'Task 4', status: 'pending', line: 4 },
99
+ ];
100
+ const progress = parser.calculateProgress(tasks);
101
+ expect(progress.total).toBe(4);
102
+ expect(progress.completed).toBe(2);
103
+ expect(progress.inProgress).toBe(1);
104
+ expect(progress.pending).toBe(1);
105
+ expect(progress.percentage).toBe(50);
106
+ });
107
+ it('should handle empty task list', () => {
108
+ const progress = parser.calculateProgress([]);
109
+ expect(progress.total).toBe(0);
110
+ expect(progress.completed).toBe(0);
111
+ expect(progress.percentage).toBe(0);
112
+ });
113
+ it('should round percentage correctly', () => {
114
+ const tasks = [
115
+ { id: '1.1', section: '', title: 'Task 1', status: 'done', line: 1 },
116
+ { id: '1.2', section: '', title: 'Task 2', status: 'pending', line: 2 },
117
+ { id: '1.3', section: '', title: 'Task 3', status: 'pending', line: 3 },
118
+ ];
119
+ const progress = parser.calculateProgress(tasks);
120
+ expect(progress.percentage).toBe(33); // 1/3 = 33.33... rounded to 33
121
+ });
122
+ });
123
+ });
124
+ //# sourceMappingURL=task-parser.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-parser.test.js","sourceRoot":"","sources":["../../src/core/task-parser.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * 模板管理器
3
+ * 管理 Change 模板的创建和使用
4
+ */
5
+ export interface TemplateFiles {
6
+ proposal: string;
7
+ tasks: string;
8
+ design?: string;
9
+ }
10
+ export interface TemplateInfo {
11
+ name: string;
12
+ description: string;
13
+ files: string[];
14
+ }
15
+ export declare class TemplateManager {
16
+ private cwd;
17
+ constructor(options?: {
18
+ cwd?: string;
19
+ });
20
+ /**
21
+ * 获取 openspec 目录
22
+ */
23
+ private getOpenSpecDir;
24
+ /**
25
+ * 获取模板目录
26
+ */
27
+ private getTemplatesDir;
28
+ /**
29
+ * 列出所有可用模板
30
+ */
31
+ listTemplates(): Promise<TemplateInfo[]>;
32
+ /**
33
+ * 获取模板内容
34
+ */
35
+ getTemplate(name: string): Promise<TemplateFiles | null>;
36
+ /**
37
+ * 创建新的 Change
38
+ */
39
+ createChange(changeId: string, options?: {
40
+ template?: string;
41
+ title?: string;
42
+ }): Promise<{
43
+ success: boolean;
44
+ path?: string;
45
+ error?: string;
46
+ }>;
47
+ }
48
+ //# sourceMappingURL=template-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-manager.d.ts","sourceRoot":"","sources":["../../src/core/template-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAuJD,qBAAa,eAAe;IAC1B,OAAO,CAAC,GAAG,CAAS;gBAER,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE;IAItC;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAkC9C;;OAEG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAuB9D;;OAEG;IACG,YAAY,CAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9C,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAmDhE"}
@@ -0,0 +1,268 @@
1
+ /**
2
+ * 模板管理器
3
+ * 管理 Change 模板的创建和使用
4
+ */
5
+ import * as fs from 'fs/promises';
6
+ import * as path from 'path';
7
+ /**
8
+ * 默认模板定义
9
+ */
10
+ const DEFAULT_TEMPLATES = {
11
+ feature: {
12
+ description: 'New feature implementation',
13
+ files: {
14
+ proposal: `# Feature: {title}
15
+
16
+ ## Summary
17
+
18
+ Brief description of the feature.
19
+
20
+ ## Motivation
21
+
22
+ Why is this feature needed?
23
+
24
+ ## Proposed Solution
25
+
26
+ High-level description of the solution.
27
+
28
+ ## Alternatives Considered
29
+
30
+ Other approaches that were considered.
31
+
32
+ ## Impact
33
+
34
+ - [ ] Breaking changes
35
+ - [ ] Database migrations
36
+ - [ ] API changes
37
+ `,
38
+ tasks: `# Tasks for {title}
39
+
40
+ ## 1. Planning
41
+
42
+ - [ ] **1.1** Review requirements
43
+ - [ ] **1.2** Design API/interface
44
+
45
+ ## 2. Implementation
46
+
47
+ - [ ] **2.1** Implement core logic
48
+ - [ ] **2.2** Add error handling
49
+ - [ ] **2.3** Write unit tests
50
+
51
+ ## 3. Integration
52
+
53
+ - [ ] **3.1** Integration testing
54
+ - [ ] **3.2** Documentation
55
+ - [ ] **3.3** Code review
56
+ `,
57
+ },
58
+ },
59
+ bugfix: {
60
+ description: 'Bug fix',
61
+ files: {
62
+ proposal: `# Bugfix: {title}
63
+
64
+ ## Bug Description
65
+
66
+ What is the bug?
67
+
68
+ ## Steps to Reproduce
69
+
70
+ 1. Step 1
71
+ 2. Step 2
72
+ 3. Observe error
73
+
74
+ ## Expected Behavior
75
+
76
+ What should happen?
77
+
78
+ ## Root Cause
79
+
80
+ Analysis of why the bug occurs.
81
+
82
+ ## Proposed Fix
83
+
84
+ How will the bug be fixed?
85
+ `,
86
+ tasks: `# Tasks for {title}
87
+
88
+ ## 1. Investigation
89
+
90
+ - [ ] **1.1** Reproduce the bug
91
+ - [ ] **1.2** Identify root cause
92
+
93
+ ## 2. Fix
94
+
95
+ - [ ] **2.1** Implement fix
96
+ - [ ] **2.2** Add regression test
97
+
98
+ ## 3. Verification
99
+
100
+ - [ ] **3.1** Verify fix works
101
+ - [ ] **3.2** Check for side effects
102
+ - [ ] **3.3** Code review
103
+ `,
104
+ },
105
+ },
106
+ refactor: {
107
+ description: 'Code refactoring',
108
+ files: {
109
+ proposal: `# Refactor: {title}
110
+
111
+ ## Current State
112
+
113
+ Description of the current implementation.
114
+
115
+ ## Problems
116
+
117
+ What issues does the current implementation have?
118
+
119
+ ## Proposed Changes
120
+
121
+ How will the code be refactored?
122
+
123
+ ## Benefits
124
+
125
+ - Improved maintainability
126
+ - Better performance
127
+ - Cleaner code
128
+
129
+ ## Risks
130
+
131
+ Potential risks and mitigation strategies.
132
+ `,
133
+ tasks: `# Tasks for {title}
134
+
135
+ ## 1. Preparation
136
+
137
+ - [ ] **1.1** Ensure test coverage
138
+ - [ ] **1.2** Document current behavior
139
+
140
+ ## 2. Refactoring
141
+
142
+ - [ ] **2.1** Extract/rename components
143
+ - [ ] **2.2** Simplify logic
144
+ - [ ] **2.3** Update tests
145
+
146
+ ## 3. Validation
147
+
148
+ - [ ] **3.1** Run all tests
149
+ - [ ] **3.2** Performance check
150
+ - [ ] **3.3** Code review
151
+ `,
152
+ },
153
+ },
154
+ };
155
+ export class TemplateManager {
156
+ cwd;
157
+ constructor(options) {
158
+ this.cwd = options?.cwd || process.cwd();
159
+ }
160
+ /**
161
+ * 获取 openspec 目录
162
+ */
163
+ getOpenSpecDir() {
164
+ return path.join(this.cwd, 'openspec');
165
+ }
166
+ /**
167
+ * 获取模板目录
168
+ */
169
+ getTemplatesDir() {
170
+ return path.join(this.getOpenSpecDir(), 'templates');
171
+ }
172
+ /**
173
+ * 列出所有可用模板
174
+ */
175
+ async listTemplates() {
176
+ const templates = [];
177
+ // 添加内置模板
178
+ for (const [name, template] of Object.entries(DEFAULT_TEMPLATES)) {
179
+ templates.push({
180
+ name,
181
+ description: template.description,
182
+ files: Object.keys(template.files),
183
+ });
184
+ }
185
+ // 检查自定义模板
186
+ try {
187
+ const templatesDir = this.getTemplatesDir();
188
+ const entries = await fs.readdir(templatesDir, { withFileTypes: true });
189
+ for (const entry of entries) {
190
+ if (entry.isDirectory() && !DEFAULT_TEMPLATES[entry.name]) {
191
+ const files = await fs.readdir(path.join(templatesDir, entry.name));
192
+ templates.push({
193
+ name: entry.name,
194
+ description: 'Custom template',
195
+ files: files.filter((f) => f.endsWith('.md')),
196
+ });
197
+ }
198
+ }
199
+ }
200
+ catch {
201
+ // 模板目录不存在
202
+ }
203
+ return templates;
204
+ }
205
+ /**
206
+ * 获取模板内容
207
+ */
208
+ async getTemplate(name) {
209
+ // 先检查内置模板
210
+ if (DEFAULT_TEMPLATES[name]) {
211
+ return DEFAULT_TEMPLATES[name].files;
212
+ }
213
+ // 检查自定义模板
214
+ const templateDir = path.join(this.getTemplatesDir(), name);
215
+ try {
216
+ const proposal = await fs.readFile(path.join(templateDir, 'proposal.md'), 'utf-8');
217
+ const tasks = await fs.readFile(path.join(templateDir, 'tasks.md'), 'utf-8');
218
+ let design;
219
+ try {
220
+ design = await fs.readFile(path.join(templateDir, 'design.md'), 'utf-8');
221
+ }
222
+ catch {
223
+ // design.md 是可选的
224
+ }
225
+ return { proposal, tasks, design };
226
+ }
227
+ catch {
228
+ return null;
229
+ }
230
+ }
231
+ /**
232
+ * 创建新的 Change
233
+ */
234
+ async createChange(changeId, options) {
235
+ const templateName = options?.template || 'feature';
236
+ const title = options?.title || changeId;
237
+ // 获取模板
238
+ const template = await this.getTemplate(templateName);
239
+ if (!template) {
240
+ return { success: false, error: `Template not found: ${templateName}` };
241
+ }
242
+ // 创建 change 目录
243
+ const changeDir = path.join(this.getOpenSpecDir(), 'changes', changeId);
244
+ try {
245
+ await fs.access(changeDir);
246
+ return { success: false, error: `Change already exists: ${changeId}` };
247
+ }
248
+ catch {
249
+ // 目录不存在,可以创建
250
+ }
251
+ try {
252
+ await fs.mkdir(changeDir, { recursive: true });
253
+ // 替换模板中的占位符
254
+ const replacePlaceholders = (content) => content.replace(/\{title\}/g, title).replace(/\{changeId\}/g, changeId);
255
+ // 写入文件
256
+ await fs.writeFile(path.join(changeDir, 'proposal.md'), replacePlaceholders(template.proposal), 'utf-8');
257
+ await fs.writeFile(path.join(changeDir, 'tasks.md'), replacePlaceholders(template.tasks), 'utf-8');
258
+ if (template.design) {
259
+ await fs.writeFile(path.join(changeDir, 'design.md'), replacePlaceholders(template.design), 'utf-8');
260
+ }
261
+ return { success: true, path: changeDir };
262
+ }
263
+ catch (error) {
264
+ return { success: false, error: error.message };
265
+ }
266
+ }
267
+ }
268
+ //# sourceMappingURL=template-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-manager.js","sourceRoot":"","sources":["../../src/core/template-manager.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -10,13 +10,21 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
10
10
  import { Command } from 'commander';
11
11
  import { OpenSpecCli } from './core/openspec-cli.js';
12
12
  import { ApprovalManager } from './core/approval-manager.js';
13
+ import { ReviewManager } from './core/review-manager.js';
14
+ import { TemplateManager } from './core/template-manager.js';
15
+ import { HooksManager } from './core/hooks-manager.js';
16
+ import { ProposalGenerator } from './core/proposal-generator.js';
13
17
  import { registerGuidesTools } from './server/tools/guides.js';
14
18
  import { registerManagementTools } from './server/tools/management.js';
15
19
  import { registerValidationTools } from './server/tools/validation.js';
16
20
  import { registerArchiveTools } from './server/tools/archive.js';
17
21
  import { registerTasksTools } from './server/tools/tasks.js';
18
22
  import { registerApprovalTools } from './server/tools/approval.js';
19
- const VERSION = '0.1.0';
23
+ import { registerReviewTools } from './server/tools/reviews.js';
24
+ import { registerTemplatesTools } from './server/tools/templates.js';
25
+ import { registerHooksTools } from './server/tools/hooks.js';
26
+ import { registerGeneratorTools } from './server/tools/generator.js';
27
+ import { VERSION } from './utils/version.js';
20
28
  /**
21
29
  * 创建并配置 MCP Server
22
30
  */
@@ -28,6 +36,10 @@ function createMcpServer(cwd) {
28
36
  // 创建核心模块实例
29
37
  const cli = new OpenSpecCli({ cwd });
30
38
  const approvalManager = new ApprovalManager({ cwd });
39
+ const reviewManager = new ReviewManager({ cwd });
40
+ const templateManager = new TemplateManager({ cwd });
41
+ const hooksManager = new HooksManager({ cwd });
42
+ const proposalGenerator = new ProposalGenerator({ cwd });
31
43
  // 注册所有工具
32
44
  registerGuidesTools(server, cli);
33
45
  registerManagementTools(server, cli);
@@ -35,6 +47,10 @@ function createMcpServer(cwd) {
35
47
  registerArchiveTools(server, cli);
36
48
  registerTasksTools(server, cli);
37
49
  registerApprovalTools(server, approvalManager);
50
+ registerReviewTools(server, reviewManager);
51
+ registerTemplatesTools(server, templateManager);
52
+ registerHooksTools(server, hooksManager);
53
+ registerGeneratorTools(server, proposalGenerator);
38
54
  return server;
39
55
  }
40
56
  /**
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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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Generator 类工具
3
+ * AI 辅助生成 Proposal
4
+ */
5
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
6
+ import { ProposalGenerator } from '../../core/proposal-generator.js';
7
+ export declare function registerGeneratorTools(server: McpServer, proposalGenerator: ProposalGenerator): void;
8
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../src/server/tools/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAErE,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,EACjB,iBAAiB,EAAE,iBAAiB,GACnC,IAAI,CAyIN"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Generator 类工具
3
+ * AI 辅助生成 Proposal
4
+ */
5
+ import { z } from 'zod';
6
+ export function registerGeneratorTools(server, proposalGenerator) {
7
+ /**
8
+ * 准备生成 proposal(返回 prompt 供 AI 使用)
9
+ */
10
+ server.tool('openspec_prepare_proposal', 'Prepare context and prompt for generating a proposal from a requirement', {
11
+ requirement: z
12
+ .string()
13
+ .describe('Description of the feature or change requirement'),
14
+ }, async ({ requirement }) => {
15
+ const result = await proposalGenerator.prepareGeneration(requirement);
16
+ let text = `# Proposal Generation Prepared\n\n`;
17
+ text += `**Suggested Change ID**: \`${result.suggestedId}\`\n\n`;
18
+ text += `## Context Gathered\n\n`;
19
+ text += result.context || '_No project context found_';
20
+ text += `\n\n## Generation Prompt\n\n`;
21
+ text += `Use the following prompt to generate the proposal:\n\n`;
22
+ text += '```\n' + result.prompt + '\n```\n';
23
+ return {
24
+ content: [{ type: 'text', text }],
25
+ };
26
+ });
27
+ /**
28
+ * 保存生成的 proposal
29
+ */
30
+ server.tool('openspec_save_proposal', 'Save a generated proposal and tasks to a new change', {
31
+ changeId: z
32
+ .string()
33
+ .describe('Change ID (kebab-case, e.g., add-user-auth)'),
34
+ proposal: z.string().describe('Content of proposal.md'),
35
+ tasks: z.string().describe('Content of tasks.md'),
36
+ }, async ({ changeId, proposal, tasks }) => {
37
+ const result = await proposalGenerator.saveDraft(changeId, proposal, tasks);
38
+ if (result.success) {
39
+ return {
40
+ content: [
41
+ {
42
+ type: 'text',
43
+ text: `✅ Saved proposal to: ${result.path}\n\nCreated files:\n- proposal.md\n- tasks.md`,
44
+ },
45
+ ],
46
+ };
47
+ }
48
+ else {
49
+ return {
50
+ content: [
51
+ {
52
+ type: 'text',
53
+ text: `❌ Failed to save: ${result.error}`,
54
+ },
55
+ ],
56
+ isError: true,
57
+ };
58
+ }
59
+ });
60
+ /**
61
+ * 一站式生成并保存(返回示例,需 AI 填充内容)
62
+ */
63
+ server.tool('openspec_generate_proposal', 'Generate a proposal from requirement description (returns template for AI to complete)', {
64
+ requirement: z
65
+ .string()
66
+ .describe('Description of the feature or change requirement'),
67
+ changeId: z
68
+ .string()
69
+ .optional()
70
+ .describe('Optional custom change ID'),
71
+ }, async ({ requirement, changeId }) => {
72
+ const preparation = await proposalGenerator.prepareGeneration(requirement);
73
+ const finalId = changeId || preparation.suggestedId;
74
+ // 生成模板(AI 应该替换这些内容)
75
+ const proposalTemplate = `# ${requirement}
76
+
77
+ ## Summary
78
+
79
+ [AI: Write a brief summary based on the requirement]
80
+
81
+ ## Motivation
82
+
83
+ [AI: Explain why this change is needed]
84
+
85
+ ## Proposed Solution
86
+
87
+ [AI: Describe the high-level solution]
88
+
89
+ ## Impact
90
+
91
+ - [ ] Breaking changes: [AI: List any breaking changes]
92
+ - [ ] Dependencies: [AI: List affected dependencies]
93
+ `;
94
+ const tasksTemplate = `# Tasks for ${requirement}
95
+
96
+ ## 1. Planning
97
+
98
+ - [ ] **1.1** [AI: Add planning tasks]
99
+
100
+ ## 2. Implementation
101
+
102
+ - [ ] **2.1** [AI: Add implementation tasks]
103
+ - [ ] **2.2** [AI: Add more tasks as needed]
104
+
105
+ ## 3. Verification
106
+
107
+ - [ ] **3.1** [AI: Add verification tasks]
108
+ `;
109
+ let text = `# Proposal Generation for: ${finalId}\n\n`;
110
+ text += `## Suggested Change ID\n\n\`${finalId}\`\n\n`;
111
+ text += `## Context\n\n${preparation.context || '_No project context_'}\n\n`;
112
+ text += `## Template proposal.md\n\n\`\`\`markdown\n${proposalTemplate}\`\`\`\n\n`;
113
+ text += `## Template tasks.md\n\n\`\`\`markdown\n${tasksTemplate}\`\`\`\n\n`;
114
+ text += `---\n\n`;
115
+ text += `**Next step**: Review and fill in the [AI: ...] placeholders, then use \`openspec_save_proposal\` to save.\n`;
116
+ return {
117
+ content: [{ type: 'text', text }],
118
+ };
119
+ });
120
+ }
121
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../src/server/tools/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Hooks 类工具
3
+ * Git hooks 管理
4
+ */
5
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
6
+ import { HooksManager } from '../../core/hooks-manager.js';
7
+ export declare function registerHooksTools(server: McpServer, hooksManager: HooksManager): void;
8
+ //# sourceMappingURL=hooks.d.ts.map