@codemcp/workflows 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/SKILL.md +23 -0
  2. package/package.json +6 -2
  3. package/.prettierignore +0 -2
  4. package/.turbo/turbo-build.log +0 -4
  5. package/.vibe/conversation-state.sqlite +0 -0
  6. package/src/components/beads/beads-instruction-generator.ts +0 -230
  7. package/src/components/beads/beads-plan-manager.ts +0 -333
  8. package/src/components/beads/beads-task-backend-client.ts +0 -229
  9. package/src/index.ts +0 -93
  10. package/src/notification-service.ts +0 -23
  11. package/src/plugin-system/beads-plugin.ts +0 -649
  12. package/src/plugin-system/commit-plugin.ts +0 -252
  13. package/src/plugin-system/index.ts +0 -20
  14. package/src/plugin-system/plugin-interfaces.ts +0 -153
  15. package/src/plugin-system/plugin-registry.ts +0 -190
  16. package/src/resource-handlers/conversation-state.ts +0 -55
  17. package/src/resource-handlers/development-plan.ts +0 -48
  18. package/src/resource-handlers/index.ts +0 -73
  19. package/src/resource-handlers/system-prompt.ts +0 -55
  20. package/src/resource-handlers/workflow-resource.ts +0 -132
  21. package/src/response-renderer.ts +0 -116
  22. package/src/server-config.ts +0 -760
  23. package/src/server-helpers.ts +0 -245
  24. package/src/server-implementation.ts +0 -277
  25. package/src/server.ts +0 -9
  26. package/src/tool-handlers/base-tool-handler.ts +0 -151
  27. package/src/tool-handlers/conduct-review.ts +0 -190
  28. package/src/tool-handlers/get-tool-info.ts +0 -273
  29. package/src/tool-handlers/index.ts +0 -115
  30. package/src/tool-handlers/list-workflows.ts +0 -78
  31. package/src/tool-handlers/no-idea.ts +0 -47
  32. package/src/tool-handlers/proceed-to-phase.ts +0 -296
  33. package/src/tool-handlers/reset-development.ts +0 -90
  34. package/src/tool-handlers/resume-workflow.ts +0 -378
  35. package/src/tool-handlers/setup-project-docs.ts +0 -232
  36. package/src/tool-handlers/start-development.ts +0 -746
  37. package/src/tool-handlers/whats-next.ts +0 -246
  38. package/src/types.ts +0 -135
  39. package/src/version-info.ts +0 -213
  40. package/test/e2e/beads-plugin-integration.test.ts +0 -1623
  41. package/test/e2e/commit-plugin-integration.test.ts +0 -222
  42. package/test/e2e/core-functionality.test.ts +0 -167
  43. package/test/e2e/git-branch-detection.test.ts +0 -351
  44. package/test/e2e/mcp-contract.test.ts +0 -509
  45. package/test/e2e/plan-management.test.ts +0 -334
  46. package/test/e2e/plugin-system-integration.test.ts +0 -1410
  47. package/test/e2e/state-management.test.ts +0 -387
  48. package/test/e2e/workflow-integration.test.ts +0 -498
  49. package/test/unit/beads-instruction-generator.test.ts +0 -979
  50. package/test/unit/beads-phase-task-id-integration.test.ts +0 -535
  51. package/test/unit/beads-plugin-behavioral.test.ts +0 -545
  52. package/test/unit/beads-plugin.test.ts +0 -117
  53. package/test/unit/commit-plugin.test.ts +0 -196
  54. package/test/unit/conduct-review.test.ts +0 -151
  55. package/test/unit/conversation-not-found-error.test.ts +0 -120
  56. package/test/unit/plugin-error-handling.test.ts +0 -240
  57. package/test/unit/proceed-to-phase-plugin-integration.test.ts +0 -150
  58. package/test/unit/reset-functionality.test.ts +0 -72
  59. package/test/unit/resume-workflow.test.ts +0 -193
  60. package/test/unit/server-config-plugin-registry.test.ts +0 -99
  61. package/test/unit/server-tools.test.ts +0 -310
  62. package/test/unit/setup-project-docs-handler.test.ts +0 -268
  63. package/test/unit/start-development-artifact-detection.test.ts +0 -387
  64. package/test/unit/start-development-gitignore.test.ts +0 -178
  65. package/test/unit/start-development-goal-extraction.test.ts +0 -226
  66. package/test/unit/system-prompt-resource.test.ts +0 -102
  67. package/test/unit/tool-handlers/no-idea.test.ts +0 -40
  68. package/test/utils/e2e-test-setup.ts +0 -451
  69. package/test/utils/run-server-in-dir.sh +0 -27
  70. package/test/utils/temp-files.ts +0 -320
  71. package/test/utils/test-access.ts +0 -79
  72. package/test/utils/test-helpers.ts +0 -288
  73. package/test/utils/test-setup.ts +0 -77
  74. package/tsconfig.build.json +0 -10
  75. package/tsconfig.build.tsbuildinfo +0 -1
  76. package/tsconfig.json +0 -12
  77. package/vitest.config.ts +0 -19
