@damper/mcp 0.3.9 → 0.3.11
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 +15 -0
- package/dist/index.js +270 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,6 +94,7 @@ The AI will see tools from both servers and can distinguish between them:
|
|
|
94
94
|
| `get_module` | Get module details |
|
|
95
95
|
| `update_module` | Register/update a module |
|
|
96
96
|
| `sync_modules` | Bulk upload module registry |
|
|
97
|
+
| `get_agent_instructions` | Get canonical workflow for CLAUDE.md setup |
|
|
97
98
|
|
|
98
99
|
### Project Context
|
|
99
100
|
|
|
@@ -332,6 +333,20 @@ When working on tasks, follow this workflow for best results:
|
|
|
332
333
|
> Sync all my documentation to Damper
|
|
333
334
|
```
|
|
334
335
|
|
|
336
|
+
## Setting Up a Project
|
|
337
|
+
|
|
338
|
+
To add Damper workflow instructions to a new project:
|
|
339
|
+
|
|
340
|
+
```
|
|
341
|
+
> Get the agent instructions and add them to my CLAUDE.md
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
The agent will call `get_agent_instructions` and write to your CLAUDE.md file. This ensures you always have the latest workflow instructions.
|
|
345
|
+
|
|
346
|
+
**Formats:**
|
|
347
|
+
- `section` (default): Just the Damper workflow section - append to existing CLAUDE.md
|
|
348
|
+
- `markdown`: Full file with header - use when creating a new CLAUDE.md
|
|
349
|
+
|
|
335
350
|
## Agent Instructions (CLAUDE.md)
|
|
336
351
|
|
|
337
352
|
Add this to your project's `CLAUDE.md` (or `.cursorrules` for Cursor) to ensure AI agents use Damper consistently:
|
package/dist/index.js
CHANGED
|
@@ -631,6 +631,77 @@ server.registerTool('abandon_task', {
|
|
|
631
631
|
structuredContent: result,
|
|
632
632
|
};
|
|
633
633
|
});
|
|
634
|
+
// ==================== Agent Instructions ====================
|
|
635
|
+
// Tool: Get agent instructions
|
|
636
|
+
server.registerTool('get_agent_instructions', {
|
|
637
|
+
title: 'Get Agent Instructions',
|
|
638
|
+
description: 'Get the canonical Damper workflow instructions. ' +
|
|
639
|
+
'Use this to set up or update CLAUDE.md in a project.',
|
|
640
|
+
inputSchema: z.object({
|
|
641
|
+
format: z.enum(['markdown', 'section']).optional()
|
|
642
|
+
.describe('markdown = full file, section = just the Damper section (default: section)'),
|
|
643
|
+
}),
|
|
644
|
+
outputSchema: z.object({
|
|
645
|
+
format: z.enum(['markdown', 'section']),
|
|
646
|
+
content: z.string(),
|
|
647
|
+
lastModified: z.string().describe('ISO date when instructions were last updated'),
|
|
648
|
+
}),
|
|
649
|
+
annotations: {
|
|
650
|
+
readOnlyHint: true,
|
|
651
|
+
destructiveHint: false,
|
|
652
|
+
idempotentHint: true,
|
|
653
|
+
openWorldHint: false,
|
|
654
|
+
},
|
|
655
|
+
}, async ({ format = 'section' }) => {
|
|
656
|
+
const lastModified = '2025-02-04';
|
|
657
|
+
const section = `## Task Management with Damper MCP
|
|
658
|
+
|
|
659
|
+
> Last updated: ${lastModified}
|
|
660
|
+
|
|
661
|
+
This project uses Damper MCP for task tracking. **You MUST follow this workflow.**
|
|
662
|
+
|
|
663
|
+
### At Session Start (MANDATORY)
|
|
664
|
+
1. \`get_project_context\` - **READ THIS FIRST.** Contains architecture, conventions, and critical project info.
|
|
665
|
+
2. \`get_context_section\` - Fetch full content for sections relevant to your task
|
|
666
|
+
3. \`list_tasks\` - Check for existing tasks to work on
|
|
667
|
+
4. If working on a task: \`start_task\` to lock it
|
|
668
|
+
|
|
669
|
+
### While Working
|
|
670
|
+
- \`add_commit\` after each commit with hash and message
|
|
671
|
+
- \`add_note\` for decisions: "Decision: chose X because Y"
|
|
672
|
+
- \`update_subtask\` to mark subtask progress
|
|
673
|
+
- **Follow patterns from project context** - Don't reinvent; use existing conventions
|
|
674
|
+
|
|
675
|
+
### Feedback & Changelog Integration
|
|
676
|
+
- \`link_feedback_to_task\` - Link user feedback IDs to your task (helps track what customer requests led to the feature)
|
|
677
|
+
- When completing a **public** task, it auto-adds to the project's draft changelog
|
|
678
|
+
- \`list_changelogs\` - View existing changelogs and drafts
|
|
679
|
+
- \`create_changelog\` / \`update_changelog\` - Create or edit changelog entries
|
|
680
|
+
- \`add_to_changelog\` - Manually add completed tasks to a changelog
|
|
681
|
+
|
|
682
|
+
### At Session End (MANDATORY)
|
|
683
|
+
- ALWAYS call \`add_note\` with session summary before stopping
|
|
684
|
+
- ALWAYS call \`complete_task\` (if done) or \`abandon_task\` (if stopping early)
|
|
685
|
+
- NEVER leave a started task without completing or abandoning it
|
|
686
|
+
- If you learned something about the codebase, consider updating project context
|
|
687
|
+
|
|
688
|
+
### Why This Matters
|
|
689
|
+
- **Project context prevents mistakes** - Contains architecture decisions, gotchas, and patterns
|
|
690
|
+
- Locked tasks block other agents from working on them
|
|
691
|
+
- Commits and notes help the next agent continue the work
|
|
692
|
+
- Updating context saves future agents from re-analyzing the codebase
|
|
693
|
+
- Linking feedback connects customer requests to shipped features`;
|
|
694
|
+
if (format === 'markdown') {
|
|
695
|
+
return {
|
|
696
|
+
content: [{ type: 'text', text: `# CLAUDE.md\n\n${section}` }],
|
|
697
|
+
structuredContent: { format: 'markdown', content: `# CLAUDE.md\n\n${section}`, lastModified },
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
return {
|
|
701
|
+
content: [{ type: 'text', text: section }],
|
|
702
|
+
structuredContent: { format: 'section', content: section, lastModified },
|
|
703
|
+
};
|
|
704
|
+
});
|
|
634
705
|
// ==================== Context Tools ====================
|
|
635
706
|
// Tool: List context sections
|
|
636
707
|
server.registerTool('list_context_sections', {
|
|
@@ -1307,6 +1378,205 @@ server.registerTool('sync_modules', {
|
|
|
1307
1378
|
structuredContent: result,
|
|
1308
1379
|
};
|
|
1309
1380
|
});
|
|
1381
|
+
// ==================== Changelog Tools ====================
|
|
1382
|
+
// Tool: Link feedback to task
|
|
1383
|
+
server.registerTool('link_feedback_to_task', {
|
|
1384
|
+
title: 'Link Feedback to Task',
|
|
1385
|
+
description: 'Link feedback items to a roadmap task. Links the specified feedback IDs to the task.\n\n' +
|
|
1386
|
+
'**When to use:**\n' +
|
|
1387
|
+
'- After seeing relevant feedback in `list_feedback`\n' +
|
|
1388
|
+
'- When user mentions feedback that should be tracked with a task',
|
|
1389
|
+
inputSchema: z.object({
|
|
1390
|
+
taskId: z.string().describe('Task ID to link feedback to'),
|
|
1391
|
+
feedbackIds: z.array(z.string()).describe('Feedback IDs to link'),
|
|
1392
|
+
}),
|
|
1393
|
+
outputSchema: z.object({
|
|
1394
|
+
taskId: z.string(),
|
|
1395
|
+
linkedFeedbackIds: z.array(z.string()),
|
|
1396
|
+
totalLinkedFeedback: z.number(),
|
|
1397
|
+
feedbackTitles: z.array(z.string()),
|
|
1398
|
+
}),
|
|
1399
|
+
annotations: {
|
|
1400
|
+
readOnlyHint: false,
|
|
1401
|
+
destructiveHint: false,
|
|
1402
|
+
idempotentHint: true,
|
|
1403
|
+
openWorldHint: false,
|
|
1404
|
+
},
|
|
1405
|
+
}, async ({ taskId, feedbackIds }) => {
|
|
1406
|
+
const result = await api('POST', `/api/agent/tasks/${taskId}/feedback`, { feedbackIds });
|
|
1407
|
+
const linkedCount = result.linkedFeedbackIds.length;
|
|
1408
|
+
if (linkedCount === 0) {
|
|
1409
|
+
return {
|
|
1410
|
+
content: [{ type: 'text', text: `No new feedback linked (already linked or not found)` }],
|
|
1411
|
+
structuredContent: result,
|
|
1412
|
+
};
|
|
1413
|
+
}
|
|
1414
|
+
return {
|
|
1415
|
+
content: [{ type: 'text', text: `🔗 Linked ${linkedCount} feedback to task: ${result.feedbackTitles.join(', ')}` }],
|
|
1416
|
+
structuredContent: result,
|
|
1417
|
+
};
|
|
1418
|
+
});
|
|
1419
|
+
// Tool: List changelogs
|
|
1420
|
+
server.registerTool('list_changelogs', {
|
|
1421
|
+
title: 'List Changelogs',
|
|
1422
|
+
description: 'List changelogs for the project. Filter by status (draft, published).\n\n' +
|
|
1423
|
+
'**Draft changelogs:** Automatically created when completing public roadmap items. ' +
|
|
1424
|
+
'Review and publish them to announce releases.',
|
|
1425
|
+
inputSchema: z.object({
|
|
1426
|
+
status: z.enum(['draft', 'published']).optional().describe('Filter by status'),
|
|
1427
|
+
limit: z.number().optional(),
|
|
1428
|
+
}),
|
|
1429
|
+
outputSchema: z.object({
|
|
1430
|
+
changelogs: z.array(z.object({
|
|
1431
|
+
id: z.string(),
|
|
1432
|
+
title: z.string(),
|
|
1433
|
+
version: z.string().nullable().optional(),
|
|
1434
|
+
status: z.string(),
|
|
1435
|
+
publishedAt: z.string().nullable().optional(),
|
|
1436
|
+
roadmapItemCount: z.number(),
|
|
1437
|
+
contentPreview: z.string(),
|
|
1438
|
+
})),
|
|
1439
|
+
}),
|
|
1440
|
+
annotations: {
|
|
1441
|
+
readOnlyHint: true,
|
|
1442
|
+
destructiveHint: false,
|
|
1443
|
+
idempotentHint: true,
|
|
1444
|
+
openWorldHint: false,
|
|
1445
|
+
},
|
|
1446
|
+
}, async ({ status, limit }) => {
|
|
1447
|
+
const params = new URLSearchParams();
|
|
1448
|
+
if (status)
|
|
1449
|
+
params.set('status', status);
|
|
1450
|
+
if (limit)
|
|
1451
|
+
params.set('limit', String(limit));
|
|
1452
|
+
const query = params.toString();
|
|
1453
|
+
const data = await api('GET', `/api/agent/changelogs${query ? `?${query}` : ''}`);
|
|
1454
|
+
if (!data.changelogs.length) {
|
|
1455
|
+
return {
|
|
1456
|
+
content: [{ type: 'text', text: 'No changelogs found' }],
|
|
1457
|
+
structuredContent: { changelogs: [] },
|
|
1458
|
+
};
|
|
1459
|
+
}
|
|
1460
|
+
const lines = data.changelogs.map((c) => {
|
|
1461
|
+
const status = c.status === 'draft' ? '📝' : '✅';
|
|
1462
|
+
const version = c.version ? ` v${c.version}` : '';
|
|
1463
|
+
const items = c.roadmapItemCount > 0 ? ` (${c.roadmapItemCount} items)` : '';
|
|
1464
|
+
return `• ${c.id}: ${status} ${c.title}${version}${items}`;
|
|
1465
|
+
});
|
|
1466
|
+
return {
|
|
1467
|
+
content: [{ type: 'text', text: `Changelogs:\n${lines.join('\n')}` }],
|
|
1468
|
+
structuredContent: data,
|
|
1469
|
+
};
|
|
1470
|
+
});
|
|
1471
|
+
// Tool: Create changelog
|
|
1472
|
+
server.registerTool('create_changelog', {
|
|
1473
|
+
title: 'Create Changelog',
|
|
1474
|
+
description: 'Create a new changelog entry. Usually starts as draft.\n\n' +
|
|
1475
|
+
'**Note:** Draft changelogs are auto-created when completing public roadmap items. ' +
|
|
1476
|
+
'Use this to create additional changelogs if needed.',
|
|
1477
|
+
inputSchema: z.object({
|
|
1478
|
+
title: z.string().describe('Changelog title (e.g., "v2.1.0" or "January 2025 Release")'),
|
|
1479
|
+
content: z.string().optional().describe('Initial changelog content (markdown)'),
|
|
1480
|
+
version: z.string().optional().describe('Version number'),
|
|
1481
|
+
status: z.enum(['draft', 'published']).optional().describe('Status (default: draft)'),
|
|
1482
|
+
}),
|
|
1483
|
+
outputSchema: z.object({
|
|
1484
|
+
id: z.string(),
|
|
1485
|
+
title: z.string(),
|
|
1486
|
+
version: z.string().nullable().optional(),
|
|
1487
|
+
status: z.string(),
|
|
1488
|
+
}),
|
|
1489
|
+
annotations: {
|
|
1490
|
+
readOnlyHint: false,
|
|
1491
|
+
destructiveHint: false,
|
|
1492
|
+
idempotentHint: false,
|
|
1493
|
+
openWorldHint: false,
|
|
1494
|
+
},
|
|
1495
|
+
}, async (args) => {
|
|
1496
|
+
const result = await api('POST', '/api/agent/changelogs', args);
|
|
1497
|
+
const status = result.status === 'draft' ? '📝' : '✅';
|
|
1498
|
+
return {
|
|
1499
|
+
content: [{ type: 'text', text: `${status} Created changelog: ${result.id} "${result.title}"` }],
|
|
1500
|
+
structuredContent: result,
|
|
1501
|
+
};
|
|
1502
|
+
});
|
|
1503
|
+
// Tool: Update changelog
|
|
1504
|
+
server.registerTool('update_changelog', {
|
|
1505
|
+
title: 'Update Changelog',
|
|
1506
|
+
description: 'Update a changelog entry. Can update title, content, version, or status.\n\n' +
|
|
1507
|
+
'**Publishing:** Set status to "published" to make the changelog public.',
|
|
1508
|
+
inputSchema: z.object({
|
|
1509
|
+
changelogId: z.string().describe('Changelog ID'),
|
|
1510
|
+
title: z.string().optional().describe('New title'),
|
|
1511
|
+
content: z.string().optional().describe('New content (markdown)'),
|
|
1512
|
+
version: z.string().optional().describe('Version number'),
|
|
1513
|
+
status: z.enum(['draft', 'published']).optional().describe('Status'),
|
|
1514
|
+
}),
|
|
1515
|
+
outputSchema: z.object({
|
|
1516
|
+
id: z.string(),
|
|
1517
|
+
title: z.string(),
|
|
1518
|
+
version: z.string().nullable().optional(),
|
|
1519
|
+
status: z.string(),
|
|
1520
|
+
publishedAt: z.string().nullable().optional(),
|
|
1521
|
+
}),
|
|
1522
|
+
annotations: {
|
|
1523
|
+
readOnlyHint: false,
|
|
1524
|
+
destructiveHint: false,
|
|
1525
|
+
idempotentHint: true,
|
|
1526
|
+
openWorldHint: false,
|
|
1527
|
+
},
|
|
1528
|
+
}, async ({ changelogId, title, content, version, status }) => {
|
|
1529
|
+
const body = {};
|
|
1530
|
+
if (title !== undefined)
|
|
1531
|
+
body.title = title;
|
|
1532
|
+
if (content !== undefined)
|
|
1533
|
+
body.content = content;
|
|
1534
|
+
if (version !== undefined)
|
|
1535
|
+
body.version = version;
|
|
1536
|
+
if (status !== undefined)
|
|
1537
|
+
body.status = status;
|
|
1538
|
+
const result = await api('PATCH', `/api/agent/changelogs/${changelogId}`, body);
|
|
1539
|
+
const statusIcon = result.status === 'published' ? '✅' : '📝';
|
|
1540
|
+
const published = result.status === 'published' && result.publishedAt ? ' (just published)' : '';
|
|
1541
|
+
return {
|
|
1542
|
+
content: [{ type: 'text', text: `${statusIcon} Updated changelog: "${result.title}"${published}` }],
|
|
1543
|
+
structuredContent: result,
|
|
1544
|
+
};
|
|
1545
|
+
});
|
|
1546
|
+
// Tool: Add roadmap items to changelog
|
|
1547
|
+
server.registerTool('add_to_changelog', {
|
|
1548
|
+
title: 'Add to Changelog',
|
|
1549
|
+
description: 'Add completed roadmap items to a changelog. Links the items and appends formatted entries to content.\n\n' +
|
|
1550
|
+
'**When to use:**\n' +
|
|
1551
|
+
'- After completing multiple items that should be in one release\n' +
|
|
1552
|
+
'- To manually add items to a draft changelog',
|
|
1553
|
+
inputSchema: z.object({
|
|
1554
|
+
changelogId: z.string().describe('Changelog ID'),
|
|
1555
|
+
roadmapItemIds: z.array(z.string()).describe('Roadmap item IDs to add'),
|
|
1556
|
+
}),
|
|
1557
|
+
outputSchema: z.object({
|
|
1558
|
+
id: z.string(),
|
|
1559
|
+
title: z.string(),
|
|
1560
|
+
roadmapItemCount: z.number(),
|
|
1561
|
+
addedItems: z.array(z.object({
|
|
1562
|
+
id: z.string(),
|
|
1563
|
+
title: z.string(),
|
|
1564
|
+
})),
|
|
1565
|
+
}),
|
|
1566
|
+
annotations: {
|
|
1567
|
+
readOnlyHint: false,
|
|
1568
|
+
destructiveHint: false,
|
|
1569
|
+
idempotentHint: true,
|
|
1570
|
+
openWorldHint: false,
|
|
1571
|
+
},
|
|
1572
|
+
}, async ({ changelogId, roadmapItemIds }) => {
|
|
1573
|
+
const result = await api('POST', `/api/agent/changelogs/${changelogId}/items`, { roadmapItemIds });
|
|
1574
|
+
const addedTitles = result.addedItems.map((i) => i.title).join(', ');
|
|
1575
|
+
return {
|
|
1576
|
+
content: [{ type: 'text', text: `📋 Added ${result.addedItems.length} items to "${result.title}": ${addedTitles}` }],
|
|
1577
|
+
structuredContent: result,
|
|
1578
|
+
};
|
|
1579
|
+
});
|
|
1310
1580
|
// Start
|
|
1311
1581
|
async function main() {
|
|
1312
1582
|
const transport = new StdioServerTransport();
|