@damper/mcp 0.1.7 → 0.1.9

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 (3) hide show
  1. package/README.md +14 -0
  2. package/dist/index.js +80 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -74,6 +74,7 @@ The AI will see tools from both servers and can distinguish between them:
74
74
  | `list_tasks` | Get roadmap tasks (filter by `status`, `type`) |
75
75
  | `get_task` | Task details + subtasks + linked feedback |
76
76
  | `create_task` | Create task with type (bug, feature, improvement, task) |
77
+ | `update_task` | Update description, plan, priority, effort, quarter, labels |
77
78
  | `start_task` | Lock and start task (use `force` to take over) |
78
79
  | `add_note` | Add progress note |
79
80
  | `create_subtask` | Add subtask to a task |
@@ -101,9 +102,22 @@ Tasks include project management fields visible in `list_tasks` and `get_task`:
101
102
 
102
103
  - **Priority**: high 🔴, medium 🟡, low ⚪
103
104
  - **Effort**: xs, s, m, l, xl
105
+ - **Quarter**: Target quarter (Q1 2025, Q2 2025, etc.)
104
106
  - **Labels**: Custom tags
105
107
  - **Due date**: Target completion date
106
108
 
109
+ ### Updating Tasks
110
+
111
+ Refine task details as you work:
112
+
113
+ ```
114
+ > Set priority to high for this task
115
+ > Update the implementation plan with what I've learned
116
+ > Add labels: backend, api, auth
117
+ > Set effort to medium
118
+ > Schedule this for Q2 2025
119
+ ```
120
+
107
121
  ### Subtasks
108
122
 
