lunaarc-mcp 1.1.4 → 1.2.0

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/dist/server.js CHANGED
@@ -26,7 +26,7 @@ catch (error) {
26
26
  // Create MCP server
27
27
  const server = new index_js_1.Server({
28
28
  name: 'lunaarc-mcp',
29
- version: '1.1.4',
29
+ version: '1.2.0',
30
30
  }, {
31
31
  capabilities: {
32
32
  tools: {},
@@ -89,22 +89,28 @@ exports.kanbanTools = [
89
89
  },
90
90
  {
91
91
  name: 'kanban_assigned_get',
92
- description: `Get all kanban cards that are assigned to this AI. Returns cards from any column that have been assigned to this AI token for processing.
92
+ description: `Get the NEXT kanban card to work on. Returns only ONE card at a time to ensure proper workflow.
93
93
 
94
- IMPORTANT - AI Workflow Guidelines:
95
- 1. BEFORE starting work on a card, verify:
96
- - Is the task clearly defined and understandable?
97
- - Are all required information/resources available?
98
- - Is the task technically feasible?
94
+ IMPORTANT - This tool enforces a strict workflow:
95
+ - If you have a card "In Progress": Only that card is returned (must be completed first!)
96
+ - If no card in progress: The next card from the queue is returned (sorted by priority)
99
97
 
100
- 2. Move card to "In Progress" before starting work.
98
+ Card queue sorting:
99
+ 1. Column: In Progress > Ready for Development > Backlog
100
+ 2. Priority: urgent > high > medium > low
101
+ 3. Due date: earliest first
101
102
 
102
- 3. If a card CANNOT be completed:
103
- - Update the description with a "## AI Feedback" section explaining WHY
104
- - Move the card to "On Hold" (not Done!)
105
- - Include: reason, missing prerequisites, and suggestions
103
+ WORKFLOW - You MUST follow these steps:
104
+ 1. Move card to "In Progress" BEFORE starting work
105
+ 2. Complete the task fully and test it
106
+ 3. Add a comment with a summary of changes
107
+ 4. Move to "Done" only when fully completed
108
+ 5. Call this tool again to get the next card
106
109
 
107
- 4. Only move to "Done" when the task is fully completed.`,
110
+ If a card CANNOT be completed:
111
+ - Add a "## AI Feedback" section explaining WHY
112
+ - Move to "On Hold" (not Done!)
113
+ - Include: reason, missing prerequisites, suggestions`,
108
114
  inputSchema: {
109
115
  type: 'object',
110
116
  properties: {},
@@ -209,6 +215,29 @@ const priorityEmoji = {
209
215
  high: '🟠',
210
216
  urgent: '🔴',
211
217
  };
218
+ // Column priority for sorting (lower = higher priority)
219
+ const columnPriority = {
220
+ 'In Progress': 0,
221
+ 'Ready for Development': 1,
222
+ 'Backlog': 2,
223
+ };
224
+ // Priority sorting (lower = higher priority)
225
+ const priorityOrder = {
226
+ urgent: 0,
227
+ high: 1,
228
+ medium: 2,
229
+ low: 3,
230
+ };
231
+ // Workflow reminder that gets added to every response
232
+ const WORKFLOW_REMINDER = `
233
+ ---
234
+ ⚠️ **WORKFLOW - Diese Schritte MÜSSEN eingehalten werden:**
235
+ 1. Karte nach "In Progress" verschieben BEVOR du anfängst
236
+ 2. Task vollständig erledigen und testen
237
+ 3. Kommentar mit Zusammenfassung der Änderungen hinzufügen
238
+ 4. Erst nach Abschluss nach "Done" verschieben
239
+ 5. Dann erneut \`kanban_assigned_get\` aufrufen für die nächste Karte
240
+ `;
212
241
  // Tool handlers
213
242
  async function handleKanbanTool(client, toolName, args) {
214
243
  switch (toolName) {
@@ -365,38 +394,82 @@ To get cards assigned to you, a team member needs to assign a card to this AI to
365
394
  ],
366
395
  };
367
396
  }
368
- let output = `# AI Assigned Cards
397
+ // Sort cards: Column priority > Priority > Due date
398
+ const sortedCards = [...cards].sort((a, b) => {
399
+ // 1. Column priority (In Progress > Ready for Development > Backlog)
400
+ const colA = columnPriority[a.column_name] ?? 99;
401
+ const colB = columnPriority[b.column_name] ?? 99;
402
+ if (colA !== colB)
403
+ return colA - colB;
404
+ // 2. Priority (urgent > high > medium > low)
405
+ const prioA = priorityOrder[a.priority] ?? 99;
406
+ const prioB = priorityOrder[b.priority] ?? 99;
407
+ if (prioA !== prioB)
408
+ return prioA - prioB;
409
+ // 3. Due date (earliest first, null at the end)
410
+ if (a.due_date && b.due_date) {
411
+ return new Date(a.due_date).getTime() - new Date(b.due_date).getTime();
412
+ }
413
+ if (a.due_date && !b.due_date)
414
+ return -1;
415
+ if (!a.due_date && b.due_date)
416
+ return 1;
417
+ return 0;
418
+ });
419
+ // Check if there's a card in "In Progress"
420
+ const inProgressCard = sortedCards.find((c) => c.column_name === 'In Progress');
421
+ const totalCards = cards.length;
422
+ let output = '';
423
+ let cardToShow;
424
+ if (inProgressCard) {
425
+ // There's already a card in progress - MUST finish this first
426
+ cardToShow = inProgressCard;
427
+ output = `# ⚠️ KARTE IN BEARBEITUNG
369
428
 
370
- **${cards.length} card${cards.length === 1 ? '' : 's'} assigned to this AI**
429
+ **Du hast bereits eine Karte in "In Progress"!**
430
+ **Diese MUSS zuerst abgeschlossen werden, bevor du eine neue Karte beginnen kannst.**
371
431
 
432
+ ${totalCards > 1 ? `_(${totalCards - 1} weitere Karte${totalCards > 2 ? 'n' : ''} in der Warteschlange)_\n` : ''}
372
433
  ---
373
434
 
374
435
  `;
375
- for (const card of cards) {
376
- const priority = priorityEmoji[card.priority] || '⚪';
377
- output += `## ${priority} ${card.title}
436
+ }
437
+ else {
438
+ // No card in progress - show the next card from the queue
439
+ cardToShow = sortedCards[0];
440
+ output = `# 📋 Nächste Karte
378
441
 
379
- **ID:** \`${card.id}\`
380
- **Column:** ${card.column_name}
381
- **Priority:** ${card.priority}`;
382
- if (card.labels.length > 0) {
383
- output += `\n**Labels:** ${card.labels.map((l) => `\`${l}\``).join(', ')}`;
384
- }
385
- if (card.due_date) {
386
- output += `\n**Due:** ${new Date(card.due_date).toLocaleDateString()}`;
387
- }
388
- // Show assigned AI Agent if present
389
- if (card.agent_name) {
390
- output += `\n**AI Agent:** ${card.agent_name}`;
391
- }
392
- output += '\n\n';
393
- output += card.description || '_No description_';
394
- // Include agent context if present
395
- if (card.agent_content) {
396
- output += `\n\n---\n\n### Agent Instructions\n\n${card.agent_content}`;
397
- }
398
- output += '\n\n---\n\n';
442
+ **Karte 1 von ${totalCards}** - Schließe diese ab, bevor du die nächste holst.
443
+
444
+ ---
445
+
446
+ `;
447
+ }
448
+ // Render the single card
449
+ const priority = priorityEmoji[cardToShow.priority] || '⚪';
450
+ output += `## ${priority} ${cardToShow.title}
451
+
452
+ **ID:** \`${cardToShow.id}\`
453
+ **Column:** ${cardToShow.column_name}
454
+ **Priority:** ${cardToShow.priority}`;
455
+ if (cardToShow.labels.length > 0) {
456
+ output += `\n**Labels:** ${cardToShow.labels.map((l) => `\`${l}\``).join(', ')}`;
457
+ }
458
+ if (cardToShow.due_date) {
459
+ output += `\n**Due:** ${new Date(cardToShow.due_date).toLocaleDateString()}`;
460
+ }
461
+ // Show assigned AI Agent if present
462
+ if (cardToShow.agent_name) {
463
+ output += `\n**AI Agent:** ${cardToShow.agent_name}`;
464
+ }
465
+ output += '\n\n';
466
+ output += cardToShow.description || '_No description_';
467
+ // Include agent context if present
468
+ if (cardToShow.agent_content) {
469
+ output += `\n\n---\n\n### Agent Instructions\n\n${cardToShow.agent_content}`;
399
470
  }
471
+ // Add workflow reminder at the end
472
+ output += WORKFLOW_REMINDER;
400
473
  return {
401
474
  content: [{ type: 'text', text: output }],
402
475
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lunaarc-mcp",
3
- "version": "1.1.4",
3
+ "version": "1.2.0",
4
4
  "description": "MCP Server for LunaArc - Access Wiki and Kanban from AI assistants",
5
5
  "main": "dist/server.js",
6
6
  "bin": {