@proletariat/cli 0.3.22 → 0.3.24

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 (173) hide show
  1. package/LICENSE +190 -21
  2. package/README.md +7 -7
  3. package/dist/commands/action/create.js +1 -1
  4. package/dist/commands/agent/{temp/cleanup.d.ts → cleanup.d.ts} +1 -1
  5. package/dist/commands/agent/{temp/cleanup.js → cleanup.js} +4 -4
  6. package/dist/commands/agent/index.js +8 -8
  7. package/dist/commands/branch/create.js +2 -2
  8. package/dist/commands/epic/create.d.ts +1 -0
  9. package/dist/commands/epic/create.js +39 -2
  10. package/dist/commands/epic/index.js +2 -2
  11. package/dist/commands/{epic/link/remove.d.ts → link/create.d.ts} +6 -7
  12. package/dist/commands/link/create.js +141 -0
  13. package/dist/commands/{epic/link/relates.d.ts → link/index.d.ts} +4 -5
  14. package/dist/commands/link/index.js +87 -0
  15. package/dist/commands/{epic/link/duplicates.d.ts → link/list.d.ts} +7 -4
  16. package/dist/commands/link/list.js +182 -0
  17. package/dist/commands/{spec/link → link}/remove.d.ts +4 -5
  18. package/dist/commands/link/remove.js +120 -0
  19. package/dist/commands/mcp-server.d.ts +22 -0
  20. package/dist/commands/mcp-server.js +98 -0
  21. package/dist/commands/phase/create.js +1 -1
  22. package/dist/commands/project/create.d.ts +1 -0
  23. package/dist/commands/project/create.js +38 -4
  24. package/dist/commands/spec/create.d.ts +1 -0
  25. package/dist/commands/spec/create.js +43 -2
  26. package/dist/commands/spec/index.js +2 -2
  27. package/dist/commands/{agent/staff → staff}/add.js +10 -10
  28. package/dist/commands/{agent/staff → staff}/index.d.ts +1 -1
  29. package/dist/commands/{agent/staff → staff}/index.js +7 -7
  30. package/dist/commands/{agent/staff → staff}/list.js +3 -3
  31. package/dist/commands/{agent/staff → staff}/remove.d.ts +1 -1
  32. package/dist/commands/{agent/staff → staff}/remove.js +8 -8
  33. package/dist/commands/{ticket/template → template}/apply.d.ts +8 -6
  34. package/dist/commands/template/apply.js +262 -0
  35. package/dist/commands/{ticket/template → template}/create.d.ts +5 -6
  36. package/dist/commands/template/create.js +238 -0
  37. package/dist/commands/template/index.js +48 -36
  38. package/dist/commands/{ticket/template → template}/save.d.ts +2 -2
  39. package/dist/commands/template/save.js +104 -0
  40. package/dist/commands/{phase/template → template}/update.d.ts +2 -2
  41. package/dist/commands/template/update.js +99 -0
  42. package/dist/commands/{agent/themes → theme}/add-names.d.ts +1 -1
  43. package/dist/commands/{agent/themes → theme}/add-names.js +6 -6
  44. package/dist/commands/{agent/themes → theme}/create.d.ts +1 -1
  45. package/dist/commands/{agent/themes → theme}/create.js +5 -5
  46. package/dist/commands/{agent/themes → theme}/index.d.ts +1 -1
  47. package/dist/commands/{agent/themes → theme}/index.js +10 -10
  48. package/dist/commands/{agent/themes → theme}/list.d.ts +1 -1
  49. package/dist/commands/{agent/themes → theme}/list.js +5 -5
  50. package/dist/commands/{agent/themes → theme}/set.d.ts +1 -1
  51. package/dist/commands/{agent/themes → theme}/set.js +7 -7
  52. package/dist/commands/ticket/create.d.ts +1 -0
  53. package/dist/commands/ticket/create.js +54 -2
  54. package/dist/commands/ticket/index.js +6 -6
  55. package/dist/commands/work/spawn.js +1 -1
  56. package/dist/lib/mcp/helpers.d.ts +43 -0
  57. package/dist/lib/mcp/helpers.js +57 -0
  58. package/dist/lib/mcp/index.d.ts +6 -0
  59. package/dist/lib/mcp/index.js +6 -0
  60. package/dist/lib/mcp/tools/action.d.ts +6 -0
  61. package/dist/lib/mcp/tools/action.js +88 -0
  62. package/dist/lib/mcp/tools/board.d.ts +6 -0
  63. package/dist/lib/mcp/tools/board.js +139 -0
  64. package/dist/lib/mcp/tools/category.d.ts +6 -0
  65. package/dist/lib/mcp/tools/category.js +84 -0
  66. package/dist/lib/mcp/tools/cli-passthrough.d.ts +15 -0
  67. package/dist/lib/mcp/tools/cli-passthrough.js +333 -0
  68. package/dist/lib/mcp/tools/epic.d.ts +6 -0
  69. package/dist/lib/mcp/tools/epic.js +178 -0
  70. package/dist/lib/mcp/tools/index.d.ts +18 -0
  71. package/dist/lib/mcp/tools/index.js +19 -0
  72. package/dist/lib/mcp/tools/phase.d.ts +6 -0
  73. package/dist/lib/mcp/tools/phase.js +131 -0
  74. package/dist/lib/mcp/tools/project.d.ts +6 -0
  75. package/dist/lib/mcp/tools/project.js +196 -0
  76. package/dist/lib/mcp/tools/roadmap.d.ts +6 -0
  77. package/dist/lib/mcp/tools/roadmap.js +123 -0
  78. package/dist/lib/mcp/tools/spec.d.ts +6 -0
  79. package/dist/lib/mcp/tools/spec.js +196 -0
  80. package/dist/lib/mcp/tools/status.d.ts +6 -0
  81. package/dist/lib/mcp/tools/status.js +109 -0
  82. package/dist/lib/mcp/tools/template.d.ts +6 -0
  83. package/dist/lib/mcp/tools/template.js +107 -0
  84. package/dist/lib/mcp/tools/ticket.d.ts +6 -0
  85. package/dist/lib/mcp/tools/ticket.js +393 -0
  86. package/dist/lib/mcp/tools/view.d.ts +6 -0
  87. package/dist/lib/mcp/tools/view.js +76 -0
  88. package/dist/lib/mcp/tools/work.d.ts +6 -0
  89. package/dist/lib/mcp/tools/work.js +132 -0
  90. package/dist/lib/mcp/tools/workflow.d.ts +6 -0
  91. package/dist/lib/mcp/tools/workflow.js +95 -0
  92. package/dist/lib/mcp/types.d.ts +17 -0
  93. package/dist/lib/mcp/types.js +4 -0
  94. package/dist/lib/prompt-json.d.ts +52 -1
  95. package/dist/lib/prompt-json.js +45 -0
  96. package/oclif.manifest.json +3553 -5457
  97. package/package.json +10 -7
  98. package/dist/commands/agent/temp/index.d.ts +0 -14
  99. package/dist/commands/agent/temp/index.js +0 -85
  100. package/dist/commands/agent/temp/list.d.ts +0 -7
  101. package/dist/commands/agent/temp/list.js +0 -108
  102. package/dist/commands/epic/link/block.d.ts +0 -14
  103. package/dist/commands/epic/link/block.js +0 -81
  104. package/dist/commands/epic/link/duplicates.js +0 -68
  105. package/dist/commands/epic/link/index.d.ts +0 -19
  106. package/dist/commands/epic/link/index.js +0 -272
  107. package/dist/commands/epic/link/relates.js +0 -68
  108. package/dist/commands/epic/link/remove.js +0 -93
  109. package/dist/commands/phase/template/apply.d.ts +0 -17
  110. package/dist/commands/phase/template/apply.js +0 -108
  111. package/dist/commands/phase/template/create.d.ts +0 -17
  112. package/dist/commands/phase/template/create.js +0 -104
  113. package/dist/commands/phase/template/delete.d.ts +0 -17
  114. package/dist/commands/phase/template/delete.js +0 -100
  115. package/dist/commands/phase/template/index.d.ts +0 -15
  116. package/dist/commands/phase/template/index.js +0 -130
  117. package/dist/commands/phase/template/list.d.ts +0 -16
  118. package/dist/commands/phase/template/list.js +0 -97
  119. package/dist/commands/phase/template/update.js +0 -89
  120. package/dist/commands/spec/link/depends.d.ts +0 -14
  121. package/dist/commands/spec/link/depends.js +0 -64
  122. package/dist/commands/spec/link/duplicates.d.ts +0 -14
  123. package/dist/commands/spec/link/duplicates.js +0 -63
  124. package/dist/commands/spec/link/index.d.ts +0 -19
  125. package/dist/commands/spec/link/index.js +0 -207
  126. package/dist/commands/spec/link/relates.d.ts +0 -14
  127. package/dist/commands/spec/link/relates.js +0 -63
  128. package/dist/commands/spec/link/remove.js +0 -96
  129. package/dist/commands/template/phase/apply.d.ts +0 -14
  130. package/dist/commands/template/phase/apply.js +0 -43
  131. package/dist/commands/template/phase/create.d.ts +0 -13
  132. package/dist/commands/template/phase/create.js +0 -38
  133. package/dist/commands/template/phase/delete.d.ts +0 -13
  134. package/dist/commands/template/phase/delete.js +0 -36
  135. package/dist/commands/template/phase/index.d.ts +0 -10
  136. package/dist/commands/template/phase/index.js +0 -63
  137. package/dist/commands/template/phase/list.d.ts +0 -11
  138. package/dist/commands/template/phase/list.js +0 -36
  139. package/dist/commands/template/phase/update.d.ts +0 -14
  140. package/dist/commands/template/phase/update.js +0 -43
  141. package/dist/commands/template/ticket/apply.d.ts +0 -17
  142. package/dist/commands/template/ticket/apply.js +0 -60
  143. package/dist/commands/template/ticket/create.d.ts +0 -20
  144. package/dist/commands/template/ticket/create.js +0 -89
  145. package/dist/commands/template/ticket/delete.d.ts +0 -13
  146. package/dist/commands/template/ticket/delete.js +0 -38
  147. package/dist/commands/template/ticket/index.d.ts +0 -10
  148. package/dist/commands/template/ticket/index.js +0 -63
  149. package/dist/commands/template/ticket/list.d.ts +0 -11
  150. package/dist/commands/template/ticket/list.js +0 -36
  151. package/dist/commands/template/ticket/save.d.ts +0 -15
  152. package/dist/commands/template/ticket/save.js +0 -46
  153. package/dist/commands/ticket/link/block.d.ts +0 -14
  154. package/dist/commands/ticket/link/block.js +0 -96
  155. package/dist/commands/ticket/link/duplicates.d.ts +0 -14
  156. package/dist/commands/ticket/link/duplicates.js +0 -95
  157. package/dist/commands/ticket/link/index.d.ts +0 -19
  158. package/dist/commands/ticket/link/index.js +0 -256
  159. package/dist/commands/ticket/link/relates.d.ts +0 -14
  160. package/dist/commands/ticket/link/relates.js +0 -95
  161. package/dist/commands/ticket/link/remove.d.ts +0 -16
  162. package/dist/commands/ticket/link/remove.js +0 -132
  163. package/dist/commands/ticket/template/apply.js +0 -252
  164. package/dist/commands/ticket/template/create.js +0 -386
  165. package/dist/commands/ticket/template/delete.d.ts +0 -17
  166. package/dist/commands/ticket/template/delete.js +0 -94
  167. package/dist/commands/ticket/template/index.d.ts +0 -15
  168. package/dist/commands/ticket/template/index.js +0 -120
  169. package/dist/commands/ticket/template/list.d.ts +0 -16
  170. package/dist/commands/ticket/template/list.js +0 -112
  171. package/dist/commands/ticket/template/save.js +0 -163
  172. /package/dist/commands/{agent/staff → staff}/add.d.ts +0 -0
  173. /package/dist/commands/{agent/staff → staff}/list.d.ts +0 -0
