harmony-mcp 1.3.2 → 1.5.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/README.md +24 -25
- package/dist/cli.js +22768 -17253
- package/dist/index.js +19930 -15858
- package/dist/init.js +281 -70
- package/package.json +11 -9
package/dist/init.js
CHANGED
|
@@ -28,7 +28,7 @@ var __export = (target, all) => {
|
|
|
28
28
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
29
29
|
|
|
30
30
|
// src/init.ts
|
|
31
|
-
import { existsSync, mkdirSync, writeFileSync, readFileSync } from "node:fs";
|
|
31
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync, symlinkSync, unlinkSync, lstatSync } from "node:fs";
|
|
32
32
|
import { join, dirname } from "node:path";
|
|
33
33
|
import { homedir } from "node:os";
|
|
34
34
|
var HARMONY_WORKFLOW_PROMPT = `# Harmony Card Workflow
|
|
@@ -106,6 +106,94 @@ If pausing: \`harmony_end_agent_session\` with \`status: "paused"\`
|
|
|
106
106
|
|
|
107
107
|
**AI:** \`harmony_generate_prompt\`, \`harmony_process_command\`
|
|
108
108
|
`;
|
|
109
|
+
var HARMONY_STANDUP_PROMPT = `# Harmony Daily Standup
|
|
110
|
+
|
|
111
|
+
Generate a daily standup summary for the current project.
|
|
112
|
+
|
|
113
|
+
## 1. Get Board State
|
|
114
|
+
|
|
115
|
+
Call \`harmony_get_board\` to get the full board state including:
|
|
116
|
+
- All columns and their cards
|
|
117
|
+
- Card priorities, assignees, and due dates
|
|
118
|
+
- Active agent sessions
|
|
119
|
+
|
|
120
|
+
## 2. Analyze Board
|
|
121
|
+
|
|
122
|
+
Organize the information into standup categories:
|
|
123
|
+
|
|
124
|
+
### What was completed recently
|
|
125
|
+
- Cards in "Done" or "Review" columns
|
|
126
|
+
- Cards with recent activity (moved, updated)
|
|
127
|
+
|
|
128
|
+
### What's in progress
|
|
129
|
+
- Cards in "In Progress" column
|
|
130
|
+
- Cards with active agent sessions (show progress %)
|
|
131
|
+
- Who's working on what
|
|
132
|
+
|
|
133
|
+
### What's blocked or at risk
|
|
134
|
+
- High-priority cards not in progress
|
|
135
|
+
- Overdue cards
|
|
136
|
+
- Cards with blockers
|
|
137
|
+
|
|
138
|
+
### What's coming up
|
|
139
|
+
- Cards in "To Do" column
|
|
140
|
+
- Upcoming due dates
|
|
141
|
+
|
|
142
|
+
## 3. Present Summary
|
|
143
|
+
|
|
144
|
+
Format the summary as a clean, readable standup report:
|
|
145
|
+
- Use bullet points for easy scanning
|
|
146
|
+
- Highlight priorities and blockers
|
|
147
|
+
- Include card short IDs for easy reference (e.g., #42)
|
|
148
|
+
- Note any agent work in progress
|
|
149
|
+
`;
|
|
150
|
+
var HARMONY_CLEANUP_PROMPT = `# Harmony Board Cleanup
|
|
151
|
+
|
|
152
|
+
Analyze the board and suggest cleanup actions.
|
|
153
|
+
|
|
154
|
+
## 1. Get Board State
|
|
155
|
+
|
|
156
|
+
Call \`harmony_get_board\` to get the full board state.
|
|
157
|
+
|
|
158
|
+
## 2. Identify Issues
|
|
159
|
+
|
|
160
|
+
Look for:
|
|
161
|
+
|
|
162
|
+
### Stale cards
|
|
163
|
+
- Cards in "In Progress" for too long without updates
|
|
164
|
+
- Cards with past due dates
|
|
165
|
+
- Cards with no recent activity
|
|
166
|
+
|
|
167
|
+
### Organizational issues
|
|
168
|
+
- Cards missing priorities
|
|
169
|
+
- Cards missing assignees in active columns
|
|
170
|
+
- Empty descriptions on complex cards
|
|
171
|
+
|
|
172
|
+
### Potential duplicates
|
|
173
|
+
- Cards with similar titles
|
|
174
|
+
- Use \`harmony_search_cards\` if needed to find related cards
|
|
175
|
+
|
|
176
|
+
## 3. Suggest Actions
|
|
177
|
+
|
|
178
|
+
For each issue found, suggest a specific action:
|
|
179
|
+
- Move stale cards back to backlog
|
|
180
|
+
- Archive completed cards
|
|
181
|
+
- Update missing information
|
|
182
|
+
- Merge or link duplicates
|
|
183
|
+
|
|
184
|
+
Present suggestions as a prioritized list with:
|
|
185
|
+
- Card reference (#ID)
|
|
186
|
+
- Current state
|
|
187
|
+
- Suggested action
|
|
188
|
+
- Why it matters
|
|
189
|
+
|
|
190
|
+
## 4. Optional: Execute Cleanup
|
|
191
|
+
|
|
192
|
+
If the user approves, execute the suggested actions:
|
|
193
|
+
- Use \`harmony_move_card\` to reorganize
|
|
194
|
+
- Use \`harmony_update_card\` to add missing info
|
|
195
|
+
- Use \`harmony_add_link_to_card\` to link related cards
|
|
196
|
+
`;
|
|
109
197
|
function ensureDir(dirPath) {
|
|
110
198
|
if (!existsSync(dirPath)) {
|
|
111
199
|
mkdirSync(dirPath, { recursive: true });
|
|
@@ -119,6 +207,28 @@ function writeFileIfNotExists(filePath, content, force) {
|
|
|
119
207
|
writeFileSync(filePath, content, "utf-8");
|
|
120
208
|
return { created: true, skipped: false };
|
|
121
209
|
}
|
|
210
|
+
var GLOBAL_SKILLS_DIR = join(homedir(), ".agents", "skills");
|
|
211
|
+
function pathExists(filePath) {
|
|
212
|
+
try {
|
|
213
|
+
lstatSync(filePath);
|
|
214
|
+
return true;
|
|
215
|
+
} catch {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function createSymlink(target, linkPath, force) {
|
|
220
|
+
if (pathExists(linkPath)) {
|
|
221
|
+
if (!force) {
|
|
222
|
+
return { created: false, skipped: true };
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
unlinkSync(linkPath);
|
|
226
|
+
} catch {}
|
|
227
|
+
}
|
|
228
|
+
ensureDir(dirname(linkPath));
|
|
229
|
+
symlinkSync(target, linkPath);
|
|
230
|
+
return { created: true, skipped: false };
|
|
231
|
+
}
|
|
122
232
|
function mergeJsonFile(filePath, updates, force) {
|
|
123
233
|
if (!existsSync(filePath)) {
|
|
124
234
|
ensureDir(dirname(filePath));
|
|
@@ -145,25 +255,76 @@ function mergeJsonFile(filePath, updates, force) {
|
|
|
145
255
|
return { created: false, skipped: true, merged: false };
|
|
146
256
|
}
|
|
147
257
|
}
|
|
148
|
-
function initClaude(cwd, force) {
|
|
258
|
+
function initClaude(cwd, force, installMode) {
|
|
149
259
|
const result = {
|
|
150
260
|
agent: "claude",
|
|
151
261
|
filesCreated: [],
|
|
152
|
-
filesSkipped: []
|
|
262
|
+
filesSkipped: [],
|
|
263
|
+
symlinksCreated: []
|
|
153
264
|
};
|
|
154
|
-
const
|
|
155
|
-
|
|
265
|
+
const skillContent = `---
|
|
266
|
+
name: hmy
|
|
267
|
+
description: Start working on a Harmony card. Use when given a card reference like #42, UUID, or card name to implement.
|
|
156
268
|
argument-hint: <card-reference>
|
|
157
269
|
---
|
|
158
270
|
|
|
159
271
|
${HARMONY_WORKFLOW_PROMPT.replace("Your agent identifier", "claude-code").replace("Your agent name", "Claude Code")}
|
|
160
272
|
`;
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
273
|
+
const standupContent = `---
|
|
274
|
+
name: hmy-standup
|
|
275
|
+
description: Generate a daily standup summary. Use when asked for project status, daily update, or standup report.
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
${HARMONY_STANDUP_PROMPT}
|
|
279
|
+
`;
|
|
280
|
+
const cleanupContent = `---
|
|
281
|
+
name: hmy-cleanup
|
|
282
|
+
description: Analyze board for stale cards and suggest cleanup. Use when asked to clean up, audit, or organize the board.
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
${HARMONY_CLEANUP_PROMPT}
|
|
286
|
+
`;
|
|
287
|
+
if (installMode === "global") {
|
|
288
|
+
const skills = [
|
|
289
|
+
{ name: "hmy", content: skillContent },
|
|
290
|
+
{ name: "hmy-standup", content: standupContent },
|
|
291
|
+
{ name: "hmy-cleanup", content: cleanupContent }
|
|
292
|
+
];
|
|
293
|
+
for (const skill of skills) {
|
|
294
|
+
const centralPath = join(GLOBAL_SKILLS_DIR, skill.name, "SKILL.md");
|
|
295
|
+
const { created, skipped } = writeFileIfNotExists(centralPath, skill.content, force);
|
|
296
|
+
if (created)
|
|
297
|
+
result.filesCreated.push(centralPath);
|
|
298
|
+
if (skipped)
|
|
299
|
+
result.filesSkipped.push(centralPath);
|
|
300
|
+
const symlinkPath = join(homedir(), ".claude", "skills", skill.name);
|
|
301
|
+
const symlinkTarget = join(GLOBAL_SKILLS_DIR, skill.name);
|
|
302
|
+
const symlinkResult = createSymlink(symlinkTarget, symlinkPath, force);
|
|
303
|
+
if (symlinkResult.created)
|
|
304
|
+
result.symlinksCreated.push(`${symlinkPath} → ${symlinkTarget}`);
|
|
305
|
+
if (symlinkResult.skipped)
|
|
306
|
+
result.filesSkipped.push(symlinkPath);
|
|
307
|
+
}
|
|
308
|
+
} else {
|
|
309
|
+
const skillPath = join(cwd, ".claude", "skills", "hmy", "SKILL.md");
|
|
310
|
+
const { created, skipped } = writeFileIfNotExists(skillPath, skillContent, force);
|
|
311
|
+
if (created)
|
|
312
|
+
result.filesCreated.push(skillPath);
|
|
313
|
+
if (skipped)
|
|
314
|
+
result.filesSkipped.push(skillPath);
|
|
315
|
+
const standupPath = join(cwd, ".claude", "skills", "hmy-standup", "SKILL.md");
|
|
316
|
+
const standupResult = writeFileIfNotExists(standupPath, standupContent, force);
|
|
317
|
+
if (standupResult.created)
|
|
318
|
+
result.filesCreated.push(standupPath);
|
|
319
|
+
if (standupResult.skipped)
|
|
320
|
+
result.filesSkipped.push(standupPath);
|
|
321
|
+
const cleanupPath = join(cwd, ".claude", "skills", "hmy-cleanup", "SKILL.md");
|
|
322
|
+
const cleanupResult = writeFileIfNotExists(cleanupPath, cleanupContent, force);
|
|
323
|
+
if (cleanupResult.created)
|
|
324
|
+
result.filesCreated.push(cleanupPath);
|
|
325
|
+
if (cleanupResult.skipped)
|
|
326
|
+
result.filesSkipped.push(cleanupPath);
|
|
327
|
+
}
|
|
167
328
|
const globalConfigPath = join(homedir(), ".claude", "settings.json");
|
|
168
329
|
const mcpConfig = {
|
|
169
330
|
mcpServers: {
|
|
@@ -181,11 +342,12 @@ ${HARMONY_WORKFLOW_PROMPT.replace("Your agent identifier", "claude-code").replac
|
|
|
181
342
|
}
|
|
182
343
|
return result;
|
|
183
344
|
}
|
|
184
|
-
function initCodex(cwd, force) {
|
|
345
|
+
function initCodex(cwd, force, installMode) {
|
|
185
346
|
const result = {
|
|
186
347
|
agent: "codex",
|
|
187
348
|
filesCreated: [],
|
|
188
|
-
filesSkipped: []
|
|
349
|
+
filesSkipped: [],
|
|
350
|
+
symlinksCreated: []
|
|
189
351
|
};
|
|
190
352
|
const agentsContent = `# Harmony Integration
|
|
191
353
|
|
|
@@ -213,12 +375,6 @@ When given a card reference (e.g., #42 or a card name), follow this workflow:
|
|
|
213
375
|
- \`harmony_get_board\` - Get board state
|
|
214
376
|
- \`harmony_generate_prompt\` - Get role-based guidance and focus areas for the card
|
|
215
377
|
`;
|
|
216
|
-
const agentsPath = join(cwd, "AGENTS.md");
|
|
217
|
-
const { created: agentsCreated, skipped: agentsSkipped } = writeFileIfNotExists(agentsPath, agentsContent, force);
|
|
218
|
-
if (agentsCreated)
|
|
219
|
-
result.filesCreated.push(agentsPath);
|
|
220
|
-
if (agentsSkipped)
|
|
221
|
-
result.filesSkipped.push(agentsPath);
|
|
222
378
|
const promptContent = `---
|
|
223
379
|
name: hmy
|
|
224
380
|
description: Start working on a Harmony card
|
|
@@ -230,13 +386,33 @@ arguments:
|
|
|
230
386
|
|
|
231
387
|
${HARMONY_WORKFLOW_PROMPT.replace("$ARGUMENTS", "{{card}}").replace("Your agent identifier", "codex").replace("Your agent name", "OpenAI Codex")}
|
|
232
388
|
`;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
389
|
+
if (installMode === "global") {
|
|
390
|
+
const centralPromptPath = join(GLOBAL_SKILLS_DIR, "codex", "hmy.md");
|
|
391
|
+
const { created, skipped } = writeFileIfNotExists(centralPromptPath, promptContent, force);
|
|
392
|
+
if (created)
|
|
393
|
+
result.filesCreated.push(centralPromptPath);
|
|
394
|
+
if (skipped)
|
|
395
|
+
result.filesSkipped.push(centralPromptPath);
|
|
396
|
+
const symlinkPath = join(homedir(), ".codex", "prompts", "hmy.md");
|
|
397
|
+
const symlinkResult = createSymlink(centralPromptPath, symlinkPath, force);
|
|
398
|
+
if (symlinkResult.created)
|
|
399
|
+
result.symlinksCreated.push(`${symlinkPath} → ${centralPromptPath}`);
|
|
400
|
+
if (symlinkResult.skipped)
|
|
401
|
+
result.filesSkipped.push(symlinkPath);
|
|
402
|
+
} else {
|
|
403
|
+
const promptPath = join(homedir(), ".codex", "prompts", "hmy.md");
|
|
404
|
+
const { created, skipped } = writeFileIfNotExists(promptPath, promptContent, force);
|
|
405
|
+
if (created)
|
|
406
|
+
result.filesCreated.push(promptPath);
|
|
407
|
+
if (skipped)
|
|
408
|
+
result.filesSkipped.push(promptPath);
|
|
409
|
+
}
|
|
410
|
+
const agentsPath = join(cwd, "AGENTS.md");
|
|
411
|
+
const { created: agentsCreated, skipped: agentsSkipped } = writeFileIfNotExists(agentsPath, agentsContent, force);
|
|
412
|
+
if (agentsCreated)
|
|
413
|
+
result.filesCreated.push(agentsPath);
|
|
414
|
+
if (agentsSkipped)
|
|
415
|
+
result.filesSkipped.push(agentsPath);
|
|
240
416
|
const configPath = join(homedir(), ".codex", "config.toml");
|
|
241
417
|
const mcpConfigSection = `
|
|
242
418
|
# Harmony MCP Server
|
|
@@ -266,12 +442,26 @@ args = ["serve"]
|
|
|
266
442
|
}
|
|
267
443
|
return result;
|
|
268
444
|
}
|
|
269
|
-
function initCursor(cwd, force) {
|
|
445
|
+
function initCursor(cwd, force, installMode) {
|
|
270
446
|
const result = {
|
|
271
447
|
agent: "cursor",
|
|
272
448
|
filesCreated: [],
|
|
273
|
-
filesSkipped: []
|
|
449
|
+
filesSkipped: [],
|
|
450
|
+
symlinksCreated: []
|
|
274
451
|
};
|
|
452
|
+
const ruleContent = `---
|
|
453
|
+
description: Harmony card workflow rule
|
|
454
|
+
globs:
|
|
455
|
+
- "**/*"
|
|
456
|
+
alwaysApply: false
|
|
457
|
+
---
|
|
458
|
+
|
|
459
|
+
# Harmony Integration
|
|
460
|
+
|
|
461
|
+
When the user asks you to work on a Harmony card (references like #42, card names, or UUIDs):
|
|
462
|
+
|
|
463
|
+
${HARMONY_WORKFLOW_PROMPT.replace("$ARGUMENTS", "the card reference").replace("Your agent identifier", "cursor").replace("Your agent name", "Cursor AI")}
|
|
464
|
+
`;
|
|
275
465
|
const mcpConfigPath = join(cwd, ".cursor", "mcp.json");
|
|
276
466
|
const mcpConfig = {
|
|
277
467
|
mcpServers: {
|
|
@@ -287,33 +477,47 @@ function initCursor(cwd, force) {
|
|
|
287
477
|
} else if (mcpResult.skipped) {
|
|
288
478
|
result.filesSkipped.push(mcpConfigPath);
|
|
289
479
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
480
|
+
if (installMode === "global") {
|
|
481
|
+
const centralRulePath = join(GLOBAL_SKILLS_DIR, "cursor", "harmony.mdc");
|
|
482
|
+
const { created, skipped } = writeFileIfNotExists(centralRulePath, ruleContent, force);
|
|
483
|
+
if (created)
|
|
484
|
+
result.filesCreated.push(centralRulePath);
|
|
485
|
+
if (skipped)
|
|
486
|
+
result.filesSkipped.push(centralRulePath);
|
|
487
|
+
const symlinkPath = join(homedir(), ".cursor", "rules", "harmony.mdc");
|
|
488
|
+
const symlinkResult = createSymlink(centralRulePath, symlinkPath, force);
|
|
489
|
+
if (symlinkResult.created)
|
|
490
|
+
result.symlinksCreated.push(`${symlinkPath} → ${centralRulePath}`);
|
|
491
|
+
if (symlinkResult.skipped)
|
|
492
|
+
result.filesSkipped.push(symlinkPath);
|
|
493
|
+
} else {
|
|
494
|
+
const rulePath = join(cwd, ".cursor", "rules", "harmony.mdc");
|
|
495
|
+
const { created, skipped } = writeFileIfNotExists(rulePath, ruleContent, force);
|
|
496
|
+
if (created)
|
|
497
|
+
result.filesCreated.push(rulePath);
|
|
498
|
+
if (skipped)
|
|
499
|
+
result.filesSkipped.push(rulePath);
|
|
500
|
+
}
|
|
309
501
|
return result;
|
|
310
502
|
}
|
|
311
|
-
function initWindsurf(cwd, force) {
|
|
503
|
+
function initWindsurf(cwd, force, installMode) {
|
|
312
504
|
const result = {
|
|
313
505
|
agent: "windsurf",
|
|
314
506
|
filesCreated: [],
|
|
315
|
-
filesSkipped: []
|
|
507
|
+
filesSkipped: [],
|
|
508
|
+
symlinksCreated: []
|
|
316
509
|
};
|
|
510
|
+
const ruleContent = `---
|
|
511
|
+
trigger: model_decision
|
|
512
|
+
description: Activate when user asks to work on a Harmony card (references like #42, card names, or task management)
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
# Harmony Card Workflow
|
|
516
|
+
|
|
517
|
+
When working on a Harmony card:
|
|
518
|
+
|
|
519
|
+
${HARMONY_WORKFLOW_PROMPT.replace("$ARGUMENTS", "the card reference").replace("Your agent identifier", "windsurf").replace("Your agent name", "Windsurf AI")}
|
|
520
|
+
`;
|
|
317
521
|
const globalMcpPath = join(homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
318
522
|
const mcpConfig = {
|
|
319
523
|
mcpServers: {
|
|
@@ -331,50 +535,56 @@ function initWindsurf(cwd, force) {
|
|
|
331
535
|
} else if (mcpResult.skipped) {
|
|
332
536
|
result.filesSkipped.push(globalMcpPath);
|
|
333
537
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
538
|
+
if (installMode === "global") {
|
|
539
|
+
const centralRulePath = join(GLOBAL_SKILLS_DIR, "windsurf", "harmony.md");
|
|
540
|
+
const { created, skipped } = writeFileIfNotExists(centralRulePath, ruleContent, force);
|
|
541
|
+
if (created)
|
|
542
|
+
result.filesCreated.push(centralRulePath);
|
|
543
|
+
if (skipped)
|
|
544
|
+
result.filesSkipped.push(centralRulePath);
|
|
545
|
+
const symlinkPath = join(homedir(), ".codeium", "windsurf", "rules", "harmony.md");
|
|
546
|
+
const symlinkResult = createSymlink(centralRulePath, symlinkPath, force);
|
|
547
|
+
if (symlinkResult.created)
|
|
548
|
+
result.symlinksCreated.push(`${symlinkPath} → ${centralRulePath}`);
|
|
549
|
+
if (symlinkResult.skipped)
|
|
550
|
+
result.filesSkipped.push(symlinkPath);
|
|
551
|
+
} else {
|
|
552
|
+
const rulePath = join(cwd, ".windsurf", "rules", "harmony.md");
|
|
553
|
+
const { created, skipped } = writeFileIfNotExists(rulePath, ruleContent, force);
|
|
554
|
+
if (created)
|
|
555
|
+
result.filesCreated.push(rulePath);
|
|
556
|
+
if (skipped)
|
|
557
|
+
result.filesSkipped.push(rulePath);
|
|
558
|
+
}
|
|
351
559
|
return result;
|
|
352
560
|
}
|
|
353
561
|
function initHarmony(options = {}) {
|
|
354
562
|
const cwd = options.cwd || process.cwd();
|
|
355
563
|
const force = options.force || false;
|
|
356
564
|
const agents = options.agents || ["claude", "codex", "cursor", "windsurf"];
|
|
565
|
+
const installMode = options.installMode || "local";
|
|
357
566
|
const results = [];
|
|
358
567
|
for (const agent of agents) {
|
|
359
568
|
try {
|
|
360
569
|
switch (agent) {
|
|
361
570
|
case "claude":
|
|
362
|
-
results.push(initClaude(cwd, force));
|
|
571
|
+
results.push(initClaude(cwd, force, installMode));
|
|
363
572
|
break;
|
|
364
573
|
case "codex":
|
|
365
|
-
results.push(initCodex(cwd, force));
|
|
574
|
+
results.push(initCodex(cwd, force, installMode));
|
|
366
575
|
break;
|
|
367
576
|
case "cursor":
|
|
368
|
-
results.push(initCursor(cwd, force));
|
|
577
|
+
results.push(initCursor(cwd, force, installMode));
|
|
369
578
|
break;
|
|
370
579
|
case "windsurf":
|
|
371
|
-
results.push(initWindsurf(cwd, force));
|
|
580
|
+
results.push(initWindsurf(cwd, force, installMode));
|
|
372
581
|
break;
|
|
373
582
|
default:
|
|
374
583
|
results.push({
|
|
375
584
|
agent,
|
|
376
585
|
filesCreated: [],
|
|
377
586
|
filesSkipped: [],
|
|
587
|
+
symlinksCreated: [],
|
|
378
588
|
error: `Unknown agent: ${agent}`
|
|
379
589
|
});
|
|
380
590
|
}
|
|
@@ -383,6 +593,7 @@ function initHarmony(options = {}) {
|
|
|
383
593
|
agent,
|
|
384
594
|
filesCreated: [],
|
|
385
595
|
filesSkipped: [],
|
|
596
|
+
symlinksCreated: [],
|
|
386
597
|
error: error instanceof Error ? error.message : String(error)
|
|
387
598
|
});
|
|
388
599
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harmony-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "MCP server for Harmony Kanban board - enables AI coding agents to manage your boards",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -37,20 +37,22 @@
|
|
|
37
37
|
"node": ">=18.0.0"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
|
-
"build": "bun build src/index.ts src/cli.ts
|
|
41
|
-
"build:bun": "bun build src/index.ts src/http.ts src/cli.ts
|
|
40
|
+
"build": "bun build src/index.ts src/cli.ts --outdir dist --target node",
|
|
41
|
+
"build:bun": "bun build src/index.ts src/http.ts src/cli.ts --outdir dist --target bun",
|
|
42
42
|
"dev": "bun --watch src/index.ts",
|
|
43
43
|
"typecheck": "tsc --noEmit",
|
|
44
44
|
"prepublishOnly": "bun run build"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
47
|
+
"@clack/prompts": "^0.11.0",
|
|
48
|
+
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
49
|
+
"commander": "^14.0.2",
|
|
50
|
+
"hono": "^4.11.5",
|
|
51
|
+
"picocolors": "^1.1.1",
|
|
52
|
+
"zod": "^4.3.6"
|
|
51
53
|
},
|
|
52
54
|
"devDependencies": {
|
|
53
|
-
"@types/node": "^
|
|
54
|
-
"typescript": "^5.
|
|
55
|
+
"@types/node": "^25.0.10",
|
|
56
|
+
"typescript": "^5.9.3"
|
|
55
57
|
}
|
|
56
58
|
}
|