lunaarc-mcp 1.2.7 → 1.2.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/dist/server.js CHANGED
@@ -27,7 +27,7 @@ catch (error) {
27
27
  // Create MCP server
28
28
  const server = new index_js_1.Server({
29
29
  name: 'lunaarc-mcp',
30
- version: '1.2.7',
30
+ version: '1.2.9',
31
31
  }, {
32
32
  capabilities: {
33
33
  tools: {},
@@ -10,6 +10,7 @@ export declare const kanbanTools: ({
10
10
  description?: undefined;
11
11
  priority?: undefined;
12
12
  labels?: undefined;
13
+ include_agent_content?: undefined;
13
14
  column?: undefined;
14
15
  content?: undefined;
15
16
  };
@@ -29,6 +30,7 @@ export declare const kanbanTools: ({
29
30
  description?: undefined;
30
31
  priority?: undefined;
31
32
  labels?: undefined;
33
+ include_agent_content?: undefined;
32
34
  column?: undefined;
33
35
  content?: undefined;
34
36
  };
@@ -61,6 +63,7 @@ export declare const kanbanTools: ({
61
63
  description: string;
62
64
  };
63
65
  card_id?: undefined;
66
+ include_agent_content?: undefined;
64
67
  column?: undefined;
65
68
  content?: undefined;
66
69
  };
@@ -96,11 +99,32 @@ export declare const kanbanTools: ({
96
99
  };
97
100
  description: string;
98
101
  };
102
+ include_agent_content?: undefined;
99
103
  column?: undefined;
100
104
  content?: undefined;
101
105
  };
102
106
  required: string[];
103
107
  };
108
+ } | {
109
+ name: string;
110
+ description: string;
111
+ inputSchema: {
112
+ type: "object";
113
+ properties: {
114
+ include_agent_content: {
115
+ type: string;
116
+ description: string;
117
+ };
118
+ card_id?: undefined;
119
+ title?: undefined;
120
+ description?: undefined;
121
+ priority?: undefined;
122
+ labels?: undefined;
123
+ column?: undefined;
124
+ content?: undefined;
125
+ };
126
+ required: never[];
127
+ };
104
128
  } | {
105
129
  name: string;
106
130
  description: string;
@@ -119,6 +143,7 @@ export declare const kanbanTools: ({
119
143
  description?: undefined;
120
144
  priority?: undefined;
121
145
  labels?: undefined;
146
+ include_agent_content?: undefined;
122
147
  content?: undefined;
123
148
  };
124
149
  required: string[];
@@ -141,6 +166,7 @@ export declare const kanbanTools: ({
141
166
  description?: undefined;
142
167
  priority?: undefined;
143
168
  labels?: undefined;
169
+ include_agent_content?: undefined;
144
170
  column?: undefined;
145
171
  };
146
172
  required: string[];
@@ -1,7 +1,146 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.kanbanTools = void 0;
4
37
  exports.handleKanbanTool = handleKanbanTool;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const crypto = __importStar(require("crypto"));
41
+ // ============================================================================
42
+ // LOCAL AGENT LOADER
43
+ // ============================================================================
44
+ const AGENT_CONTENT_HARD_LIMIT = 2000; // Max characters for full content
45
+ /**
46
+ * Load local agent file and extract metadata
47
+ */
48
+ function loadLocalAgent(agentName, includeFullContent = false) {
49
+ const agentPath = path.join(process.cwd(), '.claude/agents', `${agentName}.md`);
50
+ const result = {
51
+ found: false,
52
+ path: agentPath,
53
+ hash: null,
54
+ summary: null,
55
+ content: null,
56
+ truncated: false,
57
+ };
58
+ if (!fs.existsSync(agentPath)) {
59
+ return result;
60
+ }
61
+ try {
62
+ const fileContent = fs.readFileSync(agentPath, 'utf-8');
63
+ result.found = true;
64
+ // Generate hash for change detection
65
+ result.hash = crypto.createHash('md5').update(fileContent).digest('hex').slice(0, 8);
66
+ // Parse YAML frontmatter
67
+ const frontmatterMatch = fileContent.match(/^---\n([\s\S]*?)\n---/);
68
+ if (frontmatterMatch) {
69
+ const frontmatter = frontmatterMatch[1];
70
+ const lines = frontmatter.split('\n');
71
+ const data = {};
72
+ for (const line of lines) {
73
+ const colonIndex = line.indexOf(':');
74
+ if (colonIndex > 0) {
75
+ const key = line.slice(0, colonIndex).trim();
76
+ const value = line.slice(colonIndex + 1).trim();
77
+ data[key] = value;
78
+ }
79
+ }
80
+ result.summary = {
81
+ name: data.name || agentName,
82
+ description: data.description || null,
83
+ tools: data.tools ? data.tools.split(',').map(t => t.trim()).filter(Boolean) : [],
84
+ model: data.model || 'sonnet',
85
+ };
86
+ }
87
+ // Include full content if requested
88
+ if (includeFullContent) {
89
+ if (fileContent.length > AGENT_CONTENT_HARD_LIMIT) {
90
+ result.content = fileContent.slice(0, AGENT_CONTENT_HARD_LIMIT);
91
+ result.truncated = true;
92
+ }
93
+ else {
94
+ result.content = fileContent;
95
+ }
96
+ }
97
+ }
98
+ catch {
99
+ // File read error - return not found
100
+ }
101
+ return result;
102
+ }
103
+ /**
104
+ * Format agent info for output
105
+ */
106
+ function formatAgentOutput(agent, agentName) {
107
+ if (!agent.found) {
108
+ return `## 🤖 AI Agent: ${agentName}
109
+
110
+ ⚠️ **Agent not found locally!**
111
+ Expected at: \`${agent.path}\`
112
+
113
+ Run \`agents_download\` to get predefined agents, or create the file manually.
114
+
115
+ ---
116
+
117
+ `;
118
+ }
119
+ let output = `## 🤖 AI Agent: ${agentName}
120
+
121
+ `;
122
+ if (agent.summary) {
123
+ output += `**Description:** ${agent.summary.description || '_No description_'}
124
+ **Model:** ${agent.summary.model}
125
+ **Tools:** ${agent.summary.tools.length > 0 ? agent.summary.tools.join(', ') : 'all'}
126
+ `;
127
+ }
128
+ output += `**Hash:** \`${agent.hash}\`
129
+ **Path:** \`${agent.path}\`
130
+ `;
131
+ if (agent.content) {
132
+ output += `
133
+ <agent-definition>
134
+ ${agent.content}${agent.truncated ? '\n\n... [TRUNCATED - ' + AGENT_CONTENT_HARD_LIMIT + ' char limit]' : ''}
135
+ </agent-definition>
136
+ `;
137
+ }
138
+ output += `
139
+ ---
140
+
141
+ `;
142
+ return output;
143
+ }
5
144
  // Tool definitions for kanban operations
6
145
  exports.kanbanTools = [
7
146
  {
@@ -110,10 +249,19 @@ WORKFLOW - You MUST follow these steps:
110
249
  If a card CANNOT be completed:
111
250
  - Add a "## AI Feedback" section explaining WHY
112
251
  - Move to "On Hold" (not Done!)
113
- - Include: reason, missing prerequisites, suggestions`,
252
+ - Include: reason, missing prerequisites, suggestions
253
+
254
+ AI Agent handling:
255
+ - If the card has an AI agent assigned, the agent's summary (description, model, tools) is shown by default
256
+ - Use include_agent_content=true to include the full agent definition (max 2000 chars)`,
114
257
  inputSchema: {
115
258
  type: 'object',
116
- properties: {},
259
+ properties: {
260
+ include_agent_content: {
261
+ type: 'boolean',
262
+ description: 'Include full agent definition content (default: false, only summary shown)',
263
+ },
264
+ },
117
265
  required: [],
118
266
  },
119
267
  },
@@ -231,12 +379,12 @@ const priorityOrder = {
231
379
  // Workflow reminder that gets added to every response
232
380
  const WORKFLOW_REMINDER = `
233
381
  ---
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
382
+ ⚠️ **WORKFLOW - You MUST follow these steps:**
383
+ 1. Move card to "In Progress" BEFORE starting work
384
+ 2. Complete the task fully and test it
385
+ 3. Add a comment with a summary of changes
386
+ 4. Move to "Done" only when fully completed
387
+ 5. Call \`kanban_assigned_get\` again to get the next card
240
388
  `;
241
389
  // Tool handlers
242
390
  async function handleKanbanTool(client, toolName, args) {
@@ -379,6 +527,7 @@ ${updates.map((u) => `- ${u}`).join('\n')}`,
379
527
  };
380
528
  }
381
529
  case 'kanban_assigned_get': {
530
+ const includeAgentContent = args.include_agent_content || false;
382
531
  const cards = await client.getAIAssignedCards();
383
532
  if (cards.length === 0) {
384
533
  return {
@@ -424,12 +573,12 @@ To get cards assigned to you, a team member needs to assign a card to this AI to
424
573
  if (inProgressCard) {
425
574
  // There's already a card in progress - MUST finish this first
426
575
  cardToShow = inProgressCard;
427
- output = `# ⚠️ KARTE IN BEARBEITUNG
576
+ output = `# ⚠️ CARD IN PROGRESS
428
577
 
429
- **Du hast bereits eine Karte in "In Progress"!**
430
- **Diese MUSS zuerst abgeschlossen werden, bevor du eine neue Karte beginnen kannst.**
578
+ **You already have a card in "In Progress"!**
579
+ **This MUST be completed first before you can start a new card.**
431
580
 
432
- ${totalCards > 1 ? `_(${totalCards - 1} weitere Karte${totalCards > 2 ? 'n' : ''} in der Warteschlange)_\n` : ''}
581
+ ${totalCards > 1 ? `_(${totalCards - 1} more card${totalCards > 2 ? 's' : ''} in queue)_\n` : ''}
433
582
  ---
434
583
 
435
584
  `;
@@ -437,23 +586,18 @@ ${totalCards > 1 ? `_(${totalCards - 1} weitere Karte${totalCards > 2 ? 'n' : ''
437
586
  else {
438
587
  // No card in progress - show the next card from the queue
439
588
  cardToShow = sortedCards[0];
440
- output = `# 📋 Nächste Karte
589
+ output = `# 📋 Next Card
441
590
 
442
- **Karte 1 von ${totalCards}** - Schließe diese ab, bevor du die nächste holst.
591
+ **Card 1 of ${totalCards}** - Complete this before getting the next one.
443
592
 
444
593
  ---
445
594
 
446
595
  `;
447
596
  }
448
- // Show agent assignment if present - AI uses local agent definition
597
+ // Show agent assignment if present - load from local file
449
598
  if (cardToShow.agent_name) {
450
- output += `## 🤖 AI Agent: ${cardToShow.agent_name}
451
-
452
- Use your local agent definition from \`.claude/agents/${cardToShow.agent_name}.md\`
453
-
454
- ---
455
-
456
- `;
599
+ const agentInfo = loadLocalAgent(cardToShow.agent_name, includeAgentContent);
600
+ output += formatAgentOutput(agentInfo, cardToShow.agent_name);
457
601
  }
458
602
  // Render the single card
459
603
  const priority = priorityEmoji[cardToShow.priority] || '⚪';
@@ -468,10 +612,6 @@ Use your local agent definition from \`.claude/agents/${cardToShow.agent_name}.m
468
612
  if (cardToShow.due_date) {
469
613
  output += `\n**Due:** ${new Date(cardToShow.due_date).toLocaleDateString()}`;
470
614
  }
471
- // Show assigned AI Agent if present
472
- if (cardToShow.agent_name) {
473
- output += `\n**AI Agent:** ${cardToShow.agent_name}`;
474
- }
475
615
  output += '\n\n';
476
616
  output += cardToShow.description || '_No description_';
477
617
  // Add workflow reminder at the end
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lunaarc-mcp",
3
- "version": "1.2.7",
3
+ "version": "1.2.9",
4
4
  "description": "MCP Server for LunaArc - Access Wiki and Kanban from AI assistants",
5
5
  "main": "dist/server.js",
6
6
  "bin": {