harmony-mcp 1.3.1 → 1.3.3

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/index.js CHANGED
@@ -23013,7 +23013,8 @@ function loadConfig() {
23013
23013
  apiKey: null,
23014
23014
  apiUrl: DEFAULT_API_URL,
23015
23015
  activeWorkspaceId: null,
23016
- activeProjectId: null
23016
+ activeProjectId: null,
23017
+ userEmail: null
23017
23018
  };
23018
23019
  }
23019
23020
  try {
@@ -23023,14 +23024,16 @@ function loadConfig() {
23023
23024
  apiKey: config2.apiKey || null,
23024
23025
  apiUrl: config2.apiUrl || DEFAULT_API_URL,
23025
23026
  activeWorkspaceId: config2.activeWorkspaceId || null,
23026
- activeProjectId: config2.activeProjectId || null
23027
+ activeProjectId: config2.activeProjectId || null,
23028
+ userEmail: config2.userEmail || null
23027
23029
  };
23028
23030
  } catch {
23029
23031
  return {
23030
23032
  apiKey: null,
23031
23033
  apiUrl: DEFAULT_API_URL,
23032
23034
  activeWorkspaceId: null,
23033
- activeProjectId: null
23035
+ activeProjectId: null,
23036
+ userEmail: null
23034
23037
  };
23035
23038
  }
23036
23039
  }
@@ -23089,6 +23092,13 @@ function getApiUrl() {
23089
23092
  const config2 = loadConfig();
23090
23093
  return config2.apiUrl;
23091
23094
  }
23095
+ function getUserEmail() {
23096
+ const config2 = loadConfig();
23097
+ return config2.userEmail;
23098
+ }
23099
+ function setUserEmail(email2) {
23100
+ saveConfig({ userEmail: email2 });
23101
+ }
23092
23102
  function setActiveWorkspace(workspaceId, options) {
23093
23103
  if (options?.local) {
23094
23104
  saveLocalConfig({ workspaceId }, options.cwd);
@@ -23956,23 +23966,11 @@ var RESOURCES = [
23956
23966
  mimeType: "application/json"
23957
23967
  }
23958
23968
  ];
23959
- var PROMPTS = {
23960
- harmony_daily_standup: {
23961
- name: "Daily Standup Summary",
23962
- description: "Generate a summary of recent activity and current work items",
23963
- arguments: [{ name: "projectId", description: "Project to summarize", required: false }]
23964
- },
23965
- harmony_board_cleanup: {
23966
- name: "Board Cleanup Suggestions",
23967
- description: "Identify stale cards and suggest cleanup actions",
23968
- arguments: []
23969
- }
23970
- };
23971
23969
 
23972
23970
  class HarmonyMCPServer {
23973
23971
  server;
23974
23972
  constructor() {
23975
- this.server = new Server({ name: "harmony-mcp", version: "1.0.0" }, { capabilities: { tools: {}, resources: {}, prompts: {} } });
23973
+ this.server = new Server({ name: "harmony-mcp", version: "1.0.0" }, { capabilities: { tools: {}, resources: {} } });
23976
23974
  this.setupHandlers();
23977
23975
  }
23978
23976
  setupHandlers() {
@@ -24020,58 +24018,6 @@ class HarmonyMCPServer {
24020
24018
  }
24021
24019
  throw new Error(`Unknown resource: ${uri}`);
24022
24020
  });
24023
- this.server.setRequestHandler(ListPromptsRequestSchema, async () => ({
24024
- prompts: Object.entries(PROMPTS).map(([name, prompt]) => ({
24025
- name,
24026
- description: prompt.description,
24027
- arguments: prompt.arguments
24028
- }))
24029
- }));
24030
- this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
24031
- const { name, arguments: args } = request.params;
24032
- if (name === "harmony_daily_standup") {
24033
- const projectId = args?.projectId || getActiveProjectId();
24034
- if (!projectId) {
24035
- return {
24036
- messages: [
24037
- {
24038
- role: "user",
24039
- content: { type: "text", text: "No project context. Please set a project first using harmony_set_project_context." }
24040
- }
24041
- ]
24042
- };
24043
- }
24044
- try {
24045
- const client2 = getClient();
24046
- const board = await client2.getBoard(projectId);
24047
- return {
24048
- messages: [
24049
- {
24050
- role: "user",
24051
- content: {
24052
- type: "text",
24053
- text: `Generate a daily standup summary for this Harmony project board:
24054
-
24055
- ${JSON.stringify(board, null, 2)}
24056
-
24057
- Include: cards moved recently, current in-progress items, blocked or high-priority items, and upcoming due dates.`
24058
- }
24059
- }
24060
- ]
24061
- };
24062
- } catch (error2) {
24063
- return {
24064
- messages: [
24065
- {
24066
- role: "user",
24067
- content: { type: "text", text: `Error: ${error2 instanceof Error ? error2.message : String(error2)}` }
24068
- }
24069
- ]
24070
- };
24071
- }
24072
- }
24073
- throw new Error(`Unknown prompt: ${name}`);
24074
- });
24075
24021
  }