package/SKILL.md ADDED
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: responsible-vibe
3
+ description: >
4
+ Structured development workflows for AI-assisted coding. Use when starting
5
+ new features, fixing bugs, following TDD, refactoring code, or any development
6
+ task that benefits from planning and structure. Activate it when
7
+ users mention to build, enhance or fix code.
8
+ allowed-tools: >
9
+ whats_next proceed_to_phase conduct_review start_development
10
+ resume_workflow reset_development list_workflows get_tool_info
11
+ setup_project_docs
12
+ license: MIT
13
+ metadata:
14
+ version: '5.1.0'
15
+ repository: https://github.com/mrsimpson/responsible-vibe-mcp
16
+ author: mrsimpson
17
+ requires-mcp-servers:
18
+ - name: responsible-vibe-workflows
19
+ package: '@codemcp/workflows'
20
+ description: 'Structured development workflows for AI-assisted coding'
21
+ command: npx
22
+ args: ['-y', '@codemcp/workflows']
23
+ ---
package/package.json CHANGED
@@ -1,15 +1,19 @@
1
1
  {
2
2
  "name": "@codemcp/workflows",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "MCP server implementation for responsible-vibe",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
8
  "responsible-vibe-mcp": "dist/index.js"
9
9
  },
10
+ "files": [
11
+ "dist/**/*",
12
+ "SKILL.md"
13
+ ],
10
14
  "dependencies": {
11
15
  "@modelcontextprotocol/sdk": "1.25.3",
12
- "@codemcp/workflows-core": "5.0.0"
16
+ "@codemcp/workflows-core": "5.1.0"
13
17
  },
