sdd-mcp-server 1.1.21 → 1.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.
- package/README.md +67 -30
- package/dist/adapters/cli/SDDToolAdapter.d.ts +22 -1
- package/dist/adapters/cli/SDDToolAdapter.js +399 -17
- package/dist/adapters/cli/SDDToolAdapter.js.map +1 -1
- package/dist/application/services/TemplateService.d.ts +17 -0
- package/dist/application/services/TemplateService.js +367 -24
- package/dist/application/services/TemplateService.js.map +1 -1
- package/dist/index.js +1210 -13
- package/dist/index.js.map +1 -1
- package/mcp-server.js +1501 -0
- package/package.json +3 -3
- package/minimal-working-server.js +0 -66
package/mcp-server.js
ADDED
|
@@ -0,0 +1,1501 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import fs from 'fs/promises';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
const server = new McpServer({
|
|
9
|
+
name: 'sdd-mcp-server',
|
|
10
|
+
version: '1.1.21'
|
|
11
|
+
}, {
|
|
12
|
+
instructions: 'Use this server for spec-driven development workflows'
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// Helper functions for file operations
|
|
16
|
+
async function createKiroDirectory(projectPath) {
|
|
17
|
+
const kiroPath = path.join(projectPath, '.kiro');
|
|
18
|
+
const specsPath = path.join(kiroPath, 'specs');
|
|
19
|
+
const steeringPath = path.join(kiroPath, 'steering');
|
|
20
|
+
|
|
21
|
+
await fs.mkdir(kiroPath, { recursive: true });
|
|
22
|
+
await fs.mkdir(specsPath, { recursive: true });
|
|
23
|
+
await fs.mkdir(steeringPath, { recursive: true });
|
|
24
|
+
|
|
25
|
+
return { kiroPath, specsPath, steeringPath };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function generateFeatureName(description) {
|
|
29
|
+
// Simple feature name generation from description
|
|
30
|
+
return description.toLowerCase()
|
|
31
|
+
.replace(/[^a-z0-9\s]/g, '')
|
|
32
|
+
.replace(/\s+/g, '-')
|
|
33
|
+
.substring(0, 50);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function getCurrentTimestamp() {
|
|
37
|
+
return new Date().toISOString();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Register all SDD tools matching README and kiro command templates
|
|
41
|
+
|
|
42
|
+
// 1. sdd-init - Initialize new SDD project
|
|
43
|
+
server.registerTool("sdd-init", {
|
|
44
|
+
title: "Initialize SDD Project",
|
|
45
|
+
description: "Initialize a new SDD project",
|
|
46
|
+
inputSchema: {
|
|
47
|
+
projectName: z.string().describe('The name of the project to initialize'),
|
|
48
|
+
description: z.string().optional().describe('Optional project description')
|
|
49
|
+
},
|
|
50
|
+
}, async ({ projectName, description = '' }) => {
|
|
51
|
+
try {
|
|
52
|
+
const currentPath = process.cwd();
|
|
53
|
+
|
|
54
|
+
// Create .kiro directory structure in current directory (not in a subdirectory)
|
|
55
|
+
const { specsPath, steeringPath } = await createKiroDirectory(currentPath);
|
|
56
|
+
|
|
57
|
+
// Generate feature name from description
|
|
58
|
+
const featureName = await generateFeatureName(description || projectName);
|
|
59
|
+
const featurePath = path.join(specsPath, featureName);
|
|
60
|
+
await fs.mkdir(featurePath, { recursive: true });
|
|
61
|
+
|
|
62
|
+
// Create spec.json
|
|
63
|
+
const specJson = {
|
|
64
|
+
"feature_name": featureName,
|
|
65
|
+
"created_at": await getCurrentTimestamp(),
|
|
66
|
+
"updated_at": await getCurrentTimestamp(),
|
|
67
|
+
"language": "en",
|
|
68
|
+
"phase": "initialized",
|
|
69
|
+
"approvals": {
|
|
70
|
+
"requirements": {
|
|
71
|
+
"generated": false,
|
|
72
|
+
"approved": false
|
|
73
|
+
},
|
|
74
|
+
"design": {
|
|
75
|
+
"generated": false,
|
|
76
|
+
"approved": false
|
|
77
|
+
},
|
|
78
|
+
"tasks": {
|
|
79
|
+
"generated": false,
|
|
80
|
+
"approved": false
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"ready_for_implementation": false
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
await fs.writeFile(path.join(featurePath, 'spec.json'), JSON.stringify(specJson, null, 2));
|
|
87
|
+
|
|
88
|
+
// Create requirements.md template
|
|
89
|
+
const requirementsTemplate = `# Requirements Document\n\n## Project Description (Input)\n${description}\n\n## Requirements\n<!-- Will be generated in /kiro:spec-requirements phase -->`;
|
|
90
|
+
await fs.writeFile(path.join(featurePath, 'requirements.md'), requirementsTemplate);
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
content: [{
|
|
94
|
+
type: 'text',
|
|
95
|
+
text: `## Spec Initialization Complete\n\n**Generated Feature Name**: ${featureName}\n**Project Name**: ${projectName}\n**Project Description**: ${description}\n\n**Created Files**:\n- \`.kiro/specs/${featureName}/spec.json\` - Metadata and approval tracking\n- \`.kiro/specs/${featureName}/requirements.md\` - Requirements template\n\n**Next Step**: Use \`sdd-requirements ${featureName}\` to generate comprehensive requirements\n\nThe spec has been initialized following stage-by-stage development principles.`
|
|
96
|
+
}]
|
|
97
|
+
};
|
|
98
|
+
} catch (error) {
|
|
99
|
+
return {
|
|
100
|
+
content: [{
|
|
101
|
+
type: 'text',
|
|
102
|
+
text: `Error initializing SDD project: ${error.message}`
|
|
103
|
+
}]
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// 2. sdd-requirements - Generate requirements doc
|
|
109
|
+
server.registerTool("sdd-requirements", {
|
|
110
|
+
title: "Generate Requirements Document",
|
|
111
|
+
description: "Generate requirements doc",
|
|
112
|
+
inputSchema: {
|
|
113
|
+
featureName: z.string().describe('Feature name from spec initialization')
|
|
114
|
+
},
|
|
115
|
+
}, async ({ featureName }) => {
|
|
116
|
+
try {
|
|
117
|
+
const currentPath = process.cwd();
|
|
118
|
+
const featurePath = path.join(currentPath, '.kiro', 'specs', featureName);
|
|
119
|
+
|
|
120
|
+
// Check if spec exists
|
|
121
|
+
const specPath = path.join(featurePath, 'spec.json');
|
|
122
|
+
const specExists = await fs.access(specPath).then(() => true).catch(() => false);
|
|
123
|
+
if (!specExists) {
|
|
124
|
+
return {
|
|
125
|
+
content: [{
|
|
126
|
+
type: 'text',
|
|
127
|
+
text: `Error: Spec not found for feature "${featureName}". Use sdd-init first.`
|
|
128
|
+
}]
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Read existing spec
|
|
133
|
+
const specContent = await fs.readFile(specPath, 'utf8');
|
|
134
|
+
const spec = JSON.parse(specContent);
|
|
135
|
+
|
|
136
|
+
// Generate EARS-format requirements
|
|
137
|
+
const requirementsContent = `# Requirements Document\n\n## Introduction\nThis feature delivers comprehensive spec-driven development workflow capabilities to AI development teams.\n\n## Requirements\n\n### Requirement 1: Project Initialization\n**Objective:** As a developer, I want to initialize SDD projects with proper structure, so that I can follow structured development workflows\n\n#### Acceptance Criteria\n1. WHEN a user runs sdd-init THEN the system SHALL create .kiro directory structure\n2. WHEN initialization occurs THEN the system SHALL generate spec.json with metadata\n3. WHEN project is created THEN the system SHALL create requirements.md template\n4. WHERE .kiro directory exists THE system SHALL track project state and approvals\n\n### Requirement 2: Requirements Generation\n**Objective:** As a developer, I want to generate comprehensive requirements, so that I can clearly define project scope\n\n1. WHEN requirements are requested THEN the system SHALL generate EARS-format acceptance criteria\n2. IF project description exists THEN the system SHALL incorporate it into requirements\n3. WHILE requirements are being generated THE system SHALL follow structured documentation patterns\n\n### Requirement 3: Workflow Phase Management\n**Objective:** As a developer, I want phase-based workflow control, so that I can ensure proper development progression\n\n1. WHEN each phase completes THEN the system SHALL require approval before proceeding\n2. IF approvals are missing THEN the system SHALL block phase transitions\n3. WHERE workflow violations occur THE system SHALL provide clear guidance`;
|
|
138
|
+
|
|
139
|
+
await fs.writeFile(path.join(featurePath, 'requirements.md'), requirementsContent);
|
|
140
|
+
|
|
141
|
+
// Update spec.json
|
|
142
|
+
spec.phase = "requirements-generated";
|
|
143
|
+
spec.approvals.requirements.generated = true;
|
|
144
|
+
spec.updated_at = await getCurrentTimestamp();
|
|
145
|
+
|
|
146
|
+
await fs.writeFile(specPath, JSON.stringify(spec, null, 2));
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
content: [{
|
|
150
|
+
type: 'text',
|
|
151
|
+
text: `## Requirements Generated\n\nRequirements document generated for feature: **${featureName}**\n\n**Generated**: .kiro/specs/${featureName}/requirements.md\n**Status**: Requirements phase completed\n\n**Next Step**: Review the requirements, then use \`sdd-design\` to proceed to design phase`
|
|
152
|
+
}]
|
|
153
|
+
};
|
|
154
|
+
} catch (error) {
|
|
155
|
+
return {
|
|
156
|
+
content: [{
|
|
157
|
+
type: 'text',
|
|
158
|
+
text: `Error generating requirements: ${error.message}`
|
|
159
|
+
}]
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// 3. sdd-design - Create design specifications
|
|
165
|
+
server.registerTool("sdd-design", {
|
|
166
|
+
title: "Create Design Specifications",
|
|
167
|
+
description: "Create design specifications",
|
|
168
|
+
inputSchema: {
|
|
169
|
+
featureName: z.string().describe('Feature name from spec initialization')
|
|
170
|
+
},
|
|
171
|
+
}, async ({ featureName }) => {
|
|
172
|
+
try {
|
|
173
|
+
const currentPath = process.cwd();
|
|
174
|
+
const featurePath = path.join(currentPath, '.kiro', 'specs', featureName);
|
|
175
|
+
const specPath = path.join(featurePath, 'spec.json');
|
|
176
|
+
|
|
177
|
+
// Read and validate spec
|
|
178
|
+
const specContent = await fs.readFile(specPath, 'utf8');
|
|
179
|
+
const spec = JSON.parse(specContent);
|
|
180
|
+
|
|
181
|
+
if (!spec.approvals.requirements.generated) {
|
|
182
|
+
return {
|
|
183
|
+
content: [{
|
|
184
|
+
type: 'text',
|
|
185
|
+
text: `Error: Requirements must be generated before design. Run \`sdd-requirements ${featureName}\` first.`
|
|
186
|
+
}]
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Generate design document
|
|
191
|
+
const designContent = `# Technical Design Document\n\n## Overview\n\n**Purpose**: This feature delivers comprehensive MCP server capabilities for spec-driven development workflows to AI development teams.\n\n**Users**: AI developers and development teams will utilize this for structured project development.\n\n**Impact**: Transforms ad-hoc development into systematic, phase-based workflows with quality gates.\n\n### Goals\n- Provide complete SDD workflow automation\n- Ensure quality through Linus-style code review\n- Enable multi-language development support\n- Integrate seamlessly with AI development tools\n\n### Non-Goals\n- Real-time collaboration features\n- Deployment automation\n- Version control integration\n\n## Architecture\n\n### High-Level Architecture\n\n\`\`\`mermaid\ngraph TB\n A[AI Client] --> B[MCP Server]\n B --> C[SDD Workflow Engine]\n C --> D[Project Management]\n C --> E[Template System]\n C --> F[Quality Analysis]\n D --> G[File System]\n E --> G\n F --> G\n\`\`\`\n\n### Technology Stack\n\n**Runtime**: Node.js with ES modules\n**Protocol**: Model Context Protocol (MCP)\n**Templates**: Handlebars-based generation\n**Quality**: AST-based code analysis\n**Storage**: File-based project persistence\n\n### Key Design Decisions\n\n**Decision**: Use MCP protocol for AI tool integration\n**Context**: Need seamless integration with Claude Code and other AI development tools\n**Alternatives**: REST API, GraphQL, custom protocol\n**Selected Approach**: MCP provides standardized AI tool integration\n**Rationale**: Direct integration with AI development workflows\n**Trade-offs**: Protocol-specific but optimized for AI use cases\n\n## Components and Interfaces\n\n### SDD Workflow Engine\n\n**Responsibility**: Manages 5-phase workflow state transitions\n**Domain Boundary**: Workflow orchestration and validation\n**Data Ownership**: Phase state, approval tracking, transition rules\n\n**Contract Definition**:\n\`\`\`typescript\ninterface SDDWorkflowEngine {\n initializeProject(name: string, description: string): ProjectSpec;\n generateRequirements(featureName: string): RequirementsDoc;\n generateDesign(featureName: string): DesignDoc;\n generateTasks(featureName: string): TasksDoc;\n checkQuality(code: string): QualityReport;\n}\n\`\`\`\n\n### Template System\n\n**Responsibility**: Generate structured documents from templates\n**Domain Boundary**: Document generation and formatting\n**Data Ownership**: Template definitions, generated content\n\n### Quality Analysis Engine\n\n**Responsibility**: Perform Linus-style 5-layer code review\n**Domain Boundary**: Code quality assessment\n**Data Ownership**: Quality metrics, review reports\n\n## Data Models\n\n### Project Specification\n\`\`\`json\n{\n "feature_name": "string",\n "created_at": "ISO8601",\n "updated_at": "ISO8601",\n "language": "en",\n "phase": "initialized|requirements-generated|design-generated|tasks-generated|implementation",\n "approvals": {\n "requirements": { "generated": boolean, "approved": boolean },\n "design": { "generated": boolean, "approved": boolean },\n "tasks": { "generated": boolean, "approved": boolean }\n },\n "ready_for_implementation": boolean\n}\n\`\`\`\n\n## Error Handling\n\n### Error Strategy\n- Phase validation with clear error messages\n- Graceful degradation for missing dependencies\n- Detailed logging for debugging\n\n### Error Categories\n**User Errors**: Invalid phase transitions → workflow guidance\n**System Errors**: File system failures → graceful error handling\n**Business Logic Errors**: Missing approvals → phase requirement messages\n\n## Testing Strategy\n\n- Unit Tests: SDD workflow engine methods\n- Integration Tests: MCP protocol communication\n- E2E Tests: Complete workflow execution\n- Performance Tests: Large project handling`;
|
|
192
|
+
|
|
193
|
+
await fs.writeFile(path.join(featurePath, 'design.md'), designContent);
|
|
194
|
+
|
|
195
|
+
// Update spec.json
|
|
196
|
+
spec.phase = "design-generated";
|
|
197
|
+
spec.approvals.design.generated = true;
|
|
198
|
+
spec.updated_at = await getCurrentTimestamp();
|
|
199
|
+
|
|
200
|
+
await fs.writeFile(specPath, JSON.stringify(spec, null, 2));
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
content: [{
|
|
204
|
+
type: 'text',
|
|
205
|
+
text: `## Design Generated\n\nTechnical design document generated for feature: **${featureName}**\n\n**Generated**: .kiro/specs/${featureName}/design.md\n**Status**: Design phase completed\n\n**Next Step**: Review the design document, then use \`sdd-tasks\` to proceed to task planning phase`
|
|
206
|
+
}]
|
|
207
|
+
};
|
|
208
|
+
} catch (error) {
|
|
209
|
+
return {
|
|
210
|
+
content: [{
|
|
211
|
+
type: 'text',
|
|
212
|
+
text: `Error generating design: ${error.message}`
|
|
213
|
+
}]
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// 4. sdd-tasks - Generate task breakdown
|
|
219
|
+
server.registerTool("sdd-tasks", {
|
|
220
|
+
title: "Generate Task Breakdown",
|
|
221
|
+
description: "Generate task breakdown",
|
|
222
|
+
inputSchema: {
|
|
223
|
+
featureName: z.string().describe('Feature name from spec initialization')
|
|
224
|
+
},
|
|
225
|
+
}, async ({ featureName }) => {
|
|
226
|
+
try {
|
|
227
|
+
const currentPath = process.cwd();
|
|
228
|
+
const featurePath = path.join(currentPath, '.kiro', 'specs', featureName);
|
|
229
|
+
const specPath = path.join(featurePath, 'spec.json');
|
|
230
|
+
|
|
231
|
+
// Read and validate spec
|
|
232
|
+
const specContent = await fs.readFile(specPath, 'utf8');
|
|
233
|
+
const spec = JSON.parse(specContent);
|
|
234
|
+
|
|
235
|
+
if (!spec.approvals.design.generated) {
|
|
236
|
+
return {
|
|
237
|
+
content: [{
|
|
238
|
+
type: 'text',
|
|
239
|
+
text: `Error: Design must be generated before tasks. Run \`sdd-design ${featureName}\` first.`
|
|
240
|
+
}]
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Generate tasks document
|
|
245
|
+
const tasksContent = `# Implementation Plan\n\n- [ ] 1. Set up MCP server foundation and infrastructure\n - Initialize Node.js project with MCP SDK dependencies\n - Configure server infrastructure and request handling\n - Establish project directory structure and file operations\n - Set up configuration and environment management\n - _Requirements: All requirements need foundational setup_\n\n- [ ] 2. Build core SDD workflow engine\n- [ ] 2.1 Implement project initialization functionality\n - Set up .kiro directory structure creation\n - Implement spec.json metadata generation\n - Build requirements template creation logic\n - Add project state tracking mechanisms\n - _Requirements: 1.1, 1.2, 1.3_\n\n- [ ] 2.2 Enable workflow phase management\n - Implement phase transition validation logic\n - Build approval tracking system\n - Create workflow state persistence\n - Develop phase progression controls\n - _Requirements: 3.1, 3.2, 3.3_\n\n- [ ] 3. Implement document generation system\n- [ ] 3.1 Build requirements generation capabilities\n - Implement EARS-format requirements generation\n - Build project description integration\n - Create structured documentation patterns\n - Add requirements validation logic\n - _Requirements: 2.1, 2.2, 2.3_\n\n- [ ] 3.2 Create design document generation\n - Implement technical design template generation\n - Build architecture diagram integration\n - Create component specification logic\n - Add design validation and approval tracking\n - _Requirements: Design workflow requirements_\n\n- [ ] 3.3 Develop task breakdown functionality\n - Implement task generation from design specifications\n - Build sequential task numbering system\n - Create requirements traceability mapping\n - Add task completion tracking\n - _Requirements: Task management requirements_\n\n- [ ] 4. Integrate quality analysis and review system\n- [ ] 4.1 Implement Linus-style code review engine\n - Build 5-layer code analysis framework\n - Implement AST-based code quality assessment\n - Create quality report generation\n - Add review criteria and scoring system\n - _Requirements: Quality management requirements_\n\n- [ ] 5. Build MCP protocol integration\n- [ ] 5.1 Implement complete MCP tool registration\n - Register all 10 SDD tools with proper schemas\n - Implement tool execution handlers\n - Build error handling and validation\n - Add protocol compliance and communication\n - _Requirements: All tool integration requirements_\n\n- [ ] 6. Add testing and validation\n- [ ] 6.1 Create comprehensive test suite\n - Build unit tests for workflow engine\n - Implement integration tests for MCP communication\n - Create end-to-end workflow validation tests\n - Add performance and reliability testing\n - _Requirements: Testing and validation requirements_`;
|
|
246
|
+
|
|
247
|
+
await fs.writeFile(path.join(featurePath, 'tasks.md'), tasksContent);
|
|
248
|
+
|
|
249
|
+
// Update spec.json
|
|
250
|
+
spec.phase = "tasks-generated";
|
|
251
|
+
spec.approvals.tasks.generated = true;
|
|
252
|
+
spec.ready_for_implementation = true;
|
|
253
|
+
spec.updated_at = await getCurrentTimestamp();
|
|
254
|
+
|
|
255
|
+
await fs.writeFile(specPath, JSON.stringify(spec, null, 2));
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
content: [{
|
|
259
|
+
type: 'text',
|
|
260
|
+
text: `## Implementation Tasks Generated\n\nImplementation tasks document generated for feature: **${featureName}**\n\n**Generated**: .kiro/specs/${featureName}/tasks.md\n**Status**: Tasks phase completed\n**Ready for Implementation**: Yes\n\n**Next Step**: Review tasks, then use \`sdd-implement\` to begin implementation or \`sdd-status\` to check progress`
|
|
261
|
+
}]
|
|
262
|
+
};
|
|
263
|
+
} catch (error) {
|
|
264
|
+
return {
|
|
265
|
+
content: [{
|
|
266
|
+
type: 'text',
|
|
267
|
+
text: `Error generating tasks: ${error.message}`
|
|
268
|
+
}]
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// 5. sdd-implement - Implementation guidelines
|
|
274
|
+
server.registerTool("sdd-implement", {
|
|
275
|
+
title: "Implementation Guidelines",
|
|
276
|
+
description: "Implementation guidelines",
|
|
277
|
+
inputSchema: {
|
|
278
|
+
featureName: z.string().describe('Feature name from spec initialization')
|
|
279
|
+
},
|
|
280
|
+
}, async ({ featureName }) => {
|
|
281
|
+
try {
|
|
282
|
+
const currentPath = process.cwd();
|
|
283
|
+
const featurePath = path.join(currentPath, '.kiro', 'specs', featureName);
|
|
284
|
+
const specPath = path.join(featurePath, 'spec.json');
|
|
285
|
+
|
|
286
|
+
// Read spec
|
|
287
|
+
const specContent = await fs.readFile(specPath, 'utf8');
|
|
288
|
+
const spec = JSON.parse(specContent);
|
|
289
|
+
|
|
290
|
+
if (!spec.ready_for_implementation) {
|
|
291
|
+
return {
|
|
292
|
+
content: [{
|
|
293
|
+
type: 'text',
|
|
294
|
+
text: `Error: Project not ready for implementation. Complete requirements, design, and tasks phases first.`
|
|
295
|
+
}]
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return {
|
|
300
|
+
content: [{
|
|
301
|
+
type: 'text',
|
|
302
|
+
text: `## Implementation Guidelines for ${featureName}\n\n**Project Status**: Ready for implementation\n**Current Phase**: ${spec.phase}\n\n**Implementation Instructions**:\n1. Work through tasks sequentially as defined in tasks.md\n2. Follow the technical design specifications in design.md\n3. Ensure all requirements from requirements.md are satisfied\n4. Use \`sdd-quality-check\` to validate code quality\n5. Mark tasks as completed in tasks.md as you progress\n\n**Key Principles**:\n- Follow established coding patterns and conventions\n- Implement comprehensive error handling\n- Add appropriate logging and monitoring\n- Write tests for each component\n- Validate against requirements at each step\n\n**Next Steps**:\n- Begin with Task 1: Set up MCP server foundation\n- Use the design document as your implementation guide\n- Run quality checks regularly during development`
|
|
303
|
+
}]
|
|
304
|
+
};
|
|
305
|
+
} catch (error) {
|
|
306
|
+
return {
|
|
307
|
+
content: [{
|
|
308
|
+
type: 'text',
|
|
309
|
+
text: `Error getting implementation guidelines: ${error.message}`
|
|
310
|
+
}]
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// 6. sdd-status - Check workflow progress
|
|
316
|
+
server.registerTool("sdd-status", {
|
|
317
|
+
title: "Check Workflow Progress",
|
|
318
|
+
description: "Check workflow progress",
|
|
319
|
+
inputSchema: {
|
|
320
|
+
featureName: z.string().optional().describe('Feature name (optional - shows all if not provided)')
|
|
321
|
+
},
|
|
322
|
+
}, async ({ featureName }) => {
|
|
323
|
+
try {
|
|
324
|
+
const currentPath = process.cwd();
|
|
325
|
+
const kiroPath = path.join(currentPath, '.kiro');
|
|
326
|
+
|
|
327
|
+
// Check if .kiro directory exists
|
|
328
|
+
const kiroExists = await fs.access(kiroPath).then(() => true).catch(() => false);
|
|
329
|
+
if (!kiroExists) {
|
|
330
|
+
return {
|
|
331
|
+
content: [{
|
|
332
|
+
type: 'text',
|
|
333
|
+
text: 'SDD project status: No active project found. Use sdd-init to create a new project.'
|
|
334
|
+
}]
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const specsPath = path.join(kiroPath, 'specs');
|
|
339
|
+
|
|
340
|
+
if (featureName) {
|
|
341
|
+
// Show status for specific feature
|
|
342
|
+
const featurePath = path.join(specsPath, featureName);
|
|
343
|
+
const specPath = path.join(featurePath, 'spec.json');
|
|
344
|
+
|
|
345
|
+
const specExists = await fs.access(specPath).then(() => true).catch(() => false);
|
|
346
|
+
if (!specExists) {
|
|
347
|
+
return {
|
|
348
|
+
content: [{
|
|
349
|
+
type: 'text',
|
|
350
|
+
text: `Feature "${featureName}" not found. Use sdd-init to create it.`
|
|
351
|
+
}]
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const specContent = await fs.readFile(specPath, 'utf8');
|
|
356
|
+
const spec = JSON.parse(specContent);
|
|
357
|
+
|
|
358
|
+
let status = `## SDD Project Status: ${spec.feature_name}\n\n`;
|
|
359
|
+
status += `**Current Phase**: ${spec.phase}\n`;
|
|
360
|
+
status += `**Language**: ${spec.language}\n`;
|
|
361
|
+
status += `**Created**: ${spec.created_at}\n`;
|
|
362
|
+
status += `**Updated**: ${spec.updated_at}\n\n`;
|
|
363
|
+
|
|
364
|
+
status += `**Phase Progress**:\n`;
|
|
365
|
+
status += `- Requirements: ${spec.approvals.requirements.generated ? '✅ Generated' : '❌ Not Generated'}${spec.approvals.requirements.approved ? ', ✅ Approved' : ', ❌ Not Approved'}\n`;
|
|
366
|
+
status += `- Design: ${spec.approvals.design.generated ? '✅ Generated' : '❌ Not Generated'}${spec.approvals.design.approved ? ', ✅ Approved' : ', ❌ Not Approved'}\n`;
|
|
367
|
+
status += `- Tasks: ${spec.approvals.tasks.generated ? '✅ Generated' : '❌ Not Generated'}${spec.approvals.tasks.approved ? ', ✅ Approved' : ', ❌ Not Approved'}\n\n`;
|
|
368
|
+
|
|
369
|
+
status += `**Ready for Implementation**: ${spec.ready_for_implementation ? '✅ Yes' : '❌ No'}\n\n`;
|
|
370
|
+
|
|
371
|
+
// Suggest next steps
|
|
372
|
+
if (!spec.approvals.requirements.generated) {
|
|
373
|
+
status += `**Next Step**: Run \`sdd-requirements ${featureName}\``;
|
|
374
|
+
} else if (!spec.approvals.design.generated) {
|
|
375
|
+
status += `**Next Step**: Run \`sdd-design ${featureName}\``;
|
|
376
|
+
} else if (!spec.approvals.tasks.generated) {
|
|
377
|
+
status += `**Next Step**: Run \`sdd-tasks ${featureName}\``;
|
|
378
|
+
} else {
|
|
379
|
+
status += `**Next Step**: Run \`sdd-implement ${featureName}\` to begin implementation`;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return {
|
|
383
|
+
content: [{
|
|
384
|
+
type: 'text',
|
|
385
|
+
text: status
|
|
386
|
+
}]
|
|
387
|
+
};
|
|
388
|
+
} else {
|
|
389
|
+
// Show all features
|
|
390
|
+
const features = await fs.readdir(specsPath).catch(() => []);
|
|
391
|
+
|
|
392
|
+
if (features.length === 0) {
|
|
393
|
+
return {
|
|
394
|
+
content: [{
|
|
395
|
+
type: 'text',
|
|
396
|
+
text: 'No SDD features found. Use sdd-init to create a new project.'
|
|
397
|
+
}]
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
let status = `## SDD Project Status - All Features\n\n`;
|
|
402
|
+
|
|
403
|
+
for (const feature of features) {
|
|
404
|
+
const specPath = path.join(specsPath, feature, 'spec.json');
|
|
405
|
+
const specExists = await fs.access(specPath).then(() => true).catch(() => false);
|
|
406
|
+
|
|
407
|
+
if (specExists) {
|
|
408
|
+
const specContent = await fs.readFile(specPath, 'utf8');
|
|
409
|
+
const spec = JSON.parse(specContent);
|
|
410
|
+
|
|
411
|
+
status += `**${spec.feature_name}**:\n`;
|
|
412
|
+
status += `- Phase: ${spec.phase}\n`;
|
|
413
|
+
status += `- Requirements: ${spec.approvals.requirements.generated ? '✅' : '❌'}\n`;
|
|
414
|
+
status += `- Design: ${spec.approvals.design.generated ? '✅' : '❌'}\n`;
|
|
415
|
+
status += `- Tasks: ${spec.approvals.tasks.generated ? '✅' : '❌'}\n`;
|
|
416
|
+
status += `- Ready: ${spec.ready_for_implementation ? '✅' : '❌'}\n\n`;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return {
|
|
421
|
+
content: [{
|
|
422
|
+
type: 'text',
|
|
423
|
+
text: status
|
|
424
|
+
}]
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
} catch (error) {
|
|
428
|
+
return {
|
|
429
|
+
content: [{
|
|
430
|
+
type: 'text',
|
|
431
|
+
text: `Error checking status: ${error.message}`
|
|
432
|
+
}]
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
// 7. sdd-approve - Approve workflow phases
|
|
438
|
+
server.registerTool("sdd-approve", {
|
|
439
|
+
title: "Approve Workflow Phases",
|
|
440
|
+
description: "Approve workflow phases",
|
|
441
|
+
inputSchema: {
|
|
442
|
+
featureName: z.string().describe('Feature name from spec initialization'),
|
|
443
|
+
phase: z.enum(['requirements', 'design', 'tasks']).describe('Phase to approve')
|
|
444
|
+
},
|
|
445
|
+
}, async ({ featureName, phase }) => {
|
|
446
|
+
try {
|
|
447
|
+
const currentPath = process.cwd();
|
|
448
|
+
const featurePath = path.join(currentPath, '.kiro', 'specs', featureName);
|
|
449
|
+
const specPath = path.join(featurePath, 'spec.json');
|
|
450
|
+
|
|
451
|
+
// Read spec
|
|
452
|
+
const specContent = await fs.readFile(specPath, 'utf8');
|
|
453
|
+
const spec = JSON.parse(specContent);
|
|
454
|
+
|
|
455
|
+
if (!spec.approvals[phase].generated) {
|
|
456
|
+
return {
|
|
457
|
+
content: [{
|
|
458
|
+
type: 'text',
|
|
459
|
+
text: `Error: ${phase} must be generated before approval. Run sdd-${phase} ${featureName} first.`
|
|
460
|
+
}]
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// Approve the phase
|
|
465
|
+
spec.approvals[phase].approved = true;
|
|
466
|
+
spec.updated_at = await getCurrentTimestamp();
|
|
467
|
+
|
|
468
|
+
await fs.writeFile(specPath, JSON.stringify(spec, null, 2));
|
|
469
|
+
|
|
470
|
+
return {
|
|
471
|
+
content: [{
|
|
472
|
+
type: 'text',
|
|
473
|
+
text: `## Phase Approved\n\n**Feature**: ${featureName}\n**Phase**: ${phase}\n**Status**: ✅ Approved\n\nPhase has been marked as approved and workflow can proceed to the next phase.`
|
|
474
|
+
}]
|
|
475
|
+
};
|
|
476
|
+
} catch (error) {
|
|
477
|
+
return {
|
|
478
|
+
content: [{
|
|
479
|
+
type: 'text',
|
|
480
|
+
text: `Error approving phase: ${error.message}`
|
|
481
|
+
}]
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
// 8. sdd-quality-check - Code quality analysis
|
|
487
|
+
server.registerTool("sdd-quality-check", {
|
|
488
|
+
title: "Code Quality Analysis",
|
|
489
|
+
description: "Code quality analysis",
|
|
490
|
+
inputSchema: {
|
|
491
|
+
code: z.string().describe('Code to analyze'),
|
|
492
|
+
language: z.string().optional().describe('Programming language (default: javascript)')
|
|
493
|
+
},
|
|
494
|
+
}, async ({ code, language = 'javascript' }) => {
|
|
495
|
+
try {
|
|
496
|
+
// Simple quality analysis (Linus-style 5-layer approach)
|
|
497
|
+
const lines = code.split('\n');
|
|
498
|
+
const issues = [];
|
|
499
|
+
|
|
500
|
+
// Layer 1: Syntax and Basic Structure
|
|
501
|
+
if (code.includes('console.log')) {
|
|
502
|
+
issues.push('L1: Remove debug console.log statements');
|
|
503
|
+
}
|
|
504
|
+
if (code.includes('var ')) {
|
|
505
|
+
issues.push('L1: Use let/const instead of var');
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Layer 2: Code Style and Conventions
|
|
509
|
+
if (!/^[a-z]/.test(code.split('function ')[1]?.split('(')[0] || '')) {
|
|
510
|
+
if (code.includes('function ')) {
|
|
511
|
+
issues.push('L2: Function names should start with lowercase');
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Layer 3: Logic and Algorithm
|
|
516
|
+
if (code.includes('for') && !code.includes('const')) {
|
|
517
|
+
issues.push('L3: Consider using const in for loops for immutable iteration variables');
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Layer 4: Architecture and Design
|
|
521
|
+
if (lines.length > 50) {
|
|
522
|
+
issues.push('L4: Function/module is too long, consider breaking into smaller parts');
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Layer 5: Business Logic and Requirements
|
|
526
|
+
if (!code.includes('error') && code.includes('try')) {
|
|
527
|
+
issues.push('L5: Missing proper error handling in try block');
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
const qualityScore = Math.max(0, 100 - (issues.length * 15));
|
|
531
|
+
|
|
532
|
+
let report = `## Linus-Style Code Quality Analysis\n\n`;
|
|
533
|
+
report += `**Language**: ${language}\n`;
|
|
534
|
+
report += `**Lines of Code**: ${lines.length}\n`;
|
|
535
|
+
report += `**Quality Score**: ${qualityScore}/100\n\n`;
|
|
536
|
+
|
|
537
|
+
if (issues.length === 0) {
|
|
538
|
+
report += `**Status**: ✅ Code quality is excellent\n\n`;
|
|
539
|
+
report += `**Analysis**: No significant issues found. Code follows good practices.`;
|
|
540
|
+
} else {
|
|
541
|
+
report += `**Issues Found**: ${issues.length}\n\n`;
|
|
542
|
+
report += `**Quality Issues**:\n`;
|
|
543
|
+
for (const issue of issues) {
|
|
544
|
+
report += `- ${issue}\n`;
|
|
545
|
+
}
|
|
546
|
+
report += `\n**Recommendation**: Address the identified issues to improve code quality.`;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
return {
|
|
550
|
+
content: [{
|
|
551
|
+
type: 'text',
|
|
552
|
+
text: report
|
|
553
|
+
}]
|
|
554
|
+
};
|
|
555
|
+
} catch (error) {
|
|
556
|
+
return {
|
|
557
|
+
content: [{
|
|
558
|
+
type: 'text',
|
|
559
|
+
text: `Error analyzing code quality: ${error.message}`
|
|
560
|
+
}]
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
// 9. sdd-context-load - Load project context
|
|
566
|
+
server.registerTool("sdd-context-load", {
|
|
567
|
+
title: "Load Project Context",
|
|
568
|
+
description: "Load project context",
|
|
569
|
+
inputSchema: {
|
|
570
|
+
featureName: z.string().describe('Feature name to load context for')
|
|
571
|
+
},
|
|
572
|
+
}, async ({ featureName }) => {
|
|
573
|
+
try {
|
|
574
|
+
const currentPath = process.cwd();
|
|
575
|
+
const featurePath = path.join(currentPath, '.kiro', 'specs', featureName);
|
|
576
|
+
|
|
577
|
+
// Load all context files
|
|
578
|
+
const files = ['spec.json', 'requirements.md', 'design.md', 'tasks.md'];
|
|
579
|
+
const context = {};
|
|
580
|
+
|
|
581
|
+
for (const file of files) {
|
|
582
|
+
const filePath = path.join(featurePath, file);
|
|
583
|
+
const fileExists = await fs.access(filePath).then(() => true).catch(() => false);
|
|
584
|
+
|
|
585
|
+
if (fileExists) {
|
|
586
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
587
|
+
context[file] = file.endsWith('.json') ? JSON.parse(content) : content;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
let contextReport = `## Project Context Loaded: ${featureName}\n\n`;
|
|
592
|
+
|
|
593
|
+
if (context['spec.json']) {
|
|
594
|
+
const spec = context['spec.json'];
|
|
595
|
+
contextReport += `**Project Metadata**:\n`;
|
|
596
|
+
contextReport += `- Feature: ${spec.feature_name}\n`;
|
|
597
|
+
contextReport += `- Phase: ${spec.phase}\n`;
|
|
598
|
+
contextReport += `- Language: ${spec.language}\n`;
|
|
599
|
+
contextReport += `- Ready for Implementation: ${spec.ready_for_implementation ? 'Yes' : 'No'}\n\n`;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
contextReport += `**Available Documents**:\n`;
|
|
603
|
+
for (const [file, content] of Object.entries(context)) {
|
|
604
|
+
if (file !== 'spec.json') {
|
|
605
|
+
const preview = typeof content === 'string' ? content.substring(0, 100) + '...' : 'JSON data';
|
|
606
|
+
contextReport += `- **${file}**: ${preview}\n`;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
contextReport += `\n**Context Status**: Project memory restored successfully\n`;
|
|
611
|
+
contextReport += `**Total Files Loaded**: ${Object.keys(context).length}`;
|
|
612
|
+
|
|
613
|
+
return {
|
|
614
|
+
content: [{
|
|
615
|
+
type: 'text',
|
|
616
|
+
text: contextReport
|
|
617
|
+
}]
|
|
618
|
+
};
|
|
619
|
+
} catch (error) {
|
|
620
|
+
return {
|
|
621
|
+
content: [{
|
|
622
|
+
type: 'text',
|
|
623
|
+
text: `Error loading project context: ${error.message}`
|
|
624
|
+
}]
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
// 10. sdd-template-render - Render templates
|
|
630
|
+
server.registerTool("sdd-template-render", {
|
|
631
|
+
title: "Render Templates",
|
|
632
|
+
description: "Render templates",
|
|
633
|
+
inputSchema: {
|
|
634
|
+
templateType: z.enum(['requirements', 'design', 'tasks', 'custom']).describe('Type of template to render'),
|
|
635
|
+
featureName: z.string().describe('Feature name for template context'),
|
|
636
|
+
customTemplate: z.string().optional().describe('Custom template content (if templateType is custom)')
|
|
637
|
+
},
|
|
638
|
+
}, async ({ templateType, featureName, customTemplate }) => {
|
|
639
|
+
try {
|
|
640
|
+
const currentPath = process.cwd();
|
|
641
|
+
const featurePath = path.join(currentPath, '.kiro', 'specs', featureName);
|
|
642
|
+
const specPath = path.join(featurePath, 'spec.json');
|
|
643
|
+
|
|
644
|
+
// Load spec for context
|
|
645
|
+
const specExists = await fs.access(specPath).then(() => true).catch(() => false);
|
|
646
|
+
let spec = {};
|
|
647
|
+
if (specExists) {
|
|
648
|
+
const specContent = await fs.readFile(specPath, 'utf8');
|
|
649
|
+
spec = JSON.parse(specContent);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
let renderedContent = '';
|
|
653
|
+
|
|
654
|
+
switch (templateType) {
|
|
655
|
+
case 'requirements':
|
|
656
|
+
renderedContent = `# Requirements Template for ${featureName}\n\n## Project Context\n- Feature: ${spec.feature_name || featureName}\n- Language: ${spec.language || 'en'}\n\n## Requirements Sections\n1. Functional Requirements\n2. Non-Functional Requirements\n3. Business Rules\n4. Acceptance Criteria (EARS format)`;
|
|
657
|
+
break;
|
|
658
|
+
|
|
659
|
+
case 'design':
|
|
660
|
+
renderedContent = `# Design Template for ${featureName}\n\n## Architecture Overview\n- System Architecture\n- Component Design\n- Data Models\n- Interface Specifications\n\n## Technology Decisions\n- Stack Selection\n- Framework Choices\n- Integration Patterns`;
|
|
661
|
+
break;
|
|
662
|
+
|
|
663
|
+
case 'tasks':
|
|
664
|
+
renderedContent = `# Tasks Template for ${featureName}\n\n## Implementation Tasks\n\n- [ ] 1. Foundation Setup\n - Project initialization\n - Dependencies setup\n - Basic structure\n\n- [ ] 2. Core Implementation\n - Main functionality\n - Business logic\n - Data handling\n\n- [ ] 3. Integration & Testing\n - System integration\n - Testing implementation\n - Quality validation`;
|
|
665
|
+
break;
|
|
666
|
+
|
|
667
|
+
case 'custom':
|
|
668
|
+
if (!customTemplate) {
|
|
669
|
+
throw new Error('Custom template content is required for custom template type');
|
|
670
|
+
}
|
|
671
|
+
// Simple template variable replacement
|
|
672
|
+
renderedContent = customTemplate
|
|
673
|
+
.replace(/\{\{featureName\}\}/g, featureName)
|
|
674
|
+
.replace(/\{\{language\}\}/g, spec.language || 'en')
|
|
675
|
+
.replace(/\{\{phase\}\}/g, spec.phase || 'initialized')
|
|
676
|
+
.replace(/\{\{timestamp\}\}/g, new Date().toISOString());
|
|
677
|
+
break;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
return {
|
|
681
|
+
content: [{
|
|
682
|
+
type: 'text',
|
|
683
|
+
text: `## Template Rendered: ${templateType}\n\n**Feature**: ${featureName}\n**Template Type**: ${templateType}\n\n**Rendered Content**:\n\`\`\`markdown\n${renderedContent}\n\`\`\`\n\n**Usage**: Copy the rendered content to create your ${templateType} document`
|
|
684
|
+
}]
|
|
685
|
+
};
|
|
686
|
+
} catch (error) {
|
|
687
|
+
return {
|
|
688
|
+
content: [{
|
|
689
|
+
type: 'text',
|
|
690
|
+
text: `Error rendering template: ${error.message}`
|
|
691
|
+
}]
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
// 11. sdd-steering - Create/update steering documents
|
|
697
|
+
server.registerTool("sdd-steering", {
|
|
698
|
+
title: "Create/Update Steering Documents",
|
|
699
|
+
description: "Create or update steering documents",
|
|
700
|
+
inputSchema: {
|
|
701
|
+
updateMode: z.enum(['create', 'update']).optional().describe('Whether to create new or update existing documents (auto-detected if not specified)')
|
|
702
|
+
},
|
|
703
|
+
}, async ({ updateMode }) => {
|
|
704
|
+
try {
|
|
705
|
+
const currentPath = process.cwd();
|
|
706
|
+
const steeringPath = path.join(currentPath, '.kiro', 'steering');
|
|
707
|
+
|
|
708
|
+
// Create steering directory if it doesn't exist
|
|
709
|
+
await fs.mkdir(steeringPath, { recursive: true });
|
|
710
|
+
|
|
711
|
+
// Analyze existing files
|
|
712
|
+
const productExists = await fs.access(path.join(steeringPath, 'product.md')).then(() => true).catch(() => false);
|
|
713
|
+
const techExists = await fs.access(path.join(steeringPath, 'tech.md')).then(() => true).catch(() => false);
|
|
714
|
+
const structureExists = await fs.access(path.join(steeringPath, 'structure.md')).then(() => true).catch(() => false);
|
|
715
|
+
|
|
716
|
+
// Auto-detect mode if not specified
|
|
717
|
+
if (!updateMode) {
|
|
718
|
+
updateMode = (productExists || techExists || structureExists) ? 'update' : 'create';
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// Analyze project structure
|
|
722
|
+
const packageJsonExists = await fs.access('package.json').then(() => true).catch(() => false);
|
|
723
|
+
let projectInfo = {
|
|
724
|
+
name: 'Unknown Project',
|
|
725
|
+
description: 'No description available',
|
|
726
|
+
techStack: [],
|
|
727
|
+
structure: {}
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
if (packageJsonExists) {
|
|
731
|
+
const packageContent = await fs.readFile('package.json', 'utf8');
|
|
732
|
+
const packageJson = JSON.parse(packageContent);
|
|
733
|
+
projectInfo.name = packageJson.name || 'Unknown Project';
|
|
734
|
+
projectInfo.description = packageJson.description || 'No description available';
|
|
735
|
+
projectInfo.techStack = Object.keys(packageJson.dependencies || {}).slice(0, 10);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// Generate product.md
|
|
739
|
+
const productContent = `# Product Overview
|
|
740
|
+
|
|
741
|
+
## Product Description
|
|
742
|
+
${projectInfo.description}
|
|
743
|
+
|
|
744
|
+
## Core Features
|
|
745
|
+
- Spec-driven development workflow automation
|
|
746
|
+
- AI-agent integration via Model Context Protocol (MCP)
|
|
747
|
+
- Phase-based development with quality gates
|
|
748
|
+
- Template-based document generation
|
|
749
|
+
- Multi-language support and localization
|
|
750
|
+
|
|
751
|
+
## Target Use Case
|
|
752
|
+
This product is designed for AI-powered development teams who want to follow structured, spec-driven development workflows. It provides systematic guidance through requirements, design, tasks, and implementation phases.
|
|
753
|
+
|
|
754
|
+
## Key Value Proposition
|
|
755
|
+
- **Structured Development**: Enforces proven development methodologies
|
|
756
|
+
- **AI Integration**: Seamless integration with AI development tools
|
|
757
|
+
- **Quality Assurance**: Built-in quality gates and code review processes
|
|
758
|
+
- **Template System**: Consistent document generation and project structure
|
|
759
|
+
- **Flexibility**: Configurable workflows and customizable steering documents
|
|
760
|
+
|
|
761
|
+
## Target Users
|
|
762
|
+
- AI development teams
|
|
763
|
+
- Software engineers using Claude Code, Cursor, and similar tools
|
|
764
|
+
- Development teams implementing spec-driven development practices
|
|
765
|
+
- Projects requiring structured documentation and workflow management`;
|
|
766
|
+
|
|
767
|
+
await fs.writeFile(path.join(steeringPath, 'product.md'), productContent);
|
|
768
|
+
|
|
769
|
+
// Generate tech.md
|
|
770
|
+
const techContent = `# Technology Stack
|
|
771
|
+
|
|
772
|
+
## Architecture
|
|
773
|
+
- **Type**: ${packageJsonExists ? 'Node.js Application' : 'Unknown Architecture'}
|
|
774
|
+
- **Runtime**: Node.js with ES modules
|
|
775
|
+
- **Protocol**: Model Context Protocol (MCP) for AI integration
|
|
776
|
+
- **Package Manager**: npm
|
|
777
|
+
|
|
778
|
+
## Technology Stack
|
|
779
|
+
${projectInfo.techStack.length > 0 ?
|
|
780
|
+
projectInfo.techStack.map(dep => `- **${dep}**: ${dep.includes('mcp') ? 'Model Context Protocol SDK' : 'Runtime dependency'}`).join('\n') :
|
|
781
|
+
'- No major dependencies detected'}
|
|
782
|
+
|
|
783
|
+
## Development Environment
|
|
784
|
+
- **Node Version**: >= 18.0.0
|
|
785
|
+
- **Package Manager**: npm
|
|
786
|
+
- **Module System**: ES modules (type: "module")
|
|
787
|
+
|
|
788
|
+
## Common Commands
|
|
789
|
+
\`\`\`bash
|
|
790
|
+
# Development
|
|
791
|
+
npm install # Install dependencies
|
|
792
|
+
npm run build # Build the project
|
|
793
|
+
npm test # Run tests
|
|
794
|
+
npm start # Start the application
|
|
795
|
+
|
|
796
|
+
# MCP Server
|
|
797
|
+
node mcp-server.js # Run simple MCP server
|
|
798
|
+
\`\`\`
|
|
799
|
+
|
|
800
|
+
## Environment Variables
|
|
801
|
+
- \`LOG_LEVEL\`: Logging level (debug, info, warn, error)
|
|
802
|
+
- \`DEFAULT_LANG\`: Default language for generated documents (en, es, fr, etc.)
|
|
803
|
+
|
|
804
|
+
## Port Configuration
|
|
805
|
+
- MCP Server: Uses stdio transport (no ports)
|
|
806
|
+
- Application ports: Defined by implementation requirements`;
|
|
807
|
+
|
|
808
|
+
await fs.writeFile(path.join(steeringPath, 'tech.md'), techContent);
|
|
809
|
+
|
|
810
|
+
// Generate structure.md
|
|
811
|
+
const structureContent = `# Project Structure
|
|
812
|
+
|
|
813
|
+
## Root Directory Organization
|
|
814
|
+
\`\`\`
|
|
815
|
+
├── .kiro/ # SDD workflow files
|
|
816
|
+
│ ├── steering/ # Project steering documents
|
|
817
|
+
│ └── specs/ # Feature specifications
|
|
818
|
+
├── dist/ # Compiled output (if applicable)
|
|
819
|
+
├── src/ # Source code (if applicable)
|
|
820
|
+
├── node_modules/ # npm dependencies
|
|
821
|
+
├── package.json # Project configuration
|
|
822
|
+
├── mcp-server.js # Simple MCP server implementation
|
|
823
|
+
└── README.md # Project documentation
|
|
824
|
+
\`\`\`
|
|
825
|
+
|
|
826
|
+
## SDD Directory Structure (\`.kiro/\`)
|
|
827
|
+
- **steering/**: Always-loaded project context documents
|
|
828
|
+
- \`product.md\`: Product overview and business context
|
|
829
|
+
- \`tech.md\`: Technology stack and development environment
|
|
830
|
+
- \`structure.md\`: Project organization and architectural decisions
|
|
831
|
+
- Custom steering files for specialized contexts
|
|
832
|
+
- **specs/**: Feature-specific specifications
|
|
833
|
+
- \`{feature-name}/\`: Individual feature directories
|
|
834
|
+
- \`spec.json\`: Metadata and approval tracking
|
|
835
|
+
- \`requirements.md\`: EARS-format requirements
|
|
836
|
+
- \`design.md\`: Technical design document
|
|
837
|
+
- \`tasks.md\`: Implementation task breakdown
|
|
838
|
+
|
|
839
|
+
## Code Organization Patterns
|
|
840
|
+
- **Modular Structure**: Clear separation between different functional areas
|
|
841
|
+
- **Configuration First**: Centralized configuration management
|
|
842
|
+
- **Documentation Co-location**: Specs and steering documents alongside code
|
|
843
|
+
|
|
844
|
+
## File Naming Conventions
|
|
845
|
+
- **Steering files**: \`kebab-case.md\` (e.g., \`api-standards.md\`)
|
|
846
|
+
- **Spec files**: Standard names (\`requirements.md\`, \`design.md\`, \`tasks.md\`)
|
|
847
|
+
- **Feature names**: Auto-generated from descriptions using kebab-case
|
|
848
|
+
|
|
849
|
+
## Key Architectural Principles
|
|
850
|
+
- **Spec-Driven Development**: All features start with requirements and design
|
|
851
|
+
- **Phase-Based Workflow**: Structured progression through development phases
|
|
852
|
+
- **Quality Gates**: Approval requirements between phases
|
|
853
|
+
- **Template-Based Generation**: Consistent document structure and formatting
|
|
854
|
+
- **AI-First Design**: Optimized for AI development tool integration`;
|
|
855
|
+
|
|
856
|
+
await fs.writeFile(path.join(steeringPath, 'structure.md'), structureContent);
|
|
857
|
+
|
|
858
|
+
const mode = updateMode === 'update' ? 'Updated' : 'Created';
|
|
859
|
+
|
|
860
|
+
return {
|
|
861
|
+
content: [{
|
|
862
|
+
type: 'text',
|
|
863
|
+
text: `## Steering Documents ${mode}
|
|
864
|
+
|
|
865
|
+
**Project**: ${projectInfo.name}
|
|
866
|
+
**Mode**: ${updateMode}
|
|
867
|
+
|
|
868
|
+
**${mode} Files**:
|
|
869
|
+
- \`.kiro/steering/product.md\` - Product overview and business context
|
|
870
|
+
- \`.kiro/steering/tech.md\` - Technology stack and development environment
|
|
871
|
+
- \`.kiro/steering/structure.md\` - Project organization and architectural decisions
|
|
872
|
+
|
|
873
|
+
**Analysis**:
|
|
874
|
+
- Technology stack: ${projectInfo.techStack.length} dependencies detected
|
|
875
|
+
- Project type: ${packageJsonExists ? 'Node.js application' : 'Unknown project type'}
|
|
876
|
+
- Existing steering: ${productExists || techExists || structureExists ? 'Updated preserving customizations' : 'Created from scratch'}
|
|
877
|
+
|
|
878
|
+
These steering documents provide consistent project context for all AI interactions and spec-driven development workflows.`
|
|
879
|
+
}]
|
|
880
|
+
};
|
|
881
|
+
} catch (error) {
|
|
882
|
+
return {
|
|
883
|
+
content: [{
|
|
884
|
+
type: 'text',
|
|
885
|
+
text: `Error creating/updating steering documents: ${error.message}`
|
|
886
|
+
}]
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
// 12. sdd-steering-custom - Create custom steering documents
|
|
892
|
+
server.registerTool("sdd-steering-custom", {
|
|
893
|
+
title: "Create Custom Steering Document",
|
|
894
|
+
description: "Create custom steering documents",
|
|
895
|
+
inputSchema: {
|
|
896
|
+
fileName: z.string().describe('Filename for the custom steering document (e.g., "api-standards.md")'),
|
|
897
|
+
topic: z.string().describe('Topic/purpose of the custom steering document'),
|
|
898
|
+
inclusionMode: z.enum(['always', 'conditional', 'manual']).describe('How this steering document should be included'),
|
|
899
|
+
filePattern: z.string().optional().describe('File pattern for conditional inclusion (e.g., "*.test.js", "src/api/**/*")')
|
|
900
|
+
},
|
|
901
|
+
}, async ({ fileName, topic, inclusionMode, filePattern }) => {
|
|
902
|
+
try {
|
|
903
|
+
const currentPath = process.cwd();
|
|
904
|
+
const steeringPath = path.join(currentPath, '.kiro', 'steering');
|
|
905
|
+
|
|
906
|
+
// Create steering directory if it doesn't exist
|
|
907
|
+
await fs.mkdir(steeringPath, { recursive: true });
|
|
908
|
+
|
|
909
|
+
// Ensure filename ends with .md
|
|
910
|
+
if (!fileName.endsWith('.md')) {
|
|
911
|
+
fileName += '.md';
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
// Generate inclusion mode comment
|
|
915
|
+
let inclusionComment = '<!-- Inclusion Mode: ';
|
|
916
|
+
if (inclusionMode === 'always') {
|
|
917
|
+
inclusionComment += 'Always -->';
|
|
918
|
+
} else if (inclusionMode === 'conditional') {
|
|
919
|
+
inclusionComment += `Conditional: "${filePattern || '**/*'}" -->`;
|
|
920
|
+
} else {
|
|
921
|
+
inclusionComment += 'Manual -->';
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
// Generate content based on topic
|
|
925
|
+
let content = `${inclusionComment}
|
|
926
|
+
|
|
927
|
+
# ${topic}
|
|
928
|
+
|
|
929
|
+
## Purpose
|
|
930
|
+
This document provides specialized guidance for ${topic.toLowerCase()} within the project context.
|
|
931
|
+
|
|
932
|
+
## When This Document Applies
|
|
933
|
+
${inclusionMode === 'conditional' ?
|
|
934
|
+
`This guidance applies when working with files matching: \`${filePattern || '**/*'}\`` :
|
|
935
|
+
inclusionMode === 'always' ?
|
|
936
|
+
'This guidance applies to all development work in this project.' :
|
|
937
|
+
'Reference this document manually using @${fileName} when needed.'}
|
|
938
|
+
|
|
939
|
+
## Guidelines
|
|
940
|
+
|
|
941
|
+
### Key Principles
|
|
942
|
+
- [Add specific principles for ${topic.toLowerCase()}]
|
|
943
|
+
- [Include concrete rules and patterns]
|
|
944
|
+
- [Provide rationale for important decisions]
|
|
945
|
+
|
|
946
|
+
### Implementation Patterns
|
|
947
|
+
\`\`\`
|
|
948
|
+
// Example code patterns for ${topic.toLowerCase()}
|
|
949
|
+
// Include specific examples relevant to your project
|
|
950
|
+
\`\`\`
|
|
951
|
+
|
|
952
|
+
### Best Practices
|
|
953
|
+
1. **Practice 1**: Description and rationale
|
|
954
|
+
2. **Practice 2**: Description and rationale
|
|
955
|
+
3. **Practice 3**: Description and rationale
|
|
956
|
+
|
|
957
|
+
## Integration Points
|
|
958
|
+
- Related to core steering: product.md, tech.md, structure.md
|
|
959
|
+
- Dependencies: [List any prerequisites or related documents]
|
|
960
|
+
- Conflicts: [Note any potential conflicts with other guidance]
|
|
961
|
+
|
|
962
|
+
## Examples
|
|
963
|
+
\`\`\`
|
|
964
|
+
// Concrete examples of correct implementation
|
|
965
|
+
// Show both correct patterns and counter-examples if helpful
|
|
966
|
+
\`\`\`
|
|
967
|
+
|
|
968
|
+
## Quality Standards
|
|
969
|
+
- [Specific quality criteria for ${topic.toLowerCase()}]
|
|
970
|
+
- [Testing requirements]
|
|
971
|
+
- [Review checklist items]`;
|
|
972
|
+
|
|
973
|
+
const filePath = path.join(steeringPath, fileName);
|
|
974
|
+
await fs.writeFile(filePath, content);
|
|
975
|
+
|
|
976
|
+
return {
|
|
977
|
+
content: [{
|
|
978
|
+
type: 'text',
|
|
979
|
+
text: `## Custom Steering Document Created
|
|
980
|
+
|
|
981
|
+
**File**: .kiro/steering/${fileName}
|
|
982
|
+
**Topic**: ${topic}
|
|
983
|
+
**Inclusion Mode**: ${inclusionMode}${inclusionMode === 'conditional' ? ` (Pattern: "${filePattern}")` : ''}
|
|
984
|
+
|
|
985
|
+
**Created**: Custom steering document with template structure
|
|
986
|
+
**Usage**: ${
|
|
987
|
+
inclusionMode === 'always' ? 'Will be loaded in all AI interactions' :
|
|
988
|
+
inclusionMode === 'conditional' ? `Will be loaded when working with files matching "${filePattern}"` :
|
|
989
|
+
`Reference manually with @${fileName} when needed`
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
The document has been created with a standard template structure. Edit the file to add your specific guidelines, examples, and best practices for ${topic.toLowerCase()}.`
|
|
993
|
+
}]
|
|
994
|
+
};
|
|
995
|
+
} catch (error) {
|
|
996
|
+
return {
|
|
997
|
+
content: [{
|
|
998
|
+
type: 'text',
|
|
999
|
+
text: `Error creating custom steering document: ${error.message}`
|
|
1000
|
+
}]
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
});
|
|
1004
|
+
|
|
1005
|
+
// 13. sdd-validate-design - Interactive design quality review
|
|
1006
|
+
server.registerTool("sdd-validate-design", {
|
|
1007
|
+
title: "Validate Design Quality",
|
|
1008
|
+
description: "Interactive design quality review and validation",
|
|
1009
|
+
inputSchema: {
|
|
1010
|
+
featureName: z.string().describe('Feature name to validate design for')
|
|
1011
|
+
},
|
|
1012
|
+
}, async ({ featureName }) => {
|
|
1013
|
+
try {
|
|
1014
|
+
const currentPath = process.cwd();
|
|
1015
|
+
const featurePath = path.join(currentPath, '.kiro', 'specs', featureName);
|
|
1016
|
+
const designPath = path.join(featurePath, 'design.md');
|
|
1017
|
+
const specPath = path.join(featurePath, 'spec.json');
|
|
1018
|
+
|
|
1019
|
+
// Check if design document exists
|
|
1020
|
+
const designExists = await fs.access(designPath).then(() => true).catch(() => false);
|
|
1021
|
+
if (!designExists) {
|
|
1022
|
+
return {
|
|
1023
|
+
content: [{
|
|
1024
|
+
type: 'text',
|
|
1025
|
+
text: `Error: Design document not found. Run \`sdd-design ${featureName}\` first to generate design document.`
|
|
1026
|
+
}]
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
// Load design and spec
|
|
1031
|
+
const designContent = await fs.readFile(designPath, 'utf8');
|
|
1032
|
+
const specContent = await fs.readFile(specPath, 'utf8');
|
|
1033
|
+
const spec = JSON.parse(specContent);
|
|
1034
|
+
|
|
1035
|
+
// Analyze design for critical issues
|
|
1036
|
+
const issues = [];
|
|
1037
|
+
|
|
1038
|
+
// Check for type safety (if TypeScript patterns detected)
|
|
1039
|
+
if (designContent.includes('any') || designContent.includes(': any')) {
|
|
1040
|
+
issues.push({
|
|
1041
|
+
title: "Type Safety Concern",
|
|
1042
|
+
concern: "Design mentions 'any' types which compromises type safety",
|
|
1043
|
+
impact: "Reduces code reliability and IDE support",
|
|
1044
|
+
suggestion: "Define explicit interfaces and types for all data structures"
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
// Check for architectural patterns
|
|
1049
|
+
if (!designContent.includes('Component') && !designContent.includes('Service') && !designContent.includes('Module')) {
|
|
1050
|
+
issues.push({
|
|
1051
|
+
title: "Architecture Clarity",
|
|
1052
|
+
concern: "Design lacks clear component or service boundaries",
|
|
1053
|
+
impact: "May lead to monolithic or poorly organized code",
|
|
1054
|
+
suggestion: "Define clear components, services, or modules with specific responsibilities"
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
// Check for error handling
|
|
1059
|
+
if (!designContent.includes('error') && !designContent.includes('Error')) {
|
|
1060
|
+
issues.push({
|
|
1061
|
+
title: "Error Handling Strategy",
|
|
1062
|
+
concern: "Design doesn't address error handling patterns",
|
|
1063
|
+
impact: "Runtime errors may not be properly managed",
|
|
1064
|
+
suggestion: "Add comprehensive error handling strategy and exception management"
|
|
1065
|
+
});
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
// Limit to 3 most critical issues
|
|
1069
|
+
const criticalIssues = issues.slice(0, 3);
|
|
1070
|
+
|
|
1071
|
+
// Identify design strengths
|
|
1072
|
+
const strengths = [];
|
|
1073
|
+
if (designContent.includes('mermaid') || designContent.includes('```')) {
|
|
1074
|
+
strengths.push("Visual documentation with diagrams and code examples");
|
|
1075
|
+
}
|
|
1076
|
+
if (designContent.includes('interface') || designContent.includes('Interface')) {
|
|
1077
|
+
strengths.push("Clear interface definitions and contracts");
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
// Make GO/NO-GO decision
|
|
1081
|
+
const hasBlockingIssues = criticalIssues.length > 2 ||
|
|
1082
|
+
criticalIssues.some(issue => issue.title.includes('Architecture') || issue.title.includes('Type Safety'));
|
|
1083
|
+
|
|
1084
|
+
const decision = hasBlockingIssues ? 'NO-GO' : 'GO';
|
|
1085
|
+
const nextStep = decision === 'GO' ?
|
|
1086
|
+
`Run \`sdd-tasks ${featureName}\` to generate implementation tasks` :
|
|
1087
|
+
`Address critical issues in design document before proceeding`;
|
|
1088
|
+
|
|
1089
|
+
let report = `## Design Validation Review: ${featureName}\n\n`;
|
|
1090
|
+
report += `**Overall Assessment**: ${decision === 'GO' ? '✅ Design ready for implementation' : '❌ Design needs revision'}\n\n`;
|
|
1091
|
+
|
|
1092
|
+
if (criticalIssues.length > 0) {
|
|
1093
|
+
report += `### Critical Issues (${criticalIssues.length})\n\n`;
|
|
1094
|
+
criticalIssues.forEach((issue, index) => {
|
|
1095
|
+
report += `🔴 **Critical Issue ${index + 1}**: ${issue.title}\n`;
|
|
1096
|
+
report += `**Concern**: ${issue.concern}\n`;
|
|
1097
|
+
report += `**Impact**: ${issue.impact}\n`;
|
|
1098
|
+
report += `**Suggestion**: ${issue.suggestion}\n\n`;
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
if (strengths.length > 0) {
|
|
1103
|
+
report += `### Design Strengths\n\n`;
|
|
1104
|
+
strengths.forEach(strength => {
|
|
1105
|
+
report += `✅ ${strength}\n`;
|
|
1106
|
+
});
|
|
1107
|
+
report += `\n`;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
report += `### Final Assessment\n`;
|
|
1111
|
+
report += `**Decision**: ${decision}\n`;
|
|
1112
|
+
report += `**Rationale**: ${
|
|
1113
|
+
decision === 'GO' ?
|
|
1114
|
+
'Design addresses core requirements with acceptable architectural approach and manageable risks.' :
|
|
1115
|
+
'Critical architectural or technical issues need resolution before implementation can proceed safely.'
|
|
1116
|
+
}\n`;
|
|
1117
|
+
report += `**Next Steps**: ${nextStep}\n\n`;
|
|
1118
|
+
|
|
1119
|
+
report += `### Interactive Discussion\n`;
|
|
1120
|
+
report += `Questions for design review:\n`;
|
|
1121
|
+
report += `1. Do you agree with the identified issues and their severity?\n`;
|
|
1122
|
+
report += `2. Are there alternative approaches to address the concerns?\n`;
|
|
1123
|
+
report += `3. What are your thoughts on the overall design complexity?\n`;
|
|
1124
|
+
report += `4. Are there any design decisions that need clarification?\n`;
|
|
1125
|
+
|
|
1126
|
+
return {
|
|
1127
|
+
content: [{
|
|
1128
|
+
type: 'text',
|
|
1129
|
+
text: report
|
|
1130
|
+
}]
|
|
1131
|
+
};
|
|
1132
|
+
} catch (error) {
|
|
1133
|
+
return {
|
|
1134
|
+
content: [{
|
|
1135
|
+
type: 'text',
|
|
1136
|
+
text: `Error validating design: ${error.message}`
|
|
1137
|
+
}]
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
});
|
|
1141
|
+
|
|
1142
|
+
// 14. sdd-validate-gap - Analyze implementation gap
|
|
1143
|
+
server.registerTool("sdd-validate-gap", {
|
|
1144
|
+
title: "Validate Implementation Gap",
|
|
1145
|
+
description: "Analyze implementation gap between requirements and codebase",
|
|
1146
|
+
inputSchema: {
|
|
1147
|
+
featureName: z.string().describe('Feature name to analyze implementation gap for')
|
|
1148
|
+
},
|
|
1149
|
+
}, async ({ featureName }) => {
|
|
1150
|
+
try {
|
|
1151
|
+
const currentPath = process.cwd();
|
|
1152
|
+
const featurePath = path.join(currentPath, '.kiro', 'specs', featureName);
|
|
1153
|
+
const requirementsPath = path.join(featurePath, 'requirements.md');
|
|
1154
|
+
const specPath = path.join(featurePath, 'spec.json');
|
|
1155
|
+
|
|
1156
|
+
// Check if requirements exist
|
|
1157
|
+
const requirementsExist = await fs.access(requirementsPath).then(() => true).catch(() => false);
|
|
1158
|
+
if (!requirementsExist) {
|
|
1159
|
+
return {
|
|
1160
|
+
content: [{
|
|
1161
|
+
type: 'text',
|
|
1162
|
+
text: `Error: Requirements document not found. Run \`sdd-requirements ${featureName}\` first to generate requirements.`
|
|
1163
|
+
}]
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
// Load requirements and spec
|
|
1168
|
+
const requirementsContent = await fs.readFile(requirementsPath, 'utf8');
|
|
1169
|
+
const specContent = await fs.readFile(specPath, 'utf8');
|
|
1170
|
+
const spec = JSON.parse(specContent);
|
|
1171
|
+
|
|
1172
|
+
// Analyze current codebase
|
|
1173
|
+
const codebaseAnalysis = {
|
|
1174
|
+
hasPackageJson: await fs.access('package.json').then(() => true).catch(() => false),
|
|
1175
|
+
hasSourceCode: false,
|
|
1176
|
+
techStack: [],
|
|
1177
|
+
architecture: 'Unknown'
|
|
1178
|
+
};
|
|
1179
|
+
|
|
1180
|
+
if (codebaseAnalysis.hasPackageJson) {
|
|
1181
|
+
const packageContent = await fs.readFile('package.json', 'utf8');
|
|
1182
|
+
const packageJson = JSON.parse(packageContent);
|
|
1183
|
+
codebaseAnalysis.techStack = Object.keys(packageJson.dependencies || {});
|
|
1184
|
+
codebaseAnalysis.architecture = 'Node.js Application';
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// Check for source directories
|
|
1188
|
+
const srcExists = await fs.access('src').then(() => true).catch(() => false);
|
|
1189
|
+
const libExists = await fs.access('lib').then(() => true).catch(() => false);
|
|
1190
|
+
codebaseAnalysis.hasSourceCode = srcExists || libExists;
|
|
1191
|
+
|
|
1192
|
+
// Extract requirements complexity
|
|
1193
|
+
const requirements = requirementsContent.match(/WHEN|IF|WHILE|WHERE/g) || [];
|
|
1194
|
+
const complexity = requirements.length > 10 ? 'XL' :
|
|
1195
|
+
requirements.length > 6 ? 'L' :
|
|
1196
|
+
requirements.length > 3 ? 'M' : 'S';
|
|
1197
|
+
|
|
1198
|
+
// Identify gaps and implementation approaches
|
|
1199
|
+
const gaps = [];
|
|
1200
|
+
if (!codebaseAnalysis.hasSourceCode) {
|
|
1201
|
+
gaps.push("No existing source code structure - requires full implementation from scratch");
|
|
1202
|
+
}
|
|
1203
|
+
if (!codebaseAnalysis.techStack.includes('@modelcontextprotocol/sdk')) {
|
|
1204
|
+
gaps.push("MCP SDK integration required for AI tool compatibility");
|
|
1205
|
+
}
|
|
1206
|
+
if (requirementsContent.includes('database') || requirementsContent.includes('storage')) {
|
|
1207
|
+
gaps.push("Data storage layer needs to be designed and implemented");
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// Implementation strategy options
|
|
1211
|
+
const strategies = [
|
|
1212
|
+
{
|
|
1213
|
+
approach: "Extension",
|
|
1214
|
+
rationale: codebaseAnalysis.hasSourceCode ?
|
|
1215
|
+
"Extend existing codebase with new functionality" :
|
|
1216
|
+
"Not applicable - no existing codebase to extend",
|
|
1217
|
+
applicable: codebaseAnalysis.hasSourceCode,
|
|
1218
|
+
complexity: codebaseAnalysis.hasSourceCode ? 'M' : 'N/A',
|
|
1219
|
+
tradeoffs: codebaseAnalysis.hasSourceCode ?
|
|
1220
|
+
"Pros: Maintains consistency, faster development. Cons: May introduce technical debt" :
|
|
1221
|
+
"N/A"
|
|
1222
|
+
},
|
|
1223
|
+
{
|
|
1224
|
+
approach: "New Implementation",
|
|
1225
|
+
rationale: "Create new components following established patterns",
|
|
1226
|
+
applicable: true,
|
|
1227
|
+
complexity: complexity,
|
|
1228
|
+
tradeoffs: "Pros: Clean architecture, full control. Cons: More development time, integration complexity"
|
|
1229
|
+
},
|
|
1230
|
+
{
|
|
1231
|
+
approach: "Hybrid",
|
|
1232
|
+
rationale: "Combine extension of existing components with new development where needed",
|
|
1233
|
+
applicable: codebaseAnalysis.hasSourceCode,
|
|
1234
|
+
complexity: codebaseAnalysis.hasSourceCode ? 'L' : 'M',
|
|
1235
|
+
tradeoffs: "Pros: Balanced approach, optimal resource usage. Cons: Requires careful integration planning"
|
|
1236
|
+
}
|
|
1237
|
+
];
|
|
1238
|
+
|
|
1239
|
+
const applicableStrategies = strategies.filter(s => s.applicable);
|
|
1240
|
+
const recommendedStrategy = applicableStrategies.find(s => s.approach === 'Hybrid') ||
|
|
1241
|
+
applicableStrategies.find(s => s.approach === 'New Implementation');
|
|
1242
|
+
|
|
1243
|
+
let report = `## Implementation Gap Analysis: ${featureName}\n\n`;
|
|
1244
|
+
|
|
1245
|
+
report += `### Analysis Summary\n`;
|
|
1246
|
+
report += `- **Feature Complexity**: ${complexity} (based on ${requirements.length} requirements)\n`;
|
|
1247
|
+
report += `- **Existing Codebase**: ${codebaseAnalysis.hasSourceCode ? 'Source code detected' : 'No source code structure'}\n`;
|
|
1248
|
+
report += `- **Technology Stack**: ${codebaseAnalysis.techStack.length} dependencies\n`;
|
|
1249
|
+
report += `- **Architecture Type**: ${codebaseAnalysis.architecture}\n\n`;
|
|
1250
|
+
|
|
1251
|
+
report += `### Existing Codebase Insights\n`;
|
|
1252
|
+
report += `- **Package Management**: ${codebaseAnalysis.hasPackageJson ? 'npm/package.json configured' : 'No package.json found'}\n`;
|
|
1253
|
+
report += `- **Source Structure**: ${codebaseAnalysis.hasSourceCode ? 'Established source directories' : 'No conventional source structure'}\n`;
|
|
1254
|
+
report += `- **Key Dependencies**: ${codebaseAnalysis.techStack.slice(0, 5).join(', ') || 'None detected'}\n\n`;
|
|
1255
|
+
|
|
1256
|
+
if (gaps.length > 0) {
|
|
1257
|
+
report += `### Implementation Gaps Identified\n`;
|
|
1258
|
+
gaps.forEach(gap => report += `- ${gap}\n`);
|
|
1259
|
+
report += `\n`;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
report += `### Implementation Strategy Options\n\n`;
|
|
1263
|
+
applicableStrategies.forEach(strategy => {
|
|
1264
|
+
report += `**${strategy.approach} Approach**:\n`;
|
|
1265
|
+
report += `- **Rationale**: ${strategy.rationale}\n`;
|
|
1266
|
+
report += `- **Complexity**: ${strategy.complexity}\n`;
|
|
1267
|
+
report += `- **Trade-offs**: ${strategy.tradeoffs}\n\n`;
|
|
1268
|
+
});
|
|
1269
|
+
|
|
1270
|
+
report += `### Technical Research Needs\n`;
|
|
1271
|
+
const researchNeeds = [];
|
|
1272
|
+
if (!codebaseAnalysis.techStack.includes('@modelcontextprotocol/sdk')) {
|
|
1273
|
+
researchNeeds.push("MCP SDK integration patterns and best practices");
|
|
1274
|
+
}
|
|
1275
|
+
if (requirementsContent.includes('template') || requirementsContent.includes('generation')) {
|
|
1276
|
+
researchNeeds.push("Template engine selection and implementation");
|
|
1277
|
+
}
|
|
1278
|
+
if (requirementsContent.includes('workflow') || requirementsContent.includes('state')) {
|
|
1279
|
+
researchNeeds.push("State machine or workflow engine patterns");
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
if (researchNeeds.length > 0) {
|
|
1283
|
+
researchNeeds.forEach(need => report += `- ${need}\n`);
|
|
1284
|
+
} else {
|
|
1285
|
+
report += `- No significant research dependencies identified\n`;
|
|
1286
|
+
}
|
|
1287
|
+
report += `\n`;
|
|
1288
|
+
|
|
1289
|
+
report += `### Recommendations for Design Phase\n`;
|
|
1290
|
+
report += `- **Preferred Approach**: ${recommendedStrategy.approach} (${recommendedStrategy.complexity} complexity)\n`;
|
|
1291
|
+
report += `- **Key Decisions**: Architecture patterns, technology integration, component boundaries\n`;
|
|
1292
|
+
report += `- **Risk Mitigation**: ${complexity === 'XL' || complexity === 'L' ? 'Consider phased implementation approach' : 'Standard development approach acceptable'}\n`;
|
|
1293
|
+
report += `- **Next Step**: Use this analysis to inform technical design decisions\n`;
|
|
1294
|
+
|
|
1295
|
+
return {
|
|
1296
|
+
content: [{
|
|
1297
|
+
type: 'text',
|
|
1298
|
+
text: report
|
|
1299
|
+
}]
|
|
1300
|
+
};
|
|
1301
|
+
} catch (error) {
|
|
1302
|
+
return {
|
|
1303
|
+
content: [{
|
|
1304
|
+
type: 'text',
|
|
1305
|
+
text: `Error analyzing implementation gap: ${error.message}`
|
|
1306
|
+
}]
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
});
|
|
1310
|
+
|
|
1311
|
+
// 15. sdd-spec-impl - Execute spec tasks using TDD
|
|
1312
|
+
server.registerTool("sdd-spec-impl", {
|
|
1313
|
+
title: "Execute Spec Tasks with TDD",
|
|
1314
|
+
description: "Execute spec tasks using TDD methodology",
|
|
1315
|
+
inputSchema: {
|
|
1316
|
+
featureName: z.string().describe('Feature name to execute tasks for'),
|
|
1317
|
+
taskNumbers: z.string().optional().describe('Specific task numbers to execute (e.g., "1.1,2.3" or leave empty for all pending)')
|
|
1318
|
+
},
|
|
1319
|
+
}, async ({ featureName, taskNumbers }) => {
|
|
1320
|
+
try {
|
|
1321
|
+
const currentPath = process.cwd();
|
|
1322
|
+
const featurePath = path.join(currentPath, '.kiro', 'specs', featureName);
|
|
1323
|
+
const tasksPath = path.join(featurePath, 'tasks.md');
|
|
1324
|
+
const requirementsPath = path.join(featurePath, 'requirements.md');
|
|
1325
|
+
const designPath = path.join(featurePath, 'design.md');
|
|
1326
|
+
const specPath = path.join(featurePath, 'spec.json');
|
|
1327
|
+
|
|
1328
|
+
// Validate required files exist
|
|
1329
|
+
const requiredFiles = [
|
|
1330
|
+
{ path: requirementsPath, name: 'requirements.md' },
|
|
1331
|
+
{ path: designPath, name: 'design.md' },
|
|
1332
|
+
{ path: tasksPath, name: 'tasks.md' },
|
|
1333
|
+
{ path: specPath, name: 'spec.json' }
|
|
1334
|
+
];
|
|
1335
|
+
|
|
1336
|
+
for (const file of requiredFiles) {
|
|
1337
|
+
const exists = await fs.access(file.path).then(() => true).catch(() => false);
|
|
1338
|
+
if (!exists) {
|
|
1339
|
+
return {
|
|
1340
|
+
content: [{
|
|
1341
|
+
type: 'text',
|
|
1342
|
+
text: `Error: Required file ${file.name} not found. Complete the full spec workflow first:\n1. sdd-requirements ${featureName}\n2. sdd-design ${featureName}\n3. sdd-tasks ${featureName}`
|
|
1343
|
+
}]
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
// Load all context documents
|
|
1349
|
+
const tasksContent = await fs.readFile(tasksPath, 'utf8');
|
|
1350
|
+
const specContent = await fs.readFile(specPath, 'utf8');
|
|
1351
|
+
const spec = JSON.parse(specContent);
|
|
1352
|
+
|
|
1353
|
+
// Parse tasks to find pending ones
|
|
1354
|
+
const taskLines = tasksContent.split('\n');
|
|
1355
|
+
const tasks = [];
|
|
1356
|
+
let currentMajorTask = null;
|
|
1357
|
+
|
|
1358
|
+
for (let i = 0; i < taskLines.length; i++) {
|
|
1359
|
+
const line = taskLines[i].trim();
|
|
1360
|
+
|
|
1361
|
+
// Match major tasks (- [ ] 1. Task name)
|
|
1362
|
+
const majorMatch = line.match(/^- \[([ x])\] (\d+)\. (.+)$/);
|
|
1363
|
+
if (majorMatch) {
|
|
1364
|
+
currentMajorTask = {
|
|
1365
|
+
number: majorMatch[2],
|
|
1366
|
+
description: majorMatch[3],
|
|
1367
|
+
completed: majorMatch[1] === 'x',
|
|
1368
|
+
subtasks: []
|
|
1369
|
+
};
|
|
1370
|
+
tasks.push(currentMajorTask);
|
|
1371
|
+
continue;
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
// Match sub-tasks (- [ ] 1.1 Subtask name)
|
|
1375
|
+
const subMatch = line.match(/^- \[([ x])\] (\d+\.\d+) (.+)$/);
|
|
1376
|
+
if (subMatch && currentMajorTask) {
|
|
1377
|
+
currentMajorTask.subtasks.push({
|
|
1378
|
+
number: subMatch[2],
|
|
1379
|
+
description: subMatch[3],
|
|
1380
|
+
completed: subMatch[1] === 'x'
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
// Filter tasks based on taskNumbers parameter
|
|
1386
|
+
let tasksToExecute = [];
|
|
1387
|
+
if (taskNumbers) {
|
|
1388
|
+
const requestedNumbers = taskNumbers.split(',').map(n => n.trim());
|
|
1389
|
+
for (const task of tasks) {
|
|
1390
|
+
if (requestedNumbers.includes(task.number) && !task.completed) {
|
|
1391
|
+
tasksToExecute.push({ type: 'major', task });
|
|
1392
|
+
}
|
|
1393
|
+
for (const subtask of task.subtasks) {
|
|
1394
|
+
if (requestedNumbers.includes(subtask.number) && !subtask.completed) {
|
|
1395
|
+
tasksToExecute.push({ type: 'subtask', task: subtask, parent: task });
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
} else {
|
|
1400
|
+
// Get all pending tasks
|
|
1401
|
+
for (const task of tasks) {
|
|
1402
|
+
if (!task.completed) {
|
|
1403
|
+
tasksToExecute.push({ type: 'major', task });
|
|
1404
|
+
}
|
|
1405
|
+
for (const subtask of task.subtasks) {
|
|
1406
|
+
if (!subtask.completed) {
|
|
1407
|
+
tasksToExecute.push({ type: 'subtask', task: subtask, parent: task });
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
if (tasksToExecute.length === 0) {
|
|
1414
|
+
return {
|
|
1415
|
+
content: [{
|
|
1416
|
+
type: 'text',
|
|
1417
|
+
text: `## No Pending Tasks Found\n\n**Feature**: ${featureName}\n**Status**: ${taskNumbers ? 'Specified tasks already completed or not found' : 'All tasks already completed'}\n\n${taskNumbers ? `**Requested**: ${taskNumbers}` : '**All tasks**: ✅ Completed'}\n\nUse \`sdd-status ${featureName}\` to check current progress.`
|
|
1418
|
+
}]
|
|
1419
|
+
};
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
// Generate TDD implementation guidance for the tasks
|
|
1423
|
+
let report = `## TDD Implementation Execution: ${featureName}\n\n`;
|
|
1424
|
+
report += `**Tasks to Execute**: ${tasksToExecute.length} pending tasks\n`;
|
|
1425
|
+
report += `**TDD Methodology**: Kent Beck's Red → Green → Refactor cycle\n\n`;
|
|
1426
|
+
|
|
1427
|
+
report += `### Context Loaded\n`;
|
|
1428
|
+
report += `- ✅ Requirements: .kiro/specs/${featureName}/requirements.md\n`;
|
|
1429
|
+
report += `- ✅ Design: .kiro/specs/${featureName}/design.md\n`;
|
|
1430
|
+
report += `- ✅ Tasks: .kiro/specs/${featureName}/tasks.md\n`;
|
|
1431
|
+
report += `- ✅ Metadata: .kiro/specs/${featureName}/spec.json\n\n`;
|
|
1432
|
+
|
|
1433
|
+
report += `### TDD Implementation Plan\n\n`;
|
|
1434
|
+
|
|
1435
|
+
tasksToExecute.slice(0, 5).forEach((item, index) => {
|
|
1436
|
+
const task = item.task;
|
|
1437
|
+
const taskNumber = item.type === 'subtask' ? task.number : task.number;
|
|
1438
|
+
const taskDesc = task.description;
|
|
1439
|
+
|
|
1440
|
+
report += `**Task ${taskNumber}**: ${taskDesc}\n\n`;
|
|
1441
|
+
report += `**TDD Cycle for this task**:\n`;
|
|
1442
|
+
report += `1. 🔴 **RED**: Write failing tests for "${taskDesc}"\n`;
|
|
1443
|
+
report += ` - Define test cases that specify expected behavior\n`;
|
|
1444
|
+
report += ` - Ensure tests fail initially (no implementation yet)\n`;
|
|
1445
|
+
report += ` - Verify test framework and setup is working\n\n`;
|
|
1446
|
+
|
|
1447
|
+
report += `2. 🟢 **GREEN**: Write minimal code to pass tests\n`;
|
|
1448
|
+
report += ` - Implement only what's needed to make tests pass\n`;
|
|
1449
|
+
report += ` - Focus on making it work, not making it perfect\n`;
|
|
1450
|
+
report += ` - Avoid over-engineering at this stage\n\n`;
|
|
1451
|
+
|
|
1452
|
+
report += `3. 🔵 **REFACTOR**: Clean up and improve code structure\n`;
|
|
1453
|
+
report += ` - Improve code quality while keeping tests green\n`;
|
|
1454
|
+
report += ` - Remove duplication and improve naming\n`;
|
|
1455
|
+
report += ` - Ensure code follows project conventions\n\n`;
|
|
1456
|
+
|
|
1457
|
+
report += `4. ✅ **VERIFY**: Complete task verification\n`;
|
|
1458
|
+
report += ` - All tests pass (new and existing)\n`;
|
|
1459
|
+
report += ` - Code quality meets standards\n`;
|
|
1460
|
+
report += ` - No regressions in existing functionality\n`;
|
|
1461
|
+
report += ` - Mark task as completed: \`- [x] ${taskNumber} ${taskDesc}\`\n\n`;
|
|
1462
|
+
});
|
|
1463
|
+
|
|
1464
|
+
if (tasksToExecute.length > 5) {
|
|
1465
|
+
report += `... and ${tasksToExecute.length - 5} more tasks\n\n`;
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
report += `### Implementation Guidelines\n`;
|
|
1469
|
+
report += `- **Follow design specifications**: Implement exactly what's specified in design.md\n`;
|
|
1470
|
+
report += `- **Test-first approach**: Always write tests before implementation code\n`;
|
|
1471
|
+
report += `- **Incremental progress**: Complete one task fully before moving to next\n`;
|
|
1472
|
+
report += `- **Update task status**: Mark checkboxes as completed in tasks.md\n`;
|
|
1473
|
+
report += `- **Quality focus**: Maintain code quality and test coverage\n\n`;
|
|
1474
|
+
|
|
1475
|
+
report += `### Next Steps\n`;
|
|
1476
|
+
report += `1. Start with the first pending task: "${tasksToExecute[0].task.description}"\n`;
|
|
1477
|
+
report += `2. Follow the TDD cycle: Red → Green → Refactor → Verify\n`;
|
|
1478
|
+
report += `3. Update tasks.md to mark completed tasks with [x]\n`;
|
|
1479
|
+
report += `4. Run \`sdd-quality-check\` to validate code quality\n`;
|
|
1480
|
+
report += `5. Continue with remaining tasks sequentially\n\n`;
|
|
1481
|
+
|
|
1482
|
+
report += `**Remember**: TDD is about building confidence through tests. Write tests that clearly specify the expected behavior, then implement the simplest solution that makes those tests pass.`;
|
|
1483
|
+
|
|
1484
|
+
return {
|
|
1485
|
+
content: [{
|
|
1486
|
+
type: 'text',
|
|
1487
|
+
text: report
|
|
1488
|
+
}]
|
|
1489
|
+
};
|
|
1490
|
+
} catch (error) {
|
|
1491
|
+
return {
|
|
1492
|
+
content: [{
|
|
1493
|
+
type: 'text',
|
|
1494
|
+
text: `Error executing spec implementation: ${error.message}`
|
|
1495
|
+
}]
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
});
|
|
1499
|
+
|
|
1500
|
+
const transport = new StdioServerTransport();
|
|
1501
|
+
await server.connect(transport);
|