bmad-method-mcp
Version:
Breakthrough Method of Agile AI-driven Development with Enhanced MCP Integration
598 lines (505 loc) • 18.3 kB
JavaScript
/**
* BMAD Prompts - MCP Prompt implementations for BMAD workflows
* These prompts provide structured templates for common BMAD operations
*/
class BMadPrompts {
constructor(storage) {
this.storage = storage;
}
async listPrompts() {
return [
{
name: 'bmad_create_story',
description: 'Guided workflow for creating a new story with proper context and acceptance criteria',
arguments: [
{
name: 'epic_num',
description: 'Epic number to create the story in',
required: true
},
{
name: 'context_type',
description: 'Type of story context to include',
required: false
}
]
},
{
name: 'bmad_review_sprint',
description: 'Sprint review template with progress analysis and recommendations',
arguments: [
{
name: 'sprint_id',
description: 'Sprint ID to review (optional, defaults to active sprint)',
required: false
}
]
},
{
name: 'bmad_plan_epic',
description: 'Epic planning template for breaking down large features into stories',
arguments: [
{
name: 'epic_num',
description: 'Epic number to plan',
required: true
}
]
},
{
name: 'bmad_project_status',
description: 'Comprehensive project status report with insights and recommendations',
arguments: []
},
{
name: 'bmad_daily_standup',
description: 'Daily standup template showing progress, blockers, and next steps',
arguments: [
{
name: 'assignee',
description: 'Team member to focus on (optional)',
required: false
}
]
},
{
name: 'bmad_task_handoff',
description: 'Task handoff template for transferring work between agents or team members',
arguments: [
{
name: 'task_id',
description: 'Task ID to hand off',
required: true
},
{
name: 'from_assignee',
description: 'Current assignee',
required: true
},
{
name: 'to_assignee',
description: 'New assignee',
required: true
}
]
}
];
}
async getPrompt(name, args = {}) {
switch (name) {
case 'bmad_create_story':
return await this.createStoryPrompt(args);
case 'bmad_review_sprint':
return await this.reviewSprintPrompt(args);
case 'bmad_plan_epic':
return await this.planEpicPrompt(args);
case 'bmad_project_status':
return await this.projectStatusPrompt(args);
case 'bmad_daily_standup':
return await this.dailyStandupPrompt(args);
case 'bmad_task_handoff':
return await this.taskHandoffPrompt(args);
default:
throw new Error(`Unknown prompt: ${name}`);
}
}
async createStoryPrompt(args) {
const { epic_num, context_type = 'full' } = args;
// Get epic context
const epic = await this.storage.getEpic(epic_num);
const epicTasks = epic ? await this.storage.queryTasks({ epic_num }) : [];
const nextStoryNum = await this.storage.getNextStoryNum(epic_num);
// Get project context
const project = await this.storage.getProject();
const prdDocs = await this.storage.listDocuments('prd');
const archDocs = await this.storage.listDocuments('architecture');
let contextSection = '';
if (context_type === 'full') {
contextSection = `
## Project Context
- **Project**: ${project.name}
- **PRD Available**: ${prdDocs.length > 0 ? 'Yes' : 'No'}
- **Architecture Doc**: ${archDocs.length > 0 ? 'Yes' : 'No'}
## Epic Context
${epic ? `
- **Epic ${epic.epic_num}**: ${epic.title}
- **Description**: ${epic.description}
- **Current Stories**: ${epicTasks.length}
- **Completed**: ${epicTasks.filter(t => t.status === 'DONE').length}
` : `
- **Epic ${epic_num}**: Not yet created (will be auto-created)
- **This will be the first story in this epic**
`}
## Previous Stories Context
${epicTasks.length > 0 ?
epicTasks.slice(-3).map(task =>
`- **${task.epic_num}.${task.story_num}**: ${task.title} (${task.status})`
).join('\n')
: '- No previous stories in this epic'}
`;
}
return {
description: `Create a new story ${epic_num}.${nextStoryNum} with proper context and acceptance criteria`,
messages: [
{
role: 'user',
content: {
type: 'text',
text: `# Create Story ${epic_num}.${nextStoryNum}
I need to create a new story in Epic ${epic_num}. Please help me create a comprehensive story with:
1. **Clear Title**: Concise but descriptive
2. **Detailed Description**: What needs to be built and why
3. **Acceptance Criteria**: Specific, testable conditions for completion
4. **Technical Context**: Any architectural or implementation considerations
5. **Dependencies**: Other stories or external factors this depends on
${contextSection}
## Story Creation Guidelines
**Title Format**: Should be action-oriented (e.g., "Create user authentication API", "Add payment processing")
**Description Should Include**:
- User/business value
- Functional requirements
- Any UI/UX considerations
- Integration points
- Data requirements
**Acceptance Criteria Format**:
- Given [context]
- When [action]
- Then [expected result]
**Technical Notes**:
- Architecture patterns to follow
- Technology choices
- Performance requirements
- Security considerations
Please create the story following this structure and use the bmad_create_story tool to save it.`
}
}
]
};
}
async reviewSprintPrompt(args) {
const { sprint_id } = args;
const sprint = sprint_id ?
await this.storage.get('SELECT * FROM sprints WHERE id = ?', [sprint_id]) :
await this.storage.getActiveSprint();
if (!sprint) {
throw new Error('No sprint found for review');
}
const sprintTasks = await this.storage.queryTasks({ sprint_id: sprint.id });
const progress = await this.storage.getProjectProgress();
const completedTasks = sprintTasks.filter(t => t.status === 'DONE');
const inProgressTasks = sprintTasks.filter(t => t.status === 'IN_PROGRESS');
const blockedTasks = sprintTasks.filter(t => t.status === 'BLOCKED');
return {
description: `Sprint review for ${sprint.name}`,
messages: [
{
role: 'user',
content: {
type: 'text',
text: `# Sprint Review: ${sprint.name}
## Sprint Overview
- **Goal**: ${sprint.goal}
- **Start Date**: ${sprint.start_date || 'Not set'}
- **End Date**: ${sprint.end_date || 'Not set'}
- **Status**: ${sprint.status}
## Sprint Metrics
- **Total Tasks**: ${sprintTasks.length}
- **Completed**: ${completedTasks.length}
- **In Progress**: ${inProgressTasks.length}
- **Blocked**: ${blockedTasks.length}
- **Completion Rate**: ${sprintTasks.length > 0 ? Math.round((completedTasks.length / sprintTasks.length) * 100) : 0}%
## Completed Stories
${completedTasks.length > 0 ?
completedTasks.map(task =>
`- ✅ **${task.epic_num}.${task.story_num}**: ${task.title}`
).join('\n')
: '- No stories completed this sprint'}
## In Progress
${inProgressTasks.length > 0 ?
inProgressTasks.map(task =>
`- 🔄 **${task.epic_num}.${task.story_num}**: ${task.title} (${task.assignee || 'Unassigned'})`
).join('\n')
: '- No stories in progress'}
## Blocked Items
${blockedTasks.length > 0 ?
blockedTasks.map(task =>
`- 🚫 **${task.epic_num}.${task.story_num}**: ${task.title} (${task.assignee || 'Unassigned'})`
).join('\n')
: '- No blocked stories'}
## Review Questions
Please analyze this sprint data and provide insights on:
1. **Sprint Goal Achievement**: How well did we meet the sprint goal?
2. **Velocity Analysis**: Is our completion rate on track?
3. **Blocker Resolution**: What can we do about blocked items?
4. **Process Improvements**: What went well and what could be better?
5. **Next Sprint Planning**: What should be priorities for the next sprint?
Use the available bmad tools to get additional context as needed.`
}
}
]
};
}
async planEpicPrompt(args) {
const { epic_num } = args;
const epic = await this.storage.getEpic(epic_num);
const existingTasks = epic ? await this.storage.queryTasks({ epic_num }) : [];
const project = await this.storage.getProject();
return {
description: `Epic planning session for Epic ${epic_num}`,
messages: [
{
role: 'user',
content: {
type: 'text',
text: `# Epic Planning: Epic ${epic_num}
## Current Epic Status
${epic ? `
- **Title**: ${epic.title}
- **Description**: ${epic.description}
- **Status**: ${epic.status}
- **Existing Stories**: ${existingTasks.length}
` : `
- **Epic ${epic_num}**: Not yet created
- **This is a new epic planning session**
`}
## Epic Planning Framework
An epic should be broken down into deliverable stories that:
1. **Provide incremental value**
2. **Can be completed in 1-3 days**
3. **Have clear acceptance criteria**
4. **Build upon each other logically**
## Planning Steps
### 1. Epic Definition
${epic ? 'Review and refine the current epic definition:' : 'Define the epic:'}
- **Business Value**: What problem does this solve?
- **User Impact**: Who benefits and how?
- **Success Criteria**: How will we know when it's complete?
- **Scope Boundaries**: What's included and excluded?
### 2. Story Decomposition
Break down the epic into logical stories:
- **Foundation Stories**: Basic setup, models, infrastructure
- **Core Feature Stories**: Main functionality
- **Integration Stories**: Connecting with other systems
- **Polish Stories**: UI improvements, error handling, edge cases
### 3. Story Prioritization
Order stories by:
- **Dependencies**: What must come first?
- **Risk**: Tackle unknowns early
- **Value**: High-impact features first
- **Effort**: Mix of quick wins and larger features
### 4. Estimation
Consider for each story:
- **Complexity**: Technical difficulty
- **Unknowns**: Research or learning required
- **Dependencies**: External factors
- **Testing**: Validation requirements
## Current Project Context
- **Project**: ${project.name}
- **Total Epics**: ${(await this.storage.listEpics()).length}
- **Total Stories**: ${(await this.storage.queryTasks()).length}
Please help me plan this epic by:
1. Defining or refining the epic scope
2. Breaking it down into stories
3. Sequencing the stories logically
4. Identifying any dependencies or risks
Use the bmad_create_epic and bmad_create_story tools as we work through this planning session.`
}
}
]
};
}
async projectStatusPrompt(args) {
const project = await this.storage.getProject();
const progress = await this.storage.getProjectProgress();
const epics = await this.storage.listEpics();
const sprints = await this.storage.listSprints();
const activeSprint = await this.storage.getActiveSprint();
const totalTasks = progress.totalTasks;
const completionPercentage = totalTasks > 0 ?
Math.round(((progress.byStatus.DONE || 0) / totalTasks) * 100) : 0;
return {
description: 'Comprehensive project status report',
messages: [
{
role: 'user',
content: {
type: 'text',
text: `# Project Status Report: ${project.name}
## Project Overview
- **Name**: ${project.name}
- **Description**: ${project.description || 'No description available'}
- **Overall Progress**: ${completionPercentage}% complete
- **Total Tasks**: ${totalTasks}
## Progress Breakdown
${Object.entries(progress.byStatus).map(([status, count]) =>
`- **${status}**: ${count} tasks`
).join('\n')}
## Epic Summary
- **Total Epics**: ${epics.length}
${Object.entries(progress.byEpic).map(([epicNum, count]) => {
const epic = epics.find(e => e.epic_num == epicNum);
return `- **Epic ${epicNum}**: ${count} tasks ${epic ? `(${epic.title})` : ''}`;
}).join('\n')}
## Sprint Information
- **Total Sprints**: ${sprints.length}
- **Active Sprint**: ${activeSprint ? activeSprint.name : 'None'}
${activeSprint ? `- **Sprint Goal**: ${activeSprint.goal}` : ''}
## Key Insights Request
Please analyze this project status and provide insights on:
1. **Health Assessment**: Is the project on track?
2. **Velocity Trends**: How is our completion rate?
3. **Bottleneck Analysis**: Where are we getting stuck?
4. **Resource Allocation**: Are tasks distributed well?
5. **Risk Factors**: What could impact delivery?
6. **Recommendations**: What actions should we take?
## Next Steps Analysis
Consider:
- **Priority Tasks**: What should be worked on next?
- **Blocked Items**: What needs unblocking?
- **Sprint Planning**: What should go in the next sprint?
- **Epic Management**: Any epics need attention?
Use bmad_query_tasks and other tools to get detailed data for your analysis.`
}
}
]
};
}
async dailyStandupPrompt(args) {
const { assignee } = args;
const allTasks = await this.storage.queryTasks();
const inProgressTasks = allTasks.filter(t => t.status === 'IN_PROGRESS');
const blockedTasks = allTasks.filter(t => t.status === 'BLOCKED');
const recentlyCompleted = allTasks.filter(t =>
t.status === 'DONE' &&
new Date(t.updated_at) > new Date(Date.now() - 24 * 60 * 60 * 1000)
);
const focusTasks = assignee ?
allTasks.filter(t => t.assignee === assignee) :
allTasks;
return {
description: assignee ? `Daily standup for ${assignee}` : 'Team daily standup',
messages: [
{
role: 'user',
content: {
type: 'text',
text: `# Daily Standup ${assignee ? `- ${assignee}` : '- Team'}
## Yesterday's Completed Work
${recentlyCompleted.length > 0 ?
recentlyCompleted
.filter(t => !assignee || t.assignee === assignee)
.map(task => `- ✅ **${task.epic_num}.${task.story_num}**: ${task.title}`)
.join('\n')
: '- No tasks completed yesterday'}
## Today's In Progress Work
${inProgressTasks.length > 0 ?
inProgressTasks
.filter(t => !assignee || t.assignee === assignee)
.map(task => `- 🔄 **${task.epic_num}.${task.story_num}**: ${task.title}`)
.join('\n')
: '- No tasks currently in progress'}
## Blockers and Issues
${blockedTasks.length > 0 ?
blockedTasks
.filter(t => !assignee || t.assignee === assignee)
.map(task => `- 🚫 **${task.epic_num}.${task.story_num}**: ${task.title}`)
.join('\n')
: '- No current blockers'}
## Team Overview
${!assignee ? `
- **Total Active Work**: ${inProgressTasks.length} tasks
- **Team Blockers**: ${blockedTasks.length} tasks
- **Recent Completions**: ${recentlyCompleted.length} tasks
### Work Distribution
${['dev', 'qa', 'sm', 'pm'].map(role => {
const roleTasks = allTasks.filter(t => t.assignee === role && ['TODO', 'IN_PROGRESS'].includes(t.status));
return `- **${role}**: ${roleTasks.length} active tasks`;
}).join('\n')}
` : ''}
## Standup Questions
Please provide updates on:
1. **What was accomplished yesterday?**
2. **What's planned for today?**
3. **Any blockers or impediments?**
4. **Any help needed from team members?**
5. **Are we on track for sprint goals?**
${assignee ?
`Focus on ${assignee}'s work and any cross-team dependencies.` :
'Consider overall team coordination and sprint progress.'
}
Use bmad tools to get additional task details or update statuses as needed.`
}
}
]
};
}
async taskHandoffPrompt(args) {
const { task_id, from_assignee, to_assignee } = args;
const task = await this.storage.getTask(task_id);
if (!task) {
throw new Error(`Task not found: ${task_id}`);
}
const epic = await this.storage.getEpic(task.epic_num);
return {
description: `Task handoff from ${from_assignee} to ${to_assignee}`,
messages: [
{
role: 'user',
content: {
type: 'text',
text: `# Task Handoff: ${task.epic_num}.${task.story_num}
## Task Information
- **Title**: ${task.title}
- **Epic**: ${epic ? epic.title : `Epic ${task.epic_num}`}
- **Current Status**: ${task.status}
- **From**: ${from_assignee}
- **To**: ${to_assignee}
## Task Description
${task.description}
## Handoff Checklist
### Current Progress
- [ ] What work has been completed?
- [ ] What files/components were created or modified?
- [ ] What testing has been done?
- [ ] Are there any temporary workarounds in place?
### Technical Context
- [ ] What approach is being taken?
- [ ] Any architectural decisions made?
- [ ] Dependencies on other systems/components?
- [ ] Performance or security considerations?
### Outstanding Work
- [ ] What still needs to be done?
- [ ] Any known issues or edge cases?
- [ ] Acceptance criteria remaining?
- [ ] Testing requirements?
### Knowledge Transfer
- [ ] Code walkthrough completed?
- [ ] Documentation updated?
- [ ] Access permissions transferred?
- [ ] Tools and environments setup?
### Next Steps
- [ ] Immediate next actions defined?
- [ ] Timeline expectations set?
- [ ] Communication plan established?
- [ ] Handback criteria agreed upon?
## Handoff Notes
Please provide details for each section above. Consider:
1. **Technical State**: Exactly where is the implementation?
2. **Context**: Why were certain decisions made?
3. **Blockers**: What was preventing progress?
4. **Recommendations**: Best path forward?
Once the handoff is complete, use bmad_update_task_status to assign the task to ${to_assignee}.
## Task Metadata
- **Task ID**: ${task_id}
- **Created**: ${task.created_at}
- **Last Updated**: ${task.updated_at}
- **Priority**: ${task.priority}
- **Estimated Hours**: ${task.estimated_hours || 'Not estimated'}
- **Actual Hours**: ${task.actual_hours || 'Not tracked'}`
}
}
]
};
}
}
module.exports = BMadPrompts;