@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.
Files changed (3) hide show
  1. package/README.md +15 -0
  2. package/dist/index.js +270 -0
  3. 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();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@damper/mcp",
3
- "version": "0.3.9",
3
+ "version": "0.3.11",
4
4
  "description": "MCP server for Damper task management",
5
5
  "author": "Damper <hello@usedamper.com>",
6
6
  "repository": {