14
18
  "devDependencies": {
15
19
  "@types/node": "^22.0.0",
package/.prettierignore DELETED
@@ -1,2 +0,0 @@
1
- dist/
2
- node_modules/
@@ -1,4 +0,0 @@
1
-
2
- > @codemcp/workflows@5.0.0 build /home/runner/work/responsible-vibe-mcp/responsible-vibe-mcp/packages/mcp-server
3
- > tsc -p tsconfig.build.json
4
-
Binary file
@@ -1,230 +0,0 @@
1
- /**
2
- * Beads Instruction Generator
3
- *
4
- * Beads-specific implementation of IInstructionGenerator.
5
- * Generates instructions optimized for beads task management workflow.
6
- */
7
-
8
- import {
9
- type IInstructionGenerator,
10
- type InstructionContext,
11
- type GeneratedInstructions,
12
- type YamlStateMachine,
13
- ProjectDocsManager,
14
- } from '@codemcp/workflows-core';
15
-
16
- /**
17
- * Beads-specific instruction generator
18
- */
19
- export class BeadsInstructionGenerator implements IInstructionGenerator {
20
- private projectDocsManager: ProjectDocsManager;
21
-
22
- constructor() {
23
- this.projectDocsManager = new ProjectDocsManager();
24
- }
25
-
26
- /**
27
- * Set the state machine definition (interface requirement)
28
- */
29
- setStateMachine(_stateMachine: YamlStateMachine): void {
30
- // No-op: beads uses CLI for state management
31
- }
32
-
33
- /**
34
- * Generate comprehensive instructions optimized for beads workflow
35
- */
36
- async generateInstructions(
37
- baseInstructions: string,
38
- context: InstructionContext
39
- ): Promise<GeneratedInstructions> {
40
- // Apply variable substitution to base instructions
41
- const substitutedInstructions = this.applyVariableSubstitution(
42
- baseInstructions,
43
- context.conversationContext.projectPath,
44
- context.conversationContext.gitBranch
45
- );
46
-
47
- // Enhance base instructions with beads-specific guidance
48
- const enhancedInstructions = await this.enhanceBeadsInstructions(
49
- substitutedInstructions,
50
- context
51
- );
52
-
53
- return {
54
- instructions: enhancedInstructions,
55
- planFileGuidance:
56
- 'Using beads CLI for task management - plan file serves as context only',
57
- metadata: {
58
- phase: context.phase,
59
- planFilePath: context.conversationContext.planFilePath,
60
- transitionReason: context.transitionReason,
61
- isModeled: context.isModeled,
62
- },
63
- };
64
- }
65
-
66
- /**
67
- * Apply variable substitution to instructions
68
- */
69
- private applyVariableSubstitution(
70
- instructions: string,
71
- projectPath: string,
72
- gitBranch?: string
73
- ): string {
74
- const substitutions = this.projectDocsManager.getVariableSubstitutions(
75
- projectPath,
76
- gitBranch
77
- );
78
-
79
- let result = instructions;
80
- for (const [variable, value] of Object.entries(substitutions)) {
81
- result = result.replace(
82
- new RegExp(this.escapeRegExp(variable), 'g'),
83
- value
84
- );
85
- }
86
-
87
- return result;
88
- }
89
-
90
- /**
91
- * Escape special regex characters in variable names
92
- */
93
- private escapeRegExp(string: string): string {
94
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
95
- }
96
-
97
- /**
98
- * Enhance instructions with beads-specific guidance
99
- */
100
- private async enhanceBeadsInstructions(
101
- baseInstructions: string,
102
- context: InstructionContext
103
- ): Promise<string> {
104
- const { planFileExists } = context;
105
-
106
- // Generate beads-specific task management guidance
107
- const beadsTaskGuidance = await this.generateBeadsCLIGuidance(context);
108
-
109
- // Beads-optimized instruction structure
110
- let enhanced = `${baseInstructions}
111
-
112
- **Plan File Guidance:**
113
- Use the plan file as memory for the current objective
114
- - Update the "Key Decisions" section with important choices made
115
- - Add relevant notes to help maintain context
116
- - Do NOT enter tasks in the plan file, use beads CLI exclusively for task management
117
-
118
- ${beadsTaskGuidance}`;
119
-
120
- // Add plan file creation note if needed
121
- if (!planFileExists) {
122
- enhanced +=
123
- '\n\n**Note**: Plan file will be created when you first update it.';
124
- }
125
-
126
- // Add beads-specific reminders
127
- enhanced += `\n\n**Important Reminders:**
128
- - Use ONLY bd CLI tool for task management - do not use your own task management tools
129
- - Call whats_next() after the next user message to maintain the development workflow`;
130
-
131
- return enhanced;
132
- }
133
-
134
- /**
135
- * Generate beads-specific task management guidance
136
- */
137
- private async generateBeadsCLIGuidance(
138
- context: InstructionContext
139
- ): Promise<string> {
140
- const { instructionSource } = context;
141
-
142
- // For whats_next, provide detailed guidance
143
- if (instructionSource === 'whats_next') {
144
- let additionalInstructions = `**bd Task Management:**
145
- `;
146
-
147
- const phaseTaskId = await this.extractPhaseTaskId(context);
148
-
149
- if (!phaseTaskId) {
150
- return (
151
- additionalInstructions +
152
- `- Use bd CLI tool exclusively
153
- - **Start by listing ready tasks**: \`bd list --parent <phase-task-id> --status open\`
154
- - **Create new tasks**: \`bd create 'Task title' --parent <phase-task-id> -p <priority>\`
155
- - **Update status when working**: \`bd update <task-id> --status in_progress\`
156
- - **Complete tasks**: \`bd close <task-id>\`
157
- - **Focus on ready tasks first** - let beads handle dependencies
158
- - Add new tasks as they are identified during your work with the user`
159
- );
160
- }
161
-
162
- return (
163
- additionalInstructions +
164
- `
165
- **Focus on subtasks of \`${phaseTaskId}\`**:
166
- • \`bd list --parent ${phaseTaskId} --status open\` - List ready work items
167
- • \`bd update <task-id> --status in_progress\` - Start working on a specific task
168
- • \`bd close <task-id>\` - Mark task complete when finished
169
-
170
- **New Tasks for Current Phase**:
171
- • \`bd create 'Task description' --parent ${phaseTaskId} -p <priority>\` - Create work item under current phase
172
- • \`bd dep add <task-id> <depends-on-id>\` - Define dependencies for a task:`
173
- );
174
- }
175
-
176
- return '';
177
- }
178
-
179
- private async extractPhaseTaskId(
180
- context: InstructionContext
181
- ): Promise<string | null> {
182
- try {
183
- const { readFile } = await import('node:fs/promises');
184
- const content = await readFile(
185
- context.conversationContext.planFilePath,
186
- 'utf-8'
187
- );
188
-
189
- const phaseName = this.capitalizePhase(context.phase);
190
- const phaseHeader = `## ${phaseName}`;
191
-
192
- // Look for the phase header followed by beads-phase-id comment
193
- const phaseSection = content.split('\n');
194
- let foundPhaseHeader = false;
195
-
196
- for (const line of phaseSection) {
197
- if (line.trim() === phaseHeader) {
198
- foundPhaseHeader = true;
199
- continue;
200
- }
201
-
202
- if (foundPhaseHeader && line.includes('beads-phase-id:')) {
203
- const match = line.match(/beads-phase-id:\s*([\w\d.-]+)/);
204
- if (match) {
205
- return match[1] || null;
206
- }
207
- }
208
-
209
- // Stop looking if we hit the next phase header
210
- if (foundPhaseHeader && line.startsWith('##') && line !== phaseHeader) {
211
- break;
212
- }
213
- }
214
-
215
- return null;
216
- } catch (_error) {
217
- return null;
218
- }
219
- }
220
-
221
- /**
222
- * Capitalize phase name for display
223
- */
224
- private capitalizePhase(phase: string): string {
225
- return phase
226
- .split('_')
227
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
228
- .join(' ');
229
- }
230
- }
@@ -1,333 +0,0 @@
1
- /**
2
- * Beads Plan Manager
3
- *
4
- * Beads-specific implementation of IPlanManager.
5
- * Manages plan files optimized for beads task management workflow.
6
- */
7
-
8
- import {
9
- type IPlanManager,
10
- type PlanFileInfo,
11
- type YamlStateMachine,
12
- type TaskBackendConfig,
13
- createLogger,
14
- } from '@codemcp/workflows-core';
15
- import { writeFile, readFile, access } from 'node:fs/promises';
16
- import { dirname } from 'node:path';
17
- import { mkdir } from 'node:fs/promises';
18
-
19
- const logger = createLogger('BeadsPlanManager');
20
-
21
- /**
22
- * Beads-specific plan manager implementation
23
- */
24
- export class BeadsPlanManager implements IPlanManager {
25
- private stateMachine: YamlStateMachine | null = null;
26
-
27
- /**
28
- * Set the state machine definition for dynamic plan generation
29
- */
30
- setStateMachine(stateMachine: YamlStateMachine): void {
31
- this.stateMachine = stateMachine;
32
- logger.debug('State machine set for beads plan manager', {
33
- name: stateMachine.name,
34
- phases: Object.keys(stateMachine.states),
35
- });
36
- }
37
-
38
- /**
39
- * Set the task backend configuration
40
- */
41
- setTaskBackend(taskBackend: TaskBackendConfig): void {
42
- // Task backend is implicit for beads plan manager (always beads)
43
- logger.debug('Task backend set for beads plan manager', {
44
- backend: taskBackend.backend,
45
- available: taskBackend.isAvailable,
46
- });
47
- }
48
-
49
- /**
50
- * Get plan file information
51
- */
52
- async getPlanFileInfo(planFilePath: string): Promise<PlanFileInfo> {
53
- try {
54
- await access(planFilePath);
55
- const content = await readFile(planFilePath, 'utf-8');
56
- return {
57
- path: planFilePath,
58
- exists: true,
59
- content,
60
- };
61
- } catch (_error) {
62
- return {
63
- path: planFilePath,
64
- exists: false,
65
- };
66
- }
67
- }
68
-
69
- /**
70
- * Create initial plan file if it doesn't exist
71
- */
72
- async ensurePlanFile(
73
- planFilePath: string,
74
- projectPath: string,
75
- gitBranch: string
76
- ): Promise<void> {
77
- logger.debug('Ensuring beads plan file exists', {
78
- planFilePath,
79
- projectPath,
80
- gitBranch,
81
- });
82
-
83
- const planInfo = await this.getPlanFileInfo(planFilePath);
84
-
85
- if (!planInfo.exists) {
86
- logger.info('Plan file not found, creating beads-optimized plan', {
87
- planFilePath,
88
- });
89
- await this.createInitialBeadsPlanFile(
90
- planFilePath,
91
- projectPath,
92
- gitBranch
93
- );
94
- logger.info('Beads plan file created successfully', { planFilePath });
95
- } else {
96
- logger.debug('Plan file already exists', { planFilePath });
97
- }
98
- }
99
-
100
- /**
101
- * Create initial plan file optimized for beads workflow
102
- */
103
- private async createInitialBeadsPlanFile(
104
- planFilePath: string,
105
- projectPath: string,
106
- gitBranch: string
107
- ): Promise<void> {
108
- logger.debug('Creating beads-optimized plan file', { planFilePath });
109
-
110
- try {
111
- // Ensure directory exists
112
- await mkdir(dirname(planFilePath), { recursive: true });
113
- logger.debug('Plan file directory ensured', {
114
- directory: dirname(planFilePath),
115
- });
116
-
117
- const projectName = projectPath.split('/').pop() || 'Unknown Project';
118
- const branchInfo = gitBranch !== 'no-git' ? ` (${gitBranch} branch)` : '';
119
-
120
- const initialContent = this.generateBeadsInitialPlanContent(
121
- projectName,
122
- branchInfo
123
- );
124
-
125
- await writeFile(planFilePath, initialContent, 'utf-8');
126
- logger.info('Beads plan file written successfully', {
127
- planFilePath,
128
- contentLength: initialContent.length,
129
- projectName,
130
- });
131
- } catch (error) {
132
- logger.error('Failed to create beads plan file', error as Error, {
133
- planFilePath,
134
- });
135
- throw error;
136
- }
137
- }
138
-
139
- /**
140
- * Generate initial plan file content optimized for beads workflow
141
- */
142
- private generateBeadsInitialPlanContent(
143
- projectName: string,
144
- branchInfo: string
145
- ): string {
146
- const timestamp = new Date().toISOString().split('T')[0];
147
-
148
- if (!this.stateMachine) {
149
- throw new Error(
150
- 'State machine not set. This should not happen as state machine is always loaded.'
151
- );
152
- }
153
-
154
- const phases = Object.keys(this.stateMachine.states);
155
- const initialPhase = this.stateMachine.initial_state;
156
-
157
- const documentationUrl = this.generateWorkflowDocumentationUrl(
158
- this.stateMachine.name
159
- );
160
-
161
- let content = `# Development Plan: ${projectName}${branchInfo}
162
-
163
- *Generated on ${timestamp} by Vibe Feature MCP*
164
- *Workflow: ${
165
- documentationUrl
166
- ? '[' + this.stateMachine.name + ']' + '(' + documentationUrl + ')'
167
- : this.stateMachine.name
168
- }*
169
-
170
- ## Goal
171
- *Define what you're building or fixing - this will be updated as requirements are gathered*
172
-
173
- ## ${this.capitalizePhase(initialPhase)}
174
- <!-- beads-phase-id: TBD -->
175
- ### Tasks
176
-
177
- *Tasks managed via \`bd\` CLI*
178
-
179
- `;
180
-
181
- // Generate sections for each phase with beads-specific guidance
182
- for (const phase of phases) {
183
- if (phase !== initialPhase) {
184
- content += `## ${this.capitalizePhase(phase)}
185
- <!-- beads-phase-id: TBD -->
186
- ### Tasks
187
-
188
- *Tasks managed via \`bd\` CLI*
189
-
190
- `;
191
- }
192
- }
193
-
194
- content += `## Key Decisions
195
- *Important decisions will be documented here as they are made*
196
-
197
- ## Notes
198
- *Additional context and observations*
199
-
200
- ---
201
- *This plan is maintained by the LLM and uses beads CLI for task management. Tool responses provide guidance on which bd commands to use for task management.*
202
- `;
203
-
204
- return content;
205
- }
206
-
207
- /**
208
- * Update plan file with new content
209
- */
210
- async updatePlanFile(planFilePath: string, content: string): Promise<void> {
211
- // Ensure directory exists
212
- await mkdir(dirname(planFilePath), { recursive: true });
213
-
214
- await writeFile(planFilePath, content, 'utf-8');
215
- }
216
-
217
- /**
218
- * Get plan file content for LLM context
219
- */
220
- async getPlanFileContent(planFilePath: string): Promise<string> {
221
- const planInfo = await this.getPlanFileInfo(planFilePath);
222
-
223
- if (!planInfo.exists) {
224
- return 'Plan file does not exist yet. It will be created when the LLM updates it.';
225
- }
226
-
227
- return planInfo.content || '';
228
- }
229
-
230
- /**
231
- * Generate phase-specific plan file guidance optimized for beads
232
- */
233
- generatePlanFileGuidance(phase: string): string {
234
- if (!this.stateMachine) {
235
- throw new Error(
236
- 'State machine not set. This should not happen as state machine is always loaded.'
237
- );
238
- }
239
-
240
- const phaseDefinition = this.stateMachine.states[phase];
241
- if (!phaseDefinition) {
242
- logger.warn('Unknown phase for beads plan file guidance', { phase });
243
- return `Track key decisions and take notes in the plan file. Use bd CLI for all task management.`;
244
- }
245
-
246
- return `Track key decisions and take notes in the plan file. Use bd CLI exclusively for task management - never use checkboxes. Document important decisions in the Key Decisions section.`;
247
- }
248
-
249
- /**
250
- * Delete plan file
251
- */
252
- async deletePlanFile(planFilePath: string): Promise<boolean> {
253
- logger.debug('Deleting beads plan file', { planFilePath });
254
-
255
- try {
256
- // Check if file exists first
257
- await access(planFilePath);
258
-
259
- // Import unlink dynamically to avoid issues
260
- const { unlink } = await import('node:fs/promises');
261
- await unlink(planFilePath);
262
-
263
- logger.info('Beads plan file deleted successfully', { planFilePath });
264
- return true;
265
- } catch (error: unknown) {
266
- if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
267
- logger.debug('Beads plan file does not exist, nothing to delete', {
268
- planFilePath,
269
- });
270
- return true; // Consider it successful if file doesn't exist
271
- }
272
-
273
- logger.error('Failed to delete beads plan file', error as Error, {
274
- planFilePath,
275
- });
276
- throw error;
277
- }
278
- }
279
-
280
- /**
281
- * Ensure plan file is deleted (verify deletion)
282
- */
283
- async ensurePlanFileDeleted(planFilePath: string): Promise<boolean> {
284
- logger.debug('Ensuring beads plan file is deleted', { planFilePath });
285
-
286
- try {
287
- await access(planFilePath);
288
- // If we reach here, file still exists
289
- logger.warn('Beads plan file still exists after deletion attempt', {
290
- planFilePath,
291
- });
292
- return false;
293
- } catch (error: unknown) {
294
- if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
295
- logger.debug('Beads plan file successfully deleted (does not exist)', {
296
- planFilePath,
297
- });
298
- return true;
299
- }
300
-
301
- // Some other error occurred
302
- logger.error('Error checking beads plan file deletion', error as Error, {
303
- planFilePath,
304
- });
305
- throw error;
306
- }
307
- }
308
-
309
- /**
310
- * Capitalize phase name for display
311
- */
312
- private capitalizePhase(phase: string): string {
313
- return phase
314
- .split('_')
315
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
316
- .join(' ');
317
- }
318
-
319
- /**
320
- * Generate workflow documentation URL for predefined workflows
321
- */
322
- private generateWorkflowDocumentationUrl(
323
- workflowName: string
324
- ): string | undefined {
325
- // Don't generate URL for custom workflows
326
- if (workflowName === 'custom') {
327
- return undefined;
328
- }
329
-
330
- // Generate URL for predefined workflows
331
- return `https://mrsimpson.github.io/responsible-vibe-mcp/workflows/${workflowName}`;
332
- }
333
- }