@@ -0,0 +1,131 @@
1
+ /**
2
+ * MCP Phase Tools
3
+ */
4
+ import { z } from 'zod';
5
+ import { errorResponse } from '../helpers.js';
6
+ export function registerPhaseTools(server, ctx) {
7
+ server.tool('phase_list', 'List project phases', { category: z.enum(['triage', 'backlog', 'unstarted', 'started', 'completed', 'canceled']).optional() }, async (params) => {
8
+ try {
9
+ const phases = await ctx.storage.listPhases({ category: params.category });
10
+ return {
11
+ content: [{
12
+ type: 'text',
13
+ text: JSON.stringify({
14
+ success: true,
15
+ phases: phases.map((p) => ({
16
+ id: p.id,
17
+ name: p.name,
18
+ category: p.category,
19
+ position: p.position,
20
+ isDefault: p.isDefault,
21
+ })),
22
+ }, null, 2),
23
+ }],
24
+ };
25
+ }
26
+ catch (error) {
27
+ return errorResponse(error);
28
+ }
29
+ });
30
+ server.tool('phase_create', 'Create a project phase', {
31
+ name: z.string().describe('Phase name'),
32
+ category: z.enum(['triage', 'backlog', 'unstarted', 'started', 'completed', 'canceled']),
33
+ position: z.number().optional(),
34
+ is_default: z.boolean().optional(),
35
+ }, async (params) => {
36
+ try {
37
+ const phase = await ctx.storage.createPhase({
38
+ name: params.name,
39
+ category: params.category,
40
+ position: params.position,
41
+ isDefault: params.is_default,
42
+ });
43
+ return {
44
+ content: [{
45
+ type: 'text',
46
+ text: JSON.stringify({ success: true, phase: { id: phase.id, name: phase.name } }, null, 2),
47
+ }],
48
+ };
49
+ }
50
+ catch (error) {
51
+ return errorResponse(error);
52
+ }
53
+ });
54
+ server.tool('phase_update', 'Update a phase', {
55
+ id: z.string().describe('Phase ID'),
56
+ name: z.string().optional(),
57
+ category: z.enum(['triage', 'backlog', 'unstarted', 'started', 'completed', 'canceled']).optional(),
58
+ }, async (params) => {
59
+ try {
60
+ const changes = {};
61
+ if (params.name)
62
+ changes.name = params.name;
63
+ if (params.category)
64
+ changes.category = params.category;
65
+ const phase = await ctx.storage.updatePhase(params.id, changes);
66
+ return {
67
+ content: [{
68
+ type: 'text',
69
+ text: JSON.stringify({ success: true, phase: { id: phase.id, name: phase.name } }, null, 2),
70
+ }],
71
+ };
72
+ }
73
+ catch (error) {
74
+ return errorResponse(error);
75
+ }
76
+ });
77
+ server.tool('phase_delete', 'Delete a phase', { id: z.string().describe('Phase ID') }, async (params) => {
78
+ try {
79
+ await ctx.storage.deletePhase(params.id);
80
+ return {
81
+ content: [{
82
+ type: 'text',
83
+ text: JSON.stringify({ success: true, message: 'Phase deleted' }, null, 2),
84
+ }],
85
+ };
86
+ }
87
+ catch (error) {
88
+ return errorResponse(error);
89
+ }
90
+ });
91
+ server.tool('phase_template_list', 'List phase templates', {}, async () => {
92
+ try {
93
+ const templates = await ctx.storage.listPhaseTemplates();
94
+ return {
95
+ content: [{
96
+ type: 'text',
97
+ text: JSON.stringify({
98
+ success: true,
99
+ templates: templates.map((t) => ({
100
+ id: t.id,
101
+ name: t.name,
102
+ description: t.description,
103
+ isBuiltin: t.isBuiltin,
104
+ })),
105
+ }, null, 2),
106
+ }],
107
+ };
108
+ }
109
+ catch (error) {
110
+ return errorResponse(error);
111
+ }
112
+ });
113
+ server.tool('phase_template_apply', 'Apply a phase template', { template_id: z.string().describe('Template ID') }, async (params) => {
114
+ try {
115
+ const phases = await ctx.storage.applyPhaseTemplate(params.template_id);
116
+ return {
117
+ content: [{
118
+ type: 'text',
119
+ text: JSON.stringify({
120
+ success: true,
121
+ message: `Applied template, created ${phases.length} phases`,
122
+ phases: phases.map((p) => ({ id: p.id, name: p.name })),
123
+ }, null, 2),
124
+ }],
125
+ };
126
+ }
127
+ catch (error) {
128
+ return errorResponse(error);
129
+ }
130
+ });
131
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * MCP Project Tools
3
+ */
4
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type { McpToolContext } from '../types.js';
6
+ export declare function registerProjectTools(server: McpServer, ctx: McpToolContext): void;
@@ -0,0 +1,196 @@
1
+ /**
2
+ * MCP Project Tools
3
+ */
4
+ import { z } from 'zod';
5
+ import { errorResponse } from '../helpers.js';
6
+ export function registerProjectTools(server, ctx) {
7
+ server.tool('project_list', 'List all projects', {
8
+ include_archived: z.boolean().optional().describe('Include archived'),
9
+ search: z.string().optional().describe('Search in name'),
10
+ }, async (params) => {
11
+ try {
12
+ const projects = await ctx.storage.listProjects({
13
+ isArchived: params.include_archived ? undefined : false,
14
+ search: params.search,
15
+ });
16
+ return {
17
+ content: [{
18
+ type: 'text',
19
+ text: JSON.stringify({
20
+ success: true,
21
+ count: projects.length,
22
+ projects: projects.map((p) => ({
23
+ id: p.id,
24
+ name: p.name,
25
+ description: p.description,
26
+ template: p.template,
27
+ status: p.status,
28
+ isArchived: p.isArchived,
29
+ workflowId: p.workflowId,
30
+ createdAt: p.createdAt.toISOString(),
31
+ updatedAt: p.updatedAt.toISOString(),
32
+ })),
33
+ }, null, 2),
34
+ }],
35
+ };
36
+ }
37
+ catch (error) {
38
+ return errorResponse(error);
39
+ }
40
+ });
41
+ server.tool('project_create', 'Create a new project', {
42
+ name: z.string().describe('Project name'),
43
+ description: z.string().optional().describe('Description'),
44
+ template: z.string().optional().describe('Template (kanban, scrum, linear, simple)'),
45
+ }, async (params) => {
46
+ try {
47
+ const board = await ctx.storage.createProject({
48
+ name: params.name,
49
+ description: params.description,
50
+ template: params.template,
51
+ });
52
+ return {
53
+ content: [{
54
+ type: 'text',
55
+ text: JSON.stringify({
56
+ success: true,
57
+ project: { id: board.id, name: board.name, columns: board.columns.map((c) => c.name) },
58
+ }, null, 2),
59
+ }],
60
+ };
61
+ }
62
+ catch (error) {
63
+ return errorResponse(error);
64
+ }
65
+ });
66
+ server.tool('project_show', 'Get project details', { id: z.string().describe('Project ID') }, async (params) => {
67
+ try {
68
+ const project = await ctx.storage.getProject(params.id);
69
+ if (!project)
70
+ throw new Error(`Project not found: ${params.id}`);
71
+ const tickets = await ctx.storage.listTickets(params.id);
72
+ return {
73
+ content: [{
74
+ type: 'text',
75
+ text: JSON.stringify({
76
+ success: true,
77
+ project: {
78
+ id: project.id,
79
+ name: project.name,
80
+ description: project.description,
81
+ template: project.template,
82
+ status: project.status,
83
+ isArchived: project.isArchived,
84
+ workflowId: project.workflowId,
85
+ ticketCount: tickets.length,
86
+ createdAt: project.createdAt.toISOString(),
87
+ updatedAt: project.updatedAt.toISOString(),
88
+ },
89
+ }, null, 2),
90
+ }],
91
+ };
92
+ }
93
+ catch (error) {
94
+ return errorResponse(error);
95
+ }
96
+ });
97
+ server.tool('project_update', 'Update a project', {
98
+ id: z.string().describe('Project ID'),
99
+ name: z.string().optional().describe('New name'),
100
+ description: z.string().optional().describe('New description'),
101
+ }, async (params) => {
102
+ try {
103
+ const changes = {};
104
+ if (params.name)
105
+ changes.name = params.name;
106
+ if (params.description !== undefined)
107
+ changes.description = params.description;
108
+ const project = await ctx.storage.updateProject(params.id, changes);
109
+ return {
110
+ content: [{
111
+ type: 'text',
112
+ text: JSON.stringify({ success: true, project: { id: project.id, name: project.name } }, null, 2),
113
+ }],
114
+ };
115
+ }
116
+ catch (error) {
117
+ return errorResponse(error);
118
+ }
119
+ });
120
+ server.tool('project_archive', 'Archive a project', { id: z.string().describe('Project ID') }, async (params) => {
121
+ try {
122
+ const project = await ctx.storage.archiveProject(params.id);
123
+ return {
124
+ content: [{
125
+ type: 'text',
126
+ text: JSON.stringify({ success: true, project: { id: project.id, isArchived: project.isArchived } }, null, 2),
127
+ }],
128
+ };
129
+ }
130
+ catch (error) {
131
+ return errorResponse(error);
132
+ }
133
+ });
134
+ server.tool('project_unarchive', 'Unarchive a project', { id: z.string().describe('Project ID') }, async (params) => {
135
+ try {
136
+ const project = await ctx.storage.unarchiveProject(params.id);
137
+ return {
138
+ content: [{
139
+ type: 'text',
140
+ text: JSON.stringify({ success: true, project: { id: project.id, isArchived: project.isArchived } }, null, 2),
141
+ }],
142
+ };
143
+ }
144
+ catch (error) {
145
+ return errorResponse(error);
146
+ }
147
+ });
148
+ server.tool('project_delete', 'Delete a project', { id: z.string().describe('Project ID') }, async (params) => {
149
+ try {
150
+ await ctx.storage.deleteProject(params.id);
151
+ return {
152
+ content: [{
153
+ type: 'text',
154
+ text: JSON.stringify({ success: true, message: `Deleted project ${params.id}` }, null, 2),
155
+ }],
156
+ };
157
+ }
158
+ catch (error) {
159
+ return errorResponse(error);
160
+ }
161
+ });
162
+ server.tool('project_link_to_spec', 'Link project to a spec', {
163
+ project_id: z.string().describe('Project ID'),
164
+ spec_id: z.string().describe('Spec ID'),
165
+ }, async (params) => {
166
+ try {
167
+ await ctx.storage.linkProjectToSpec(params.project_id, params.spec_id);
168
+ return {
169
+ content: [{
170
+ type: 'text',
171
+ text: JSON.stringify({ success: true, message: 'Project linked to spec' }, null, 2),
172
+ }],
173
+ };
174
+ }
175
+ catch (error) {
176
+ return errorResponse(error);
177
+ }
178
+ });
179
+ server.tool('project_get_specs', 'Get specs linked to a project', { project_id: z.string().describe('Project ID') }, async (params) => {
180
+ try {
181
+ const specs = await ctx.storage.getSpecsForProject(params.project_id);
182
+ return {
183
+ content: [{
184
+ type: 'text',
185
+ text: JSON.stringify({
186
+ success: true,
187
+ specs: specs.map((s) => ({ id: s.id, title: s.title, status: s.status })),
188
+ }, null, 2),
189
+ }],
190
+ };
191
+ }
192
+ catch (error) {
193
+ return errorResponse(error);
194
+ }
195
+ });
196
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * MCP Roadmap Tools
3
+ */
4
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type { McpToolContext } from '../types.js';
6
+ export declare function registerRoadmapTools(server: McpServer, ctx: McpToolContext): void;
@@ -0,0 +1,123 @@
1
+ /**
2
+ * MCP Roadmap Tools
3
+ */
4
+ import { z } from 'zod';
5
+ import { errorResponse } from '../helpers.js';
6
+ export function registerRoadmapTools(server, ctx) {
7
+ server.tool('roadmap_list', 'List roadmaps', {}, async () => {
8
+ try {
9
+ const roadmaps = await ctx.storage.listRoadmaps();
10
+ return {
11
+ content: [{
12
+ type: 'text',
13
+ text: JSON.stringify({
14
+ success: true,
15
+ roadmaps: roadmaps.map((r) => ({
16
+ id: r.id,
17
+ name: r.name,
18
+ description: r.description,
19
+ isDefault: r.isDefault,
20
+ })),
21
+ }, null, 2),
22
+ }],
23
+ };
24
+ }
25
+ catch (error) {
26
+ return errorResponse(error);
27
+ }
28
+ });
29
+ server.tool('roadmap_create', 'Create a roadmap', {
30
+ name: z.string().describe('Roadmap name'),
31
+ description: z.string().optional(),
32
+ is_default: z.boolean().optional(),
33
+ }, async (params) => {
34
+ try {
35
+ const roadmap = await ctx.storage.createRoadmap({
36
+ name: params.name,
37
+ description: params.description,
38
+ isDefault: params.is_default ?? false,
39
+ });
40
+ return {
41
+ content: [{
42
+ type: 'text',
43
+ text: JSON.stringify({ success: true, roadmap: { id: roadmap.id, name: roadmap.name } }, null, 2),
44
+ }],
45
+ };
46
+ }
47
+ catch (error) {
48
+ return errorResponse(error);
49
+ }
50
+ });
51
+ server.tool('roadmap_show', 'Get roadmap with projects', { id: z.string().describe('Roadmap ID') }, async (params) => {
52
+ try {
53
+ const roadmap = await ctx.storage.getRoadmap(params.id);
54
+ if (!roadmap)
55
+ throw new Error(`Roadmap not found: ${params.id}`);
56
+ const projects = await ctx.storage.listRoadmapProjects(params.id);
57
+ return {
58
+ content: [{
59
+ type: 'text',
60
+ text: JSON.stringify({
61
+ success: true,
62
+ roadmap: {
63
+ ...roadmap,
64
+ projects: projects.map((p) => ({ id: p.id, name: p.name })),
65
+ },
66
+ }, null, 2),
67
+ }],
68
+ };
69
+ }
70
+ catch (error) {
71
+ return errorResponse(error);
72
+ }
73
+ });
74
+ server.tool('roadmap_add_project', 'Add project to roadmap', {
75
+ roadmap_id: z.string().describe('Roadmap ID'),
76
+ project_id: z.string().describe('Project ID'),
77
+ position: z.number().optional(),
78
+ }, async (params) => {
79
+ try {
80
+ await ctx.storage.addProjectToRoadmap(params.roadmap_id, params.project_id, params.position);
81
+ return {
82
+ content: [{
83
+ type: 'text',
84
+ text: JSON.stringify({ success: true, message: 'Project added to roadmap' }, null, 2),
85
+ }],
86
+ };
87
+ }
88
+ catch (error) {
89
+ return errorResponse(error);
90
+ }
91
+ });
92
+ server.tool('roadmap_remove_project', 'Remove project from roadmap', {
93
+ roadmap_id: z.string().describe('Roadmap ID'),
94
+ project_id: z.string().describe('Project ID'),
95
+ }, async (params) => {
96
+ try {
97
+ await ctx.storage.removeProjectFromRoadmap(params.roadmap_id, params.project_id);
98
+ return {
99
+ content: [{
100
+ type: 'text',
101
+ text: JSON.stringify({ success: true, message: 'Project removed from roadmap' }, null, 2),
102
+ }],
103
+ };
104
+ }
105
+ catch (error) {
106
+ return errorResponse(error);
107
+ }
108
+ });
109
+ server.tool('roadmap_delete', 'Delete a roadmap', { id: z.string().describe('Roadmap ID') }, async (params) => {
110
+ try {
111
+ await ctx.storage.deleteRoadmap(params.id);
112
+ return {
113
+ content: [{
114
+ type: 'text',
115
+ text: JSON.stringify({ success: true, message: 'Roadmap deleted' }, null, 2),
116
+ }],
117
+ };
118
+ }
119
+ catch (error) {
120
+ return errorResponse(error);
121
+ }
122
+ });
123
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * MCP Spec Tools
3
+ */
4
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type { McpToolContext } from '../types.js';
6
+ export declare function registerSpecTools(server: McpServer, ctx: McpToolContext): void;
@@ -0,0 +1,196 @@
1
+ /**
2
+ * MCP Spec Tools
3
+ */
4
+ import { z } from 'zod';
5
+ import { errorResponse } from '../helpers.js';
6
+ export function registerSpecTools(server, ctx) {
7
+ server.tool('spec_list', 'List specifications', {
8
+ status: z.enum(['draft', 'active', 'implemented']).optional(),
9
+ type: z.enum(['product', 'platform', 'infra', 'integration']).optional(),
10
+ search: z.string().optional(),
11
+ }, async (params) => {
12
+ try {
13
+ const specs = await ctx.storage.listSpecs({
14
+ status: params.status,
15
+ type: params.type,
16
+ search: params.search,
17
+ });
18
+ return {
19
+ content: [{
20
+ type: 'text',
21
+ text: JSON.stringify({
22
+ success: true,
23
+ count: specs.length,
24
+ specs: specs.map((s) => ({
25
+ id: s.id,
26
+ title: s.title,
27
+ status: s.status,
28
+ type: s.type,
29
+ tags: s.tags,
30
+ createdAt: s.createdAt.toISOString(),
31
+ })),
32
+ }, null, 2),
33
+ }],
34
+ };
35
+ }
36
+ catch (error) {
37
+ return errorResponse(error);
38
+ }
39
+ });
40
+ server.tool('spec_create', 'Create a specification', {
41
+ title: z.string().describe('Spec title'),
42
+ status: z.enum(['draft', 'active', 'implemented']).optional(),
43
+ type: z.enum(['product', 'platform', 'infra', 'integration']).optional(),
44
+ problem: z.string().optional(),
45
+ solution: z.string().optional(),
46
+ acceptance_criteria: z.string().optional(),
47
+ context: z.string().optional(),
48
+ }, async (params) => {
49
+ try {
50
+ const spec = await ctx.storage.createSpec({
51
+ title: params.title,
52
+ status: params.status || 'draft',
53
+ type: params.type,
54
+ problem: params.problem,
55
+ solution: params.solution,
56
+ acceptanceCriteria: params.acceptance_criteria,
57
+ context: params.context,
58
+ });
59
+ return {
60
+ content: [{
61
+ type: 'text',
62
+ text: JSON.stringify({ success: true, spec: { id: spec.id, title: spec.title, status: spec.status } }, null, 2),
63
+ }],
64
+ };
65
+ }
66
+ catch (error) {
67
+ return errorResponse(error);
68
+ }
69
+ });
70
+ server.tool('spec_show', 'Get spec details', { id: z.string().describe('Spec ID') }, async (params) => {
71
+ try {
72
+ const spec = await ctx.storage.getSpec(params.id);
73
+ if (!spec)
74
+ throw new Error(`Spec not found: ${params.id}`);
75
+ return {
76
+ content: [{
77
+ type: 'text',
78
+ text: JSON.stringify({ success: true, spec }, null, 2),
79
+ }],
80
+ };
81
+ }
82
+ catch (error) {
83
+ return errorResponse(error);
84
+ }
85
+ });
86
+ server.tool('spec_update', 'Update a spec', {
87
+ id: z.string().describe('Spec ID'),
88
+ title: z.string().optional(),
89
+ status: z.enum(['draft', 'active', 'implemented']).optional(),
90
+ type: z.enum(['product', 'platform', 'infra', 'integration']).optional(),
91
+ problem: z.string().optional(),
92
+ solution: z.string().optional(),
93
+ acceptance_criteria: z.string().optional(),
94
+ }, async (params) => {
95
+ try {
96
+ const changes = {};
97
+ if (params.title)
98
+ changes.title = params.title;
99
+ if (params.status)
100
+ changes.status = params.status;
101
+ if (params.type)
102
+ changes.type = params.type;
103
+ if (params.problem !== undefined)
104
+ changes.problem = params.problem;
105
+ if (params.solution !== undefined)
106
+ changes.solution = params.solution;
107
+ if (params.acceptance_criteria !== undefined)
108
+ changes.acceptanceCriteria = params.acceptance_criteria;
109
+ const spec = await ctx.storage.updateSpec(params.id, changes);
110
+ return {
111
+ content: [{
112
+ type: 'text',
113
+ text: JSON.stringify({ success: true, spec: { id: spec.id, title: spec.title } }, null, 2),
114
+ }],
115
+ };
116
+ }
117
+ catch (error) {
118
+ return errorResponse(error);
119
+ }
120
+ });
121
+ server.tool('spec_delete', 'Delete a spec', { id: z.string().describe('Spec ID') }, async (params) => {
122
+ try {
123
+ await ctx.storage.deleteSpec(params.id);
124
+ return {
125
+ content: [{
126
+ type: 'text',
127
+ text: JSON.stringify({ success: true, message: `Deleted spec ${params.id}` }, null, 2),
128
+ }],
129
+ };
130
+ }
131
+ catch (error) {
132
+ return errorResponse(error);
133
+ }
134
+ });
135
+ server.tool('spec_add_dependency', 'Add spec dependency', {
136
+ spec_id: z.string().describe('Spec ID'),
137
+ depends_on_id: z.string().describe('ID of spec this depends on'),
138
+ }, async (params) => {
139
+ try {
140
+ await ctx.storage.addSpecDependency(params.spec_id, params.depends_on_id);
141
+ return {
142
+ content: [{
143
+ type: 'text',
144
+ text: JSON.stringify({ success: true, message: 'Dependency added' }, null, 2),
145
+ }],
146
+ };
147
+ }
148
+ catch (error) {
149
+ return errorResponse(error);
150
+ }
151
+ });
152
+ server.tool('spec_get_dependencies', 'Get spec dependencies', { spec_id: z.string().describe('Spec ID') }, async (params) => {
153
+ try {
154
+ const deps = await ctx.storage.getSpecDependencies(params.spec_id);
155
+ return {
156
+ content: [{
157
+ type: 'text',
158
+ text: JSON.stringify({
159
+ success: true,
160
+ dependencies: deps.map((s) => ({ id: s.id, title: s.title })),
161
+ }, null, 2),
162
+ }],
163
+ };
164
+ }
165
+ catch (error) {
166
+ return errorResponse(error);
167
+ }
168
+ });
169
+ server.tool('spec_get_tickets', 'Get tickets linked to a spec', {
170
+ spec_id: z.string().describe('Spec ID'),
171
+ project: z.string().optional().describe('Project ID'),
172
+ }, async (params) => {
173
+ try {
174
+ let projectId = params.project;
175
+ if (!projectId) {
176
+ const projects = await ctx.storage.listProjects();
177
+ if (projects.length === 0)
178
+ throw new Error('No projects');
179
+ projectId = projects[0].id;
180
+ }
181
+ const tickets = await ctx.storage.getTicketsForSpec(projectId, params.spec_id);
182
+ return {
183
+ content: [{
184
+ type: 'text',
185
+ text: JSON.stringify({
186
+ success: true,
187
+ tickets: tickets.map((t) => ({ id: t.id, title: t.title, statusName: t.statusName })),
188
+ }, null, 2),
189
+ }],
190
+ };
191
+ }
192
+ catch (error) {
193
+ return errorResponse(error);
194
+ }
195
+ });
196
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * MCP Status Tools
3
+ */
4
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type { McpToolContext } from '../types.js';
6
+ export declare function registerStatusTools(server: McpServer, ctx: McpToolContext): void;