@damper/mcp 0.3.7 → 0.3.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.
- package/README.md +41 -15
- package/dist/formatters.js +23 -14
- package/dist/index.js +90 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,14 +74,15 @@ The AI will see tools from both servers and can distinguish between them:
|
|
|
74
74
|
| Tool | Description |
|
|
75
75
|
|------|-------------|
|
|
76
76
|
| `list_tasks` | Get roadmap tasks (filter by `status`, `type`, `quarter`, sort by `importance`/`newest`/`votes`) |
|
|
77
|
-
| `get_task` | Task details + subtasks + linked feedback |
|
|
77
|
+
| `get_task` | Task details + subtasks + commits + linked feedback |
|
|
78
78
|
| `create_task` | Create task with type (bug, feature, improvement, task) |
|
|
79
79
|
| `update_task` | Update description, plan, priority, effort, quarter, labels |
|
|
80
80
|
| `start_task` | Lock and start task (use `force` to take over). Returns project context index. |
|
|
81
81
|
| `add_note` | Add progress note |
|
|
82
|
+
| `add_commit` | Log a commit (hash + message). Appears in task details. |
|
|
82
83
|
| `create_subtask` | Add subtask to a task |
|
|
83
84
|
| `update_subtask` | Mark subtask done/undone |
|
|
84
|
-
| `complete_task` | Mark done, release lock.
|
|
85
|
+
| `complete_task` | Mark done, release lock. Optionally log commits at completion. |
|
|
85
86
|
| `abandon_task` | Release lock, return to planned |
|
|
86
87
|
| `list_feedback` | Browse user feedback |
|
|
87
88
|
| `get_feedback` | Feedback details + votes |
|
|
@@ -259,21 +260,42 @@ When you start a task, it's locked to prevent other agents from working on it si
|
|
|
259
260
|
- Different agent starting → fails with 409 (use `force: true` to take over)
|
|
260
261
|
- Complete or abandon → releases lock
|
|
261
262
|
|
|
263
|
+
### Commit Tracking
|
|
264
|
+
|
|
265
|
+
Log commits as you work to track code changes for each task:
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
> Log commit abc1234 with message "Added validation"
|
|
269
|
+
> Add commit def5678: "Fixed auth bug"
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Commits are stored structurally and displayed in task details:
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
## Commits (2)
|
|
276
|
+
- abc1234: Added validation
|
|
277
|
+
- def5678: Fixed auth bug
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Two ways to log commits:**
|
|
281
|
+
1. `add_commit` - Log commits as you make them
|
|
282
|
+
2. `complete_task` with `commits` - Log final commits at completion
|
|
283
|
+
|
|
262
284
|
### Recommended Workflow
|
|
263
285
|
|
|
264
286
|
When working on tasks, follow this workflow for best results:
|
|
265
287
|
|
|
266
288
|
1. **Start**: `start_task` → locks the task and returns project context
|
|
267
289
|
2. **Log start**: `add_note` with "Session started: <your goal>"
|
|
268
|
-
3. **Work**: Make changes,
|
|
290
|
+
3. **Work**: Make changes, use `add_commit` after each commit, `add_note` for decisions
|
|
269
291
|
4. **Log end**: `add_note` with "Session end: <summary, next steps>"
|
|
270
292
|
5. **Finish**: `complete_task` (done) or `abandon_task` (stopping)
|
|
271
293
|
|
|
272
|
-
**
|
|
273
|
-
- Session start: `"Session started: implementing dark mode"`
|
|
274
|
-
- Commits: `
|
|
275
|
-
- Decisions: `"Decision: Using CSS variables because..."`
|
|
276
|
-
- Session end: `"Session end: Done theme provider, remaining: toggle UI"`
|
|
294
|
+
**What to log:**
|
|
295
|
+
- Session start: `add_note "Session started: implementing dark mode"`
|
|
296
|
+
- Commits: `add_commit abc123 "Added theme provider"`
|
|
297
|
+
- Decisions: `add_note "Decision: Using CSS variables because..."`
|
|
298
|
+
- Session end: `add_note "Session end: Done theme provider, remaining: toggle UI"`
|
|
277
299
|
|
|
278
300
|
**Before completing:**
|
|
279
301
|
- Push all commits
|
|
@@ -319,25 +341,29 @@ Add this to your project's `CLAUDE.md` (or `.cursorrules` for Cursor) to ensure
|
|
|
319
341
|
|
|
320
342
|
This project uses Damper MCP for task tracking. **You MUST follow this workflow.**
|
|
321
343
|
|
|
322
|
-
### At Session Start
|
|
323
|
-
1. `get_project_context` -
|
|
324
|
-
2. `
|
|
325
|
-
3.
|
|
344
|
+
### At Session Start (MANDATORY)
|
|
345
|
+
1. `get_project_context` - **READ THIS FIRST.** Contains architecture, conventions, and critical project info. Do NOT skip.
|
|
346
|
+
2. `get_context_section` - Fetch full content for sections relevant to your task (e.g., "api", "database", "testing")
|
|
347
|
+
3. `list_tasks` - Check for existing tasks to work on
|
|
348
|
+
4. If working on a task: `start_task` to lock it (returns context index - read relevant sections)
|
|
326
349
|
|
|
327
350
|
### While Working
|
|
328
|
-
- `
|
|
351
|
+
- `add_commit` after each commit with hash and message
|
|
329
352
|
- `add_note` for decisions: "Decision: chose X because Y"
|
|
330
353
|
- `update_subtask` to mark subtask progress
|
|
354
|
+
- **Follow patterns from project context** - Don't reinvent; use existing conventions
|
|
331
355
|
|
|
332
356
|
### At Session End (MANDATORY)
|
|
333
357
|
- ALWAYS call `add_note` with session summary before stopping
|
|
334
358
|
- ALWAYS call `complete_task` (if done) or `abandon_task` (if stopping early)
|
|
335
359
|
- NEVER leave a started task without completing or abandoning it
|
|
360
|
+
- If you learned something about the codebase, consider updating project context
|
|
336
361
|
|
|
337
362
|
### Why This Matters
|
|
363
|
+
- **Project context prevents mistakes** - Contains architecture decisions, gotchas, and patterns you need to follow
|
|
338
364
|
- Locked tasks block other agents from working on them
|
|
339
|
-
-
|
|
340
|
-
-
|
|
365
|
+
- Commits and notes help the next agent (or you) continue the work
|
|
366
|
+
- Updating context saves future agents from re-analyzing the codebase
|
|
341
367
|
```
|
|
342
368
|
|
|
343
369
|
## Environment
|
package/dist/formatters.js
CHANGED
|
@@ -8,29 +8,36 @@
|
|
|
8
8
|
* Format start_task response
|
|
9
9
|
*/
|
|
10
10
|
export function formatStartTaskResponse(result) {
|
|
11
|
-
const lines = [
|
|
11
|
+
const lines = [`✅ Started ${result.id}: ${result.message}`];
|
|
12
|
+
// Context section - emphatic about reading it first
|
|
12
13
|
if (result.context) {
|
|
13
14
|
if (result.context.isEmpty) {
|
|
14
15
|
lines.push(`\n📚 ${result.context.hint || 'No project context available.'}`);
|
|
15
16
|
}
|
|
16
17
|
else {
|
|
17
|
-
lines.push('\n**
|
|
18
|
+
lines.push('\n⚠️ **BEFORE YOU START:** Read project context to understand patterns and conventions.');
|
|
19
|
+
lines.push('');
|
|
20
|
+
if (result.context.relevantSections && result.context.relevantSections.length > 0) {
|
|
21
|
+
lines.push(`**Required reading for this task:**`);
|
|
22
|
+
for (const section of result.context.relevantSections) {
|
|
23
|
+
lines.push(`→ \`get_context_section("${section}")\``);
|
|
24
|
+
}
|
|
25
|
+
lines.push('');
|
|
26
|
+
}
|
|
27
|
+
lines.push('**All available sections:**');
|
|
18
28
|
for (const s of result.context.index) {
|
|
19
29
|
const relevant = result.context.relevantSections?.includes(s.section) ? ' ⭐' : '';
|
|
20
30
|
lines.push(`• ${s.section}${relevant}`);
|
|
21
31
|
}
|
|
22
|
-
if (result.context.relevantSections && result.context.relevantSections.length > 0) {
|
|
23
|
-
lines.push(`\nRelevant for this task: ${result.context.relevantSections.join(', ')}`);
|
|
24
|
-
lines.push('Use get_context_section to fetch full content.');
|
|
25
|
-
}
|
|
26
32
|
}
|
|
27
33
|
}
|
|
28
34
|
lines.push('\n---');
|
|
29
|
-
lines.push('**📋
|
|
30
|
-
lines.push('1.
|
|
31
|
-
lines.push('2.
|
|
32
|
-
lines.push('3. `
|
|
33
|
-
lines.push('4. `
|
|
35
|
+
lines.push('**📋 Required workflow:**');
|
|
36
|
+
lines.push('1. **Read context sections above** (contains patterns you must follow)');
|
|
37
|
+
lines.push('2. `add_note`: "Session started: <goal>"');
|
|
38
|
+
lines.push('3. Work: use `add_commit` for commits, `add_note` for decisions');
|
|
39
|
+
lines.push('4. `add_note`: "Session end: <summary>"');
|
|
40
|
+
lines.push('5. `complete_task` or `abandon_task` (NEVER skip this)');
|
|
34
41
|
return lines.join('\n');
|
|
35
42
|
}
|
|
36
43
|
/**
|
|
@@ -38,11 +45,13 @@ export function formatStartTaskResponse(result) {
|
|
|
38
45
|
*/
|
|
39
46
|
export function formatCompleteTaskResponse(result) {
|
|
40
47
|
const lines = [`✅ Completed ${result.id}`];
|
|
48
|
+
lines.push('\n---');
|
|
49
|
+
lines.push('**📚 Before you finish:**');
|
|
50
|
+
lines.push('Did you learn something about this codebase that would help future agents?');
|
|
51
|
+
lines.push('→ Use `update_context_section` to share architecture, patterns, or gotchas.');
|
|
41
52
|
if (result.documentation) {
|
|
42
|
-
lines.push('\n---');
|
|
43
|
-
lines.push('**📚 Documentation:**');
|
|
44
53
|
if (result.documentation.affectedSections?.length > 0) {
|
|
45
|
-
lines.push(
|
|
54
|
+
lines.push(`\nSections that may need updates: ${result.documentation.affectedSections.join(', ')}`);
|
|
46
55
|
}
|
|
47
56
|
if (result.documentation.reminder) {
|
|
48
57
|
lines.push(result.documentation.reminder);
|
package/dist/index.js
CHANGED
|
@@ -61,6 +61,10 @@ const SubtaskSchema = z.object({
|
|
|
61
61
|
title: z.string(),
|
|
62
62
|
done: z.boolean(),
|
|
63
63
|
});
|
|
64
|
+
const CommitSchema = z.object({
|
|
65
|
+
hash: z.string(),
|
|
66
|
+
message: z.string(),
|
|
67
|
+
});
|
|
64
68
|
const TaskDetailSchema = z.object({
|
|
65
69
|
id: z.string(),
|
|
66
70
|
title: z.string(),
|
|
@@ -76,6 +80,7 @@ const TaskDetailSchema = z.object({
|
|
|
76
80
|
voteScore: z.number(),
|
|
77
81
|
subtasks: z.array(SubtaskSchema).optional(),
|
|
78
82
|
agentNotes: z.string().nullable().optional(),
|
|
83
|
+
commits: z.array(CommitSchema).optional(),
|
|
79
84
|
feedback: z.array(z.object({
|
|
80
85
|
id: z.string(),
|
|
81
86
|
title: z.string(),
|
|
@@ -105,7 +110,8 @@ const FeedbackDetailSchema = z.object({
|
|
|
105
110
|
server.registerTool('list_tasks', {
|
|
106
111
|
title: 'List Tasks',
|
|
107
112
|
description: 'Get roadmap tasks. Returns planned/in-progress by default. ' +
|
|
108
|
-
'Filter by type, quarter, etc
|
|
113
|
+
'Filter by type, quarter, etc.\n\n' +
|
|
114
|
+
'**Recommended:** Call `get_project_context` before starting work to understand codebase patterns.',
|
|
109
115
|
inputSchema: z.object({
|
|
110
116
|
status: z.enum(['planned', 'in_progress', 'done', 'all']).optional(),
|
|
111
117
|
type: z.enum(['bug', 'feature', 'improvement', 'task']).optional().describe('Filter by task type'),
|
|
@@ -151,15 +157,21 @@ server.registerTool('list_tasks', {
|
|
|
151
157
|
const quarterInfo = t.quarter ? ` 📅${t.quarter}` : '';
|
|
152
158
|
return `• ${t.id}: ${typeIcon} ${t.title} [${t.status}] ${p}${quarterInfo}${t.hasImplementationPlan ? ' 📋' : ''}${subtaskInfo}`;
|
|
153
159
|
});
|
|
160
|
+
const output = [
|
|
161
|
+
`Tasks in "${data.project.name}":`,
|
|
162
|
+
lines.join('\n'),
|
|
163
|
+
'',
|
|
164
|
+
'💡 **Tip:** Run `get_project_context` first to understand codebase patterns before starting work.',
|
|
165
|
+
].join('\n');
|
|
154
166
|
return {
|
|
155
|
-
content: [{ type: 'text', text:
|
|
167
|
+
content: [{ type: 'text', text: output }],
|
|
156
168
|
structuredContent: { project: data.project.name, tasks: data.tasks },
|
|
157
169
|
};
|
|
158
170
|
});
|
|
159
171
|
// Tool: Get task
|
|
160
172
|
server.registerTool('get_task', {
|
|
161
173
|
title: 'Get Task',
|
|
162
|
-
description: 'Get task details including description, plan, and linked feedback.',
|
|
174
|
+
description: 'Get task details including description, plan, commits, and linked feedback.',
|
|
163
175
|
inputSchema: z.object({
|
|
164
176
|
taskId: z.string().describe('Task ID'),
|
|
165
177
|
}),
|
|
@@ -202,12 +214,24 @@ server.registerTool('get_task', {
|
|
|
202
214
|
parts.push(`\n## Subtasks (${done}/${t.subtasks.length})`);
|
|
203
215
|
t.subtasks.forEach((s) => parts.push(`- [${s.done ? 'x' : ' '}] ${s.title} (id: ${s.id})`));
|
|
204
216
|
}
|
|
217
|
+
// Show commits
|
|
218
|
+
if (t.commits && t.commits.length) {
|
|
219
|
+
parts.push(`\n## Commits (${t.commits.length})`);
|
|
220
|
+
t.commits.forEach((c) => parts.push(`- ${c.hash.slice(0, 7)}: ${c.message}`));
|
|
221
|
+
}
|
|
205
222
|
if (t.agentNotes)
|
|
206
223
|
parts.push(`\n## Notes\n${t.agentNotes}`);
|
|
207
224
|
if (t.feedback.length) {
|
|
208
225
|
parts.push(`\n## Feedback (${t.feedback.length})`);
|
|
209
226
|
t.feedback.forEach((f) => parts.push(`- ${f.title} (${f.voterCount} votes)`));
|
|
210
227
|
}
|
|
228
|
+
// Add workflow reminder for tasks not yet started
|
|
229
|
+
if (t.status === 'planned') {
|
|
230
|
+
parts.push('\n---');
|
|
231
|
+
parts.push('**To work on this task:**');
|
|
232
|
+
parts.push('1. `get_project_context` → read relevant sections');
|
|
233
|
+
parts.push('2. `start_task` → locks task and shows context');
|
|
234
|
+
}
|
|
211
235
|
return {
|
|
212
236
|
content: [{ type: 'text', text: parts.join('\n') }],
|
|
213
237
|
structuredContent: t,
|
|
@@ -216,7 +240,7 @@ server.registerTool('get_task', {
|
|
|
216
240
|
// Tool: Update task
|
|
217
241
|
server.registerTool('update_task', {
|
|
218
242
|
title: 'Update Task',
|
|
219
|
-
description: 'Update task fields like description, implementation plan, priority, effort, quarter, or
|
|
243
|
+
description: 'Update task fields like description, implementation plan, priority, effort, quarter, labels, or visibility. ' +
|
|
220
244
|
'Useful for refining task details as you learn more about the work.',
|
|
221
245
|
inputSchema: z.object({
|
|
222
246
|
taskId: z.string().describe('Task ID'),
|
|
@@ -226,6 +250,7 @@ server.registerTool('update_task', {
|
|
|
226
250
|
effort: z.enum(['xs', 's', 'm', 'l', 'xl']).nullable().optional().describe('Estimated effort'),
|
|
227
251
|
quarter: z.string().nullable().optional().describe('Target quarter (e.g., "Q1 2025", "Q2 2025")'),
|
|
228
252
|
labels: z.array(z.string()).optional().describe('Labels/tags'),
|
|
253
|
+
isPublic: z.boolean().optional().describe('Whether task is visible on public roadmap'),
|
|
229
254
|
}),
|
|
230
255
|
outputSchema: z.object({
|
|
231
256
|
id: z.string(),
|
|
@@ -236,6 +261,7 @@ server.registerTool('update_task', {
|
|
|
236
261
|
effort: z.string().nullable().optional(),
|
|
237
262
|
quarter: z.string().nullable().optional(),
|
|
238
263
|
labels: z.array(z.string()).optional(),
|
|
264
|
+
isPublic: z.boolean().optional(),
|
|
239
265
|
}),
|
|
240
266
|
annotations: {
|
|
241
267
|
readOnlyHint: false,
|
|
@@ -243,7 +269,7 @@ server.registerTool('update_task', {
|
|
|
243
269
|
idempotentHint: true,
|
|
244
270
|
openWorldHint: false,
|
|
245
271
|
},
|
|
246
|
-
}, async ({ taskId, description, implementationPlan, priority, effort, quarter, labels }) => {
|
|
272
|
+
}, async ({ taskId, description, implementationPlan, priority, effort, quarter, labels, isPublic }) => {
|
|
247
273
|
const body = {};
|
|
248
274
|
if (description !== undefined)
|
|
249
275
|
body.description = description;
|
|
@@ -257,6 +283,8 @@ server.registerTool('update_task', {
|
|
|
257
283
|
body.quarter = quarter;
|
|
258
284
|
if (labels !== undefined)
|
|
259
285
|
body.labels = labels;
|
|
286
|
+
if (isPublic !== undefined)
|
|
287
|
+
body.isPublic = isPublic;
|
|
260
288
|
const result = await api('PATCH', `/api/agent/tasks/${taskId}`, body);
|
|
261
289
|
const updates = [];
|
|
262
290
|
if (description !== undefined)
|
|
@@ -271,6 +299,8 @@ server.registerTool('update_task', {
|
|
|
271
299
|
updates.push(`quarter=${quarter || 'none'}`);
|
|
272
300
|
if (labels !== undefined)
|
|
273
301
|
updates.push(`labels=[${labels.join(', ')}]`);
|
|
302
|
+
if (isPublic !== undefined)
|
|
303
|
+
updates.push(`isPublic=${isPublic}`);
|
|
274
304
|
return {
|
|
275
305
|
content: [{ type: 'text', text: `📝 Updated ${result.title}: ${updates.join(', ')}` }],
|
|
276
306
|
structuredContent: {
|
|
@@ -282,6 +312,7 @@ server.registerTool('update_task', {
|
|
|
282
312
|
effort: result.effort,
|
|
283
313
|
quarter: result.quarter,
|
|
284
314
|
labels: result.labels,
|
|
315
|
+
isPublic: result.isPublic,
|
|
285
316
|
},
|
|
286
317
|
};
|
|
287
318
|
});
|
|
@@ -295,12 +326,14 @@ server.registerTool('create_task', {
|
|
|
295
326
|
type: z.enum(['bug', 'feature', 'improvement', 'task']).optional().describe('Task type (default: feature)'),
|
|
296
327
|
status: z.enum(['planned', 'in_progress']).optional(),
|
|
297
328
|
implementationPlan: z.string().optional(),
|
|
329
|
+
isPublic: z.boolean().optional().describe('Whether task is visible on public roadmap (default: true)'),
|
|
298
330
|
}),
|
|
299
331
|
outputSchema: z.object({
|
|
300
332
|
id: z.string(),
|
|
301
333
|
title: z.string(),
|
|
302
334
|
type: z.string(),
|
|
303
335
|
status: z.string(),
|
|
336
|
+
isPublic: z.boolean().optional(),
|
|
304
337
|
}),
|
|
305
338
|
annotations: {
|
|
306
339
|
readOnlyHint: false,
|
|
@@ -311,8 +344,9 @@ server.registerTool('create_task', {
|
|
|
311
344
|
}, async (args) => {
|
|
312
345
|
const result = await api('POST', '/api/agent/tasks', args);
|
|
313
346
|
const typeIcon = result.type === 'bug' ? '🐛' : result.type === 'feature' ? '✨' : result.type === 'improvement' ? '💡' : '📌';
|
|
347
|
+
const visibilityIcon = result.isPublic ? '' : ' 🔒';
|
|
314
348
|
return {
|
|
315
|
-
content: [{ type: 'text', text: `Created: ${result.id} ${typeIcon} "${result.title}" [${result.status}]` }],
|
|
349
|
+
content: [{ type: 'text', text: `Created: ${result.id} ${typeIcon} "${result.title}" [${result.status}]${visibilityIcon}` }],
|
|
316
350
|
structuredContent: result,
|
|
317
351
|
};
|
|
318
352
|
});
|
|
@@ -333,11 +367,14 @@ server.registerTool('start_task', {
|
|
|
333
367
|
description: 'Lock and start a task. Fails if locked by another agent unless force=true. ' +
|
|
334
368
|
'Use force=true to take over a task from another agent (e.g., if they abandoned it). ' +
|
|
335
369
|
'Returns project context index with relevant sections for the task.\n\n' +
|
|
370
|
+
'**IMPORTANT:** After starting, use get_context_section to read relevant sections. ' +
|
|
371
|
+
'Project context contains architecture and patterns you MUST follow.\n\n' +
|
|
336
372
|
'**Workflow after starting:**\n' +
|
|
337
|
-
'1.
|
|
338
|
-
'2.
|
|
339
|
-
'3.
|
|
340
|
-
'4.
|
|
373
|
+
'1. Read relevant context sections (architecture, conventions, etc.)\n' +
|
|
374
|
+
'2. add_note: "Session started: <your goal>"\n' +
|
|
375
|
+
'3. Do work, log commits with add_commit, decisions with add_note\n' +
|
|
376
|
+
'4. add_note: "Session end: <summary, next steps>"\n' +
|
|
377
|
+
'5. complete_task (done) or abandon_task (stopping)',
|
|
341
378
|
inputSchema: z.object({
|
|
342
379
|
taskId: z.string(),
|
|
343
380
|
force: z.boolean().optional().describe('Take over lock from another agent'),
|
|
@@ -395,9 +432,9 @@ server.registerTool('add_note', {
|
|
|
395
432
|
description: 'Add progress note to task. Notes help future agents continue your work.\n\n' +
|
|
396
433
|
'**When to use:**\n' +
|
|
397
434
|
'- Session start: "Session started: implementing X"\n' +
|
|
398
|
-
'- Commits: "Committed abc123: Added validation"\n' +
|
|
399
435
|
'- Decisions: "Decision: Using X because Y"\n' +
|
|
400
436
|
'- Session end: "Session end: Done X, remaining Y, blockers Z"\n\n' +
|
|
437
|
+
'**For commits:** Use `add_commit` instead for structured commit tracking.\n\n' +
|
|
401
438
|
'**Important:** Always log session end before complete_task or abandon_task.',
|
|
402
439
|
inputSchema: z.object({
|
|
403
440
|
taskId: z.string(),
|
|
@@ -420,6 +457,37 @@ server.registerTool('add_note', {
|
|
|
420
457
|
structuredContent: { taskId, success: true },
|
|
421
458
|
};
|
|
422
459
|
});
|
|
460
|
+
// Tool: Add commit
|
|
461
|
+
server.registerTool('add_commit', {
|
|
462
|
+
title: 'Add Commit',
|
|
463
|
+
description: 'Log a commit for a task. Stores structured commit info that appears in task details.\n\n' +
|
|
464
|
+
'**When to use:**\n' +
|
|
465
|
+
'- After making a commit: log hash and message\n' +
|
|
466
|
+
'- When completing work: optionally pass commits to complete_task instead\n\n' +
|
|
467
|
+
'**Example:** After `git commit`, call this with the commit hash and message.',
|
|
468
|
+
inputSchema: z.object({
|
|
469
|
+
taskId: z.string(),
|
|
470
|
+
hash: z.string().describe('Commit hash (short or full)'),
|
|
471
|
+
message: z.string().describe('Commit message'),
|
|
472
|
+
}),
|
|
473
|
+
outputSchema: z.object({
|
|
474
|
+
taskId: z.string(),
|
|
475
|
+
hash: z.string(),
|
|
476
|
+
success: z.boolean(),
|
|
477
|
+
}),
|
|
478
|
+
annotations: {
|
|
479
|
+
readOnlyHint: false,
|
|
480
|
+
destructiveHint: false,
|
|
481
|
+
idempotentHint: false,
|
|
482
|
+
openWorldHint: false,
|
|
483
|
+
},
|
|
484
|
+
}, async ({ taskId, hash, message }) => {
|
|
485
|
+
const result = await api('POST', `/api/agent/tasks/${taskId}/commits`, { hash, message });
|
|
486
|
+
return {
|
|
487
|
+
content: [{ type: 'text', text: `📝 Commit logged: ${hash.slice(0, 7)} - ${message}` }],
|
|
488
|
+
structuredContent: { taskId, hash: result.hash, success: true },
|
|
489
|
+
};
|
|
490
|
+
});
|
|
423
491
|
// Tool: Create subtask
|
|
424
492
|
server.registerTool('create_subtask', {
|
|
425
493
|
title: 'Create Subtask',
|
|
@@ -500,15 +568,20 @@ const DocumentationSchema = z.object({
|
|
|
500
568
|
// Tool: Complete task
|
|
501
569
|
server.registerTool('complete_task', {
|
|
502
570
|
title: 'Complete Task',
|
|
503
|
-
description: 'Mark task done with summary.
|
|
571
|
+
description: 'Mark task done with summary. Optionally log final commits at completion.\n\n' +
|
|
504
572
|
'**Before calling:**\n' +
|
|
505
573
|
'1. Push all commits\n' +
|
|
506
574
|
'2. add_note: "Session end: <what was done>"\n' +
|
|
507
575
|
'3. Check if project context docs need updating\n\n' +
|
|
576
|
+
'**Commits:** Pass commits array to log them at completion (convenience for final commits).\n\n' +
|
|
508
577
|
'Returns documentation update suggestions.',
|
|
509
578
|
inputSchema: z.object({
|
|
510
579
|
taskId: z.string(),
|
|
511
580
|
summary: z.string().describe('What was implemented'),
|
|
581
|
+
commits: z.array(z.object({
|
|
582
|
+
hash: z.string().describe('Commit hash (short or full)'),
|
|
583
|
+
message: z.string().describe('Commit message'),
|
|
584
|
+
})).optional().describe('Optional: commits to log at completion'),
|
|
512
585
|
}),
|
|
513
586
|
outputSchema: z.object({
|
|
514
587
|
id: z.string(),
|
|
@@ -521,8 +594,8 @@ server.registerTool('complete_task', {
|
|
|
521
594
|
idempotentHint: true,
|
|
522
595
|
openWorldHint: false,
|
|
523
596
|
},
|
|
524
|
-
}, async ({ taskId, summary }) => {
|
|
525
|
-
const result = await api('POST', `/api/agent/tasks/${taskId}/complete`, { summary });
|
|
597
|
+
}, async ({ taskId, summary, commits }) => {
|
|
598
|
+
const result = await api('POST', `/api/agent/tasks/${taskId}/complete`, { summary, commits });
|
|
526
599
|
return {
|
|
527
600
|
content: [{ type: 'text', text: formatCompleteTaskResponse(result) }],
|
|
528
601
|
structuredContent: result,
|
|
@@ -776,7 +849,9 @@ server.registerTool('sync_project_context', {
|
|
|
776
849
|
server.registerTool('get_project_context', {
|
|
777
850
|
title: 'Get Project Context',
|
|
778
851
|
description: 'Get project context index (token-efficient). Returns section list with previews. ' +
|
|
779
|
-
'Use get_context_section to fetch full content for sections you need
|
|
852
|
+
'Use get_context_section to fetch full content for sections you need.\n\n' +
|
|
853
|
+
'**IMPORTANT:** Call this at session start. Contains architecture, conventions, and ' +
|
|
854
|
+
'patterns you MUST follow. Skipping this leads to mistakes and inconsistent code.',
|
|
780
855
|
inputSchema: z.object({
|
|
781
856
|
taskId: z.string().optional().describe('If provided, highlights sections relevant to this task'),
|
|
782
857
|
}),
|