24076
24022
  async handleToolCall(name, args) {
24077
24023
  if (!isConfigured()) {
@@ -24283,6 +24229,21 @@ Include: cards moved recently, current in-progress items, blocked or high-priori
24283
24229
  const cardId = exports_external.string().uuid().parse(args.cardId);
24284
24230
  const agentIdentifier = exports_external.string().min(1).parse(args.agentIdentifier);
24285
24231
  const agentName = exports_external.string().min(1).parse(args.agentName);
24232
+ let assignedTo = null;
24233
+ const userEmail = getUserEmail();
24234
+ if (userEmail) {
24235
+ try {
24236
+ const workspaceId = getActiveWorkspaceId();
24237
+ if (workspaceId) {
24238
+ const { members } = await client2.getWorkspaceMembers(workspaceId);
24239
+ const user = members.find((m) => m.email === userEmail);
24240
+ if (user) {
24241
+ await client2.updateCard(cardId, { assigneeId: user.id });
24242
+ assignedTo = user.email;
24243
+ }
24244
+ }
24245
+ } catch {}
24246
+ }
24286
24247
  const result = await client2.startAgentSession(cardId, {
24287
24248
  agentIdentifier,
24288
24249
  agentName,
@@ -24290,7 +24251,7 @@ Include: cards moved recently, current in-progress items, blocked or high-priori
24290
24251
  currentTask: args.currentTask,
24291
24252
  estimatedMinutesRemaining: args.estimatedMinutesRemaining
24292
24253
  });
24293
- return { success: true, ...result };
24254
+ return { success: true, assignedTo, ...result };
24294
24255
  }
24295
24256
  case "harmony_update_agent_progress": {
24296
24257
  const cardId = exports_external.string().uuid().parse(args.cardId);
package/dist/init.js CHANGED
@@ -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 });
@@ -164,6 +252,30 @@ ${HARMONY_WORKFLOW_PROMPT.replace("Your agent identifier", "claude-code").replac
164
252
  result.filesCreated.push(commandPath);
165
253
  if (skipped)
166
254
  result.filesSkipped.push(commandPath);
255
+ const standupContent = `---
256
+ description: Generate a daily standup summary for the current Harmony project
257
+ ---
258
+
259
+ ${HARMONY_STANDUP_PROMPT}
260
+ `;
261
+ const standupPath = join(cwd, ".claude", "commands", "hmy-standup.md");
262
+ const standupResult = writeFileIfNotExists(standupPath, standupContent, force);
263
+ if (standupResult.created)
264
+ result.filesCreated.push(standupPath);
265
+ if (standupResult.skipped)
266
+ result.filesSkipped.push(standupPath);
267
+ const cleanupContent = `---
268
+ description: Analyze the Harmony board and suggest cleanup actions for stale cards
269
+ ---
270
+
271
+ ${HARMONY_CLEANUP_PROMPT}
272
+ `;
273
+ const cleanupPath = join(cwd, ".claude", "commands", "hmy-cleanup.md");
274
+ const cleanupResult = writeFileIfNotExists(cleanupPath, cleanupContent, force);
275
+ if (cleanupResult.created)
276
+ result.filesCreated.push(cleanupPath);
277
+ if (cleanupResult.skipped)
278
+ result.filesSkipped.push(cleanupPath);
167
279
  const globalConfigPath = join(homedir(), ".claude", "settings.json");
168
280
  const mcpConfig = {
169
281
  mcpServers: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harmony-mcp",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
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",
@@ -44,9 +44,11 @@
44
44
  "prepublishOnly": "bun run build"
45
45
  },
46
46
  "dependencies": {
47
+ "@clack/prompts": "^0.9.1",
47
48
  "@modelcontextprotocol/sdk": "^1.0.0",
48
49
  "commander": "^12.0.0",
49
50
  "hono": "^4.0.0",
51
+ "picocolors": "^1.1.1",
50
52
  "zod": "^3.23.0"
51
53
  },
52
54
  "devDependencies": {