109
123
  Tasks can have subtasks for tracking incremental progress. Use `get_task` to see subtasks with their IDs:
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ async function api(method, path, body) {
34
34
  // Server
35
35
  const server = new McpServer({
36
36
  name: 'damper',
37
- version: '0.1.7',
37
+ version: '0.1.9',
38
38
  });
39
39
  // Output schemas
40
40
  const SubtaskProgressSchema = z.object({
@@ -48,6 +48,7 @@ const TaskSummarySchema = z.object({
48
48
  status: z.string(),
49
49
  priority: z.string(),
50
50
  effort: z.string().nullable().optional(),
51
+ quarter: z.string().nullable().optional(),
51
52
  labels: z.array(z.string()).optional(),
52
53
  dueDate: z.string().nullable().optional(),
53
54
  feedbackCount: z.number(),
@@ -68,6 +69,7 @@ const TaskDetailSchema = z.object({
68
69
  status: z.string(),
69
70
  priority: z.string().nullable().optional(),
70
71
  effort: z.string().nullable().optional(),
72
+ quarter: z.string().nullable().optional(),
71
73
  labels: z.array(z.string()).optional(),
72
74
  dueDate: z.string().nullable().optional(),
73
75
  voteScore: z.number(),
@@ -138,7 +140,8 @@ server.registerTool('list_tasks', {
138
140
  const p = t.priority === 'high' ? '🔴' : t.priority === 'medium' ? '🟡' : '⚪';
139
141
  const typeIcon = t.type === 'bug' ? '🐛' : t.type === 'feature' ? '✨' : t.type === 'improvement' ? '💡' : '📌';
140
142
  const subtaskInfo = t.subtaskProgress ? ` [${t.subtaskProgress.done}/${t.subtaskProgress.total}]` : '';
141
- return `• ${t.id}: ${typeIcon} ${t.title} [${t.status}] ${p}${t.hasImplementationPlan ? ' 📋' : ''}${subtaskInfo}`;
143
+ const quarterInfo = t.quarter ? ` 📅${t.quarter}` : '';
144
+ return `• ${t.id}: ${typeIcon} ${t.title} [${t.status}] ${p}${quarterInfo}${t.hasImplementationPlan ? ' 📋' : ''}${subtaskInfo}`;
142
145
  });
143
146
  return {
144
147
  content: [{ type: 'text', text: `Tasks in "${data.project.name}":\n${lines.join('\n')}` }],
@@ -166,12 +169,14 @@ server.registerTool('get_task', {
166
169
  `# ${typeIcon} ${t.title}`,
167
170
  `Type: ${t.type} | Status: ${t.status} | Score: ${t.voteScore}`,
168
171
  ];
169
- // Add priority/effort/labels if present
172
+ // Add priority/effort/quarter/labels if present
170
173
  const meta = [];
171
174
  if (t.priority)
172
175
  meta.push(`Priority: ${t.priority}`);
173
176
  if (t.effort)
174
177
  meta.push(`Effort: ${t.effort}`);
178
+ if (t.quarter)
179
+ meta.push(`Quarter: ${t.quarter}`);
175
180
  if (t.dueDate)
176
181
  meta.push(`Due: ${t.dueDate}`);
177
182
  if (t.labels && t.labels.length)
@@ -199,6 +204,78 @@ server.registerTool('get_task', {
199
204
  structuredContent: t,
200
205
  };
201
206
  });
207
+ // Tool: Update task
208
+ server.registerTool('update_task', {
209
+ title: 'Update Task',
210
+ description: 'Update task fields like description, implementation plan, priority, effort, quarter, or labels. ' +
211
+ 'Useful for refining task details as you learn more about the work.',
212
+ inputSchema: z.object({
213
+ taskId: z.string().describe('Task ID'),
214
+ description: z.string().optional().describe('Task description'),
215
+ implementationPlan: z.string().optional().describe('Implementation plan (markdown)'),
216
+ priority: z.enum(['high', 'medium', 'low']).nullable().optional().describe('Task priority'),
217
+ effort: z.enum(['xs', 's', 'm', 'l', 'xl']).nullable().optional().describe('Estimated effort'),
218
+ quarter: z.string().nullable().optional().describe('Target quarter (e.g., "Q1 2025", "Q2 2025")'),
219
+ labels: z.array(z.string()).optional().describe('Labels/tags'),
220
+ }),
221
+ outputSchema: z.object({
222
+ id: z.string(),
223
+ title: z.string(),
224
+ description: z.string().nullable().optional(),
225
+ implementationPlan: z.string().nullable().optional(),
226
+ priority: z.string().nullable().optional(),
227
+ effort: z.string().nullable().optional(),
228
+ quarter: z.string().nullable().optional(),
229
+ labels: z.array(z.string()).optional(),
230
+ }),
231
+ annotations: {
232
+ readOnlyHint: false,
233
+ destructiveHint: false,
234
+ idempotentHint: true,
235
+ openWorldHint: false,
236
+ },
237
+ }, async ({ taskId, description, implementationPlan, priority, effort, quarter, labels }) => {
238
+ const body = {};
239
+ if (description !== undefined)
240
+ body.description = description;
241
+ if (implementationPlan !== undefined)
242
+ body.implementationPlan = implementationPlan;
243
+ if (priority !== undefined)
244
+ body.priority = priority;
245
+ if (effort !== undefined)
246
+ body.effort = effort;
247
+ if (quarter !== undefined)
248
+ body.quarter = quarter;
249
+ if (labels !== undefined)
250
+ body.labels = labels;
251
+ const result = await api('PATCH', `/api/agent/tasks/${taskId}`, body);
252
+ const updates = [];
253
+ if (description !== undefined)
254
+ updates.push('description');
255
+ if (implementationPlan !== undefined)
256
+ updates.push('plan');
257
+ if (priority !== undefined)
258
+ updates.push(`priority=${priority || 'none'}`);
259
+ if (effort !== undefined)
260
+ updates.push(`effort=${effort || 'none'}`);
261
+ if (quarter !== undefined)
262
+ updates.push(`quarter=${quarter || 'none'}`);
263
+ if (labels !== undefined)
264
+ updates.push(`labels=[${labels.join(', ')}]`);
265
+ return {
266
+ content: [{ type: 'text', text: `📝 Updated ${result.title}: ${updates.join(', ')}` }],
267
+ structuredContent: {
268
+ id: result.id,
269
+ title: result.title,
270
+ description: result.description,
271
+ implementationPlan: result.implementationPlan,
272
+ priority: result.priority,
273
+ effort: result.effort,
274
+ quarter: result.quarter,
275
+ labels: result.labels,
276
+ },
277
+ };
278
+ });
202
279
  // Tool: Create task
203
280
  server.registerTool('create_task', {
204
281
  title: 'Create Task',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@damper/mcp",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "MCP server for Damper task management",
5
5
  "author": "Damper <hello@usedamper.com>",
6
6
  "repository": {