@gethmy/mcp 2.9.9 → 2.10.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 +2 -1
- package/dist/cli.js +35 -10
- package/dist/index.js +34 -10
- package/dist/lib/api-client.js +0 -6
- package/package.json +1 -1
- package/src/api-client.ts +0 -37
- package/src/server.ts +49 -6
- package/src/tui/setup.ts +1 -0
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Enables AI coding agents (Claude Code, OpenAI Codex, Cursor) to interact with yo
|
|
|
5
5
|
|
|
6
6
|
## Features
|
|
7
7
|
|
|
8
|
-
- **
|
|
8
|
+
- **71 MCP Tools** for full board control, knowledge graph, and workflow plans
|
|
9
9
|
- **7 Global Skills** — `/hmy`, `/hmy-plan`, `/hmy-cleanup`, `/hmy-standup`, `/hmy-memory-prune`, `/hmy-upgrade`, `/hmy-review`, served from the DB-backed [skill hub](../../docs/skills.md) with auto-update and admin-managed versioning
|
|
10
10
|
- **Knowledge Graph Memory** — Phase 1 surface: hybrid retrieval (vector + lexical + RRF), session-scoped working memory, activity feed. See [docs/memory.md](../../docs/memory.md)
|
|
11
11
|
- **GSD Workflow Plans** - plan/execute/verify/done lifecycle with auto card creation
|
|
@@ -255,6 +255,7 @@ Every skill ships with an `hmy-update-check` preamble that fires on invocation.
|
|
|
255
255
|
- `harmony_list_projects` - List projects
|
|
256
256
|
- `harmony_get_board` - Get board state (supports pagination via `limit`/`offset`, `summary` mode, `columnId` filter, `includeArchived`)
|
|
257
257
|
- `harmony_get_workspace_members` - Get team members
|
|
258
|
+
- `harmony_list_agents` - List a workspace's virtual agents (daemons); use the id with `harmony_assign_card` (`agentId`)
|
|
258
259
|
- `harmony_set_workspace_context` - Set active workspace
|
|
259
260
|
- `harmony_set_project_context` - Set active project
|
|
260
261
|
- `harmony_get_context` - Get current context
|
package/dist/cli.js
CHANGED
|
@@ -1919,15 +1919,9 @@ class HarmonyApiClient {
|
|
|
1919
1919
|
async endAgentSession(cardId, data) {
|
|
1920
1920
|
return this.request("DELETE", `/cards/${cardId}/agent-context`, data);
|
|
1921
1921
|
}
|
|
1922
|
-
async flushActivityLog(cardId, data) {
|
|
1923
|
-
return this.request("POST", `/cards/${cardId}/agent-activity-log`, data);
|
|
1924
|
-
}
|
|
1925
1922
|
async appendAgentRunEvents(cardId, data) {
|
|
1926
1923
|
return this.request("POST", `/cards/${cardId}/agent-run-events`, data);
|
|
1927
1924
|
}
|
|
1928
|
-
async getActivityLog(cardId, sessionId) {
|
|
1929
|
-
return this.request("GET", `/cards/${cardId}/agent-activity-log?sessionId=${sessionId}`);
|
|
1930
|
-
}
|
|
1931
1925
|
async getPendingUserMessages(cardId, sessionId, sinceSeq) {
|
|
1932
1926
|
return this.request("GET", `/cards/${cardId}/agent-messages?sessionId=${sessionId}&sinceSeq=${sinceSeq}`);
|
|
1933
1927
|
}
|
|
@@ -3646,7 +3640,7 @@ var TOOLS = {
|
|
|
3646
3640
|
}
|
|
3647
3641
|
},
|
|
3648
3642
|
harmony_assign_card: {
|
|
3649
|
-
description: "Assign a card to a team member",
|
|
3643
|
+
description: "Assign a card to a team member (human) or a virtual agent (e.g. the autonomous agent daemon). Pass at most one of assigneeId / agentId — a card is assigned to a human OR an agent, never both. Use harmony_list_agents to find a virtual agent's id.",
|
|
3650
3644
|
inputSchema: {
|
|
3651
3645
|
type: "object",
|
|
3652
3646
|
properties: {
|
|
@@ -3654,7 +3648,12 @@ var TOOLS = {
|
|
|
3654
3648
|
assigneeId: {
|
|
3655
3649
|
type: "string",
|
|
3656
3650
|
nullable: true,
|
|
3657
|
-
description: "
|
|
3651
|
+
description: "Human user ID (null to unassign). Mutually exclusive with agentId."
|
|
3652
|
+
},
|
|
3653
|
+
agentId: {
|
|
3654
|
+
type: "string",
|
|
3655
|
+
nullable: true,
|
|
3656
|
+
description: "Virtual agent ID from harmony_list_agents (null to unassign). Setting it hands the card to the agent daemon. Mutually exclusive with assigneeId."
|
|
3658
3657
|
}
|
|
3659
3658
|
},
|
|
3660
3659
|
required: ["cardId"]
|
|
@@ -4083,6 +4082,18 @@ var TOOLS = {
|
|
|
4083
4082
|
}
|
|
4084
4083
|
}
|
|
4085
4084
|
},
|
|
4085
|
+
harmony_list_agents: {
|
|
4086
|
+
description: "List a workspace's virtual agents (autonomous agent daemons registered to the board). Returns each agent's id, identifier, name and last-seen time. Use the returned id with harmony_assign_card (agentId) to hand a card to the daemon.",
|
|
4087
|
+
inputSchema: {
|
|
4088
|
+
type: "object",
|
|
4089
|
+
properties: {
|
|
4090
|
+
workspaceId: {
|
|
4091
|
+
type: "string",
|
|
4092
|
+
description: "Workspace ID (optional if context set)"
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
}
|
|
4096
|
+
},
|
|
4086
4097
|
harmony_set_workspace_context: {
|
|
4087
4098
|
description: "Set the active workspace context for subsequent operations",
|
|
4088
4099
|
inputSchema: {
|
|
@@ -5203,8 +5214,16 @@ async function handleToolCall(name, args, deps) {
|
|
|
5203
5214
|
}
|
|
5204
5215
|
case "harmony_assign_card": {
|
|
5205
5216
|
const cardId = z.string().uuid().parse(args.cardId);
|
|
5206
|
-
|
|
5207
|
-
|
|
5217
|
+
if (args.assigneeId != null && args.agentId != null) {
|
|
5218
|
+
throw new Error("Pass at most one of assigneeId / agentId — a card is assigned to a human OR an agent, never both.");
|
|
5219
|
+
}
|
|
5220
|
+
const updates = {};
|
|
5221
|
+
if (args.agentId !== undefined) {
|
|
5222
|
+
updates.assignedAgentId = args.agentId ? z.string().uuid().parse(args.agentId) : null;
|
|
5223
|
+
} else {
|
|
5224
|
+
updates.assigneeId = args.assigneeId ? z.string().uuid().parse(args.assigneeId) : null;
|
|
5225
|
+
}
|
|
5226
|
+
const result = await client3.updateCard(cardId, updates);
|
|
5208
5227
|
return { success: true, ...result };
|
|
5209
5228
|
}
|
|
5210
5229
|
case "harmony_search_cards": {
|
|
@@ -5479,6 +5498,11 @@ async function handleToolCall(name, args, deps) {
|
|
|
5479
5498
|
const result = await client3.getWorkspaceMembers(workspaceId);
|
|
5480
5499
|
return { success: true, ...result };
|
|
5481
5500
|
}
|
|
5501
|
+
case "harmony_list_agents": {
|
|
5502
|
+
const workspaceId = getWorkspaceId();
|
|
5503
|
+
const result = await client3.listWorkspaceAgents(workspaceId);
|
|
5504
|
+
return { success: true, ...result };
|
|
5505
|
+
}
|
|
5482
5506
|
case "harmony_set_workspace_context": {
|
|
5483
5507
|
const workspaceId = z.string().uuid().parse(args.workspaceId);
|
|
5484
5508
|
deps.setActiveWorkspace(workspaceId);
|
|
@@ -7386,6 +7410,7 @@ var SAFE_HARMONY_TOOLS = [
|
|
|
7386
7410
|
"harmony_list_plans",
|
|
7387
7411
|
"harmony_get_agent_session",
|
|
7388
7412
|
"harmony_get_workspace_members",
|
|
7413
|
+
"harmony_list_agents",
|
|
7389
7414
|
"harmony_resolve_links",
|
|
7390
7415
|
"harmony_recall",
|
|
7391
7416
|
"harmony_memory_search",
|
package/dist/index.js
CHANGED
|
@@ -1914,15 +1914,9 @@ class HarmonyApiClient {
|
|
|
1914
1914
|
async endAgentSession(cardId, data) {
|
|
1915
1915
|
return this.request("DELETE", `/cards/${cardId}/agent-context`, data);
|
|
1916
1916
|
}
|
|
1917
|
-
async flushActivityLog(cardId, data) {
|
|
1918
|
-
return this.request("POST", `/cards/${cardId}/agent-activity-log`, data);
|
|
1919
|
-
}
|
|
1920
1917
|
async appendAgentRunEvents(cardId, data) {
|
|
1921
1918
|
return this.request("POST", `/cards/${cardId}/agent-run-events`, data);
|
|
1922
1919
|
}
|
|
1923
|
-
async getActivityLog(cardId, sessionId) {
|
|
1924
|
-
return this.request("GET", `/cards/${cardId}/agent-activity-log?sessionId=${sessionId}`);
|
|
1925
|
-
}
|
|
1926
1920
|
async getPendingUserMessages(cardId, sessionId, sinceSeq) {
|
|
1927
1921
|
return this.request("GET", `/cards/${cardId}/agent-messages?sessionId=${sessionId}&sinceSeq=${sinceSeq}`);
|
|
1928
1922
|
}
|
|
@@ -3641,7 +3635,7 @@ var TOOLS = {
|
|
|
3641
3635
|
}
|
|
3642
3636
|
},
|
|
3643
3637
|
harmony_assign_card: {
|
|
3644
|
-
description: "Assign a card to a team member",
|
|
3638
|
+
description: "Assign a card to a team member (human) or a virtual agent (e.g. the autonomous agent daemon). Pass at most one of assigneeId / agentId — a card is assigned to a human OR an agent, never both. Use harmony_list_agents to find a virtual agent's id.",
|
|
3645
3639
|
inputSchema: {
|
|
3646
3640
|
type: "object",
|
|
3647
3641
|
properties: {
|
|
@@ -3649,7 +3643,12 @@ var TOOLS = {
|
|
|
3649
3643
|
assigneeId: {
|
|
3650
3644
|
type: "string",
|
|
3651
3645
|
nullable: true,
|
|
3652
|
-
description: "
|
|
3646
|
+
description: "Human user ID (null to unassign). Mutually exclusive with agentId."
|
|
3647
|
+
},
|
|
3648
|
+
agentId: {
|
|
3649
|
+
type: "string",
|
|
3650
|
+
nullable: true,
|
|
3651
|
+
description: "Virtual agent ID from harmony_list_agents (null to unassign). Setting it hands the card to the agent daemon. Mutually exclusive with assigneeId."
|
|
3653
3652
|
}
|
|
3654
3653
|
},
|
|
3655
3654
|
required: ["cardId"]
|
|
@@ -4078,6 +4077,18 @@ var TOOLS = {
|
|
|
4078
4077
|
}
|
|
4079
4078
|
}
|
|
4080
4079
|
},
|
|
4080
|
+
harmony_list_agents: {
|
|
4081
|
+
description: "List a workspace's virtual agents (autonomous agent daemons registered to the board). Returns each agent's id, identifier, name and last-seen time. Use the returned id with harmony_assign_card (agentId) to hand a card to the daemon.",
|
|
4082
|
+
inputSchema: {
|
|
4083
|
+
type: "object",
|
|
4084
|
+
properties: {
|
|
4085
|
+
workspaceId: {
|
|
4086
|
+
type: "string",
|
|
4087
|
+
description: "Workspace ID (optional if context set)"
|
|
4088
|
+
}
|
|
4089
|
+
}
|
|
4090
|
+
}
|
|
4091
|
+
},
|
|
4081
4092
|
harmony_set_workspace_context: {
|
|
4082
4093
|
description: "Set the active workspace context for subsequent operations",
|
|
4083
4094
|
inputSchema: {
|
|
@@ -5198,8 +5209,16 @@ async function handleToolCall(name, args, deps) {
|
|
|
5198
5209
|
}
|
|
5199
5210
|
case "harmony_assign_card": {
|
|
5200
5211
|
const cardId = z.string().uuid().parse(args.cardId);
|
|
5201
|
-
|
|
5202
|
-
|
|
5212
|
+
if (args.assigneeId != null && args.agentId != null) {
|
|
5213
|
+
throw new Error("Pass at most one of assigneeId / agentId — a card is assigned to a human OR an agent, never both.");
|
|
5214
|
+
}
|
|
5215
|
+
const updates = {};
|
|
5216
|
+
if (args.agentId !== undefined) {
|
|
5217
|
+
updates.assignedAgentId = args.agentId ? z.string().uuid().parse(args.agentId) : null;
|
|
5218
|
+
} else {
|
|
5219
|
+
updates.assigneeId = args.assigneeId ? z.string().uuid().parse(args.assigneeId) : null;
|
|
5220
|
+
}
|
|
5221
|
+
const result = await client3.updateCard(cardId, updates);
|
|
5203
5222
|
return { success: true, ...result };
|
|
5204
5223
|
}
|
|
5205
5224
|
case "harmony_search_cards": {
|
|
@@ -5474,6 +5493,11 @@ async function handleToolCall(name, args, deps) {
|
|
|
5474
5493
|
const result = await client3.getWorkspaceMembers(workspaceId);
|
|
5475
5494
|
return { success: true, ...result };
|
|
5476
5495
|
}
|
|
5496
|
+
case "harmony_list_agents": {
|
|
5497
|
+
const workspaceId = getWorkspaceId();
|
|
5498
|
+
const result = await client3.listWorkspaceAgents(workspaceId);
|
|
5499
|
+
return { success: true, ...result };
|
|
5500
|
+
}
|
|
5477
5501
|
case "harmony_set_workspace_context": {
|
|
5478
5502
|
const workspaceId = z.string().uuid().parse(args.workspaceId);
|
|
5479
5503
|
deps.setActiveWorkspace(workspaceId);
|
package/dist/lib/api-client.js
CHANGED
|
@@ -1367,15 +1367,9 @@ class HarmonyApiClient {
|
|
|
1367
1367
|
async endAgentSession(cardId, data) {
|
|
1368
1368
|
return this.request("DELETE", `/cards/${cardId}/agent-context`, data);
|
|
1369
1369
|
}
|
|
1370
|
-
async flushActivityLog(cardId, data) {
|
|
1371
|
-
return this.request("POST", `/cards/${cardId}/agent-activity-log`, data);
|
|
1372
|
-
}
|
|
1373
1370
|
async appendAgentRunEvents(cardId, data) {
|
|
1374
1371
|
return this.request("POST", `/cards/${cardId}/agent-run-events`, data);
|
|
1375
1372
|
}
|
|
1376
|
-
async getActivityLog(cardId, sessionId) {
|
|
1377
|
-
return this.request("GET", `/cards/${cardId}/agent-activity-log?sessionId=${sessionId}`);
|
|
1378
|
-
}
|
|
1379
1373
|
async getPendingUserMessages(cardId, sessionId, sinceSeq) {
|
|
1380
1374
|
return this.request("GET", `/cards/${cardId}/agent-messages?sessionId=${sessionId}&sinceSeq=${sinceSeq}`);
|
|
1381
1375
|
}
|
package/package.json
CHANGED
package/src/api-client.ts
CHANGED
|
@@ -882,23 +882,6 @@ export class HarmonyApiClient {
|
|
|
882
882
|
return this.request("DELETE", `/cards/${cardId}/agent-context`, data);
|
|
883
883
|
}
|
|
884
884
|
|
|
885
|
-
async flushActivityLog(
|
|
886
|
-
cardId: string,
|
|
887
|
-
data: {
|
|
888
|
-
sessionId: string;
|
|
889
|
-
entries: {
|
|
890
|
-
phase?: string;
|
|
891
|
-
eventType: string;
|
|
892
|
-
toolName?: string;
|
|
893
|
-
description: string;
|
|
894
|
-
metadata?: Record<string, unknown>;
|
|
895
|
-
createdAt?: string;
|
|
896
|
-
}[];
|
|
897
|
-
},
|
|
898
|
-
): Promise<{ inserted: number }> {
|
|
899
|
-
return this.request("POST", `/cards/${cardId}/agent-activity-log`, data);
|
|
900
|
-
}
|
|
901
|
-
|
|
902
885
|
/**
|
|
903
886
|
* Append events to a run's agent_run_events stream (card #417). Send drafts in
|
|
904
887
|
* chronological order — the server's seq trigger assigns the monotonic per-run order.
|
|
@@ -913,26 +896,6 @@ export class HarmonyApiClient {
|
|
|
913
896
|
return this.request("POST", `/cards/${cardId}/agent-run-events`, data);
|
|
914
897
|
}
|
|
915
898
|
|
|
916
|
-
async getActivityLog(
|
|
917
|
-
cardId: string,
|
|
918
|
-
sessionId: string,
|
|
919
|
-
): Promise<{
|
|
920
|
-
entries: {
|
|
921
|
-
id: string;
|
|
922
|
-
phase: string | null;
|
|
923
|
-
eventType: string;
|
|
924
|
-
toolName: string | null;
|
|
925
|
-
description: string;
|
|
926
|
-
metadata: Record<string, unknown>;
|
|
927
|
-
createdAt: string;
|
|
928
|
-
}[];
|
|
929
|
-
}> {
|
|
930
|
-
return this.request(
|
|
931
|
-
"GET",
|
|
932
|
-
`/cards/${cardId}/agent-activity-log?sessionId=${sessionId}`,
|
|
933
|
-
);
|
|
934
|
-
}
|
|
935
|
-
|
|
936
899
|
/**
|
|
937
900
|
* Drain queued chat-steering messages for a run (card #417). Returns `user_message`
|
|
938
901
|
* events with `seq` greater than `sinceSeq`, oldest first, so the daemon can continue
|
package/src/server.ts
CHANGED
|
@@ -417,7 +417,8 @@ export const TOOLS = {
|
|
|
417
417
|
},
|
|
418
418
|
},
|
|
419
419
|
harmony_assign_card: {
|
|
420
|
-
description:
|
|
420
|
+
description:
|
|
421
|
+
"Assign a card to a team member (human) or a virtual agent (e.g. the autonomous agent daemon). Pass at most one of assigneeId / agentId — a card is assigned to a human OR an agent, never both. Use harmony_list_agents to find a virtual agent's id.",
|
|
421
422
|
inputSchema: {
|
|
422
423
|
type: "object",
|
|
423
424
|
properties: {
|
|
@@ -425,7 +426,14 @@ export const TOOLS = {
|
|
|
425
426
|
assigneeId: {
|
|
426
427
|
type: "string",
|
|
427
428
|
nullable: true,
|
|
428
|
-
description:
|
|
429
|
+
description:
|
|
430
|
+
"Human user ID (null to unassign). Mutually exclusive with agentId.",
|
|
431
|
+
},
|
|
432
|
+
agentId: {
|
|
433
|
+
type: "string",
|
|
434
|
+
nullable: true,
|
|
435
|
+
description:
|
|
436
|
+
"Virtual agent ID from harmony_list_agents (null to unassign). Setting it hands the card to the agent daemon. Mutually exclusive with assigneeId.",
|
|
429
437
|
},
|
|
430
438
|
},
|
|
431
439
|
required: ["cardId"],
|
|
@@ -894,6 +902,19 @@ export const TOOLS = {
|
|
|
894
902
|
},
|
|
895
903
|
},
|
|
896
904
|
},
|
|
905
|
+
harmony_list_agents: {
|
|
906
|
+
description:
|
|
907
|
+
"List a workspace's virtual agents (autonomous agent daemons registered to the board). Returns each agent's id, identifier, name and last-seen time. Use the returned id with harmony_assign_card (agentId) to hand a card to the daemon.",
|
|
908
|
+
inputSchema: {
|
|
909
|
+
type: "object",
|
|
910
|
+
properties: {
|
|
911
|
+
workspaceId: {
|
|
912
|
+
type: "string",
|
|
913
|
+
description: "Workspace ID (optional if context set)",
|
|
914
|
+
},
|
|
915
|
+
},
|
|
916
|
+
},
|
|
917
|
+
},
|
|
897
918
|
harmony_set_workspace_context: {
|
|
898
919
|
description: "Set the active workspace context for subsequent operations",
|
|
899
920
|
inputSchema: {
|
|
@@ -2261,10 +2282,26 @@ async function handleToolCall(
|
|
|
2261
2282
|
|
|
2262
2283
|
case "harmony_assign_card": {
|
|
2263
2284
|
const cardId = z.string().uuid().parse(args.cardId);
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2285
|
+
if (args.assigneeId != null && args.agentId != null) {
|
|
2286
|
+
throw new Error(
|
|
2287
|
+
"Pass at most one of assigneeId / agentId — a card is assigned to a human OR an agent, never both.",
|
|
2288
|
+
);
|
|
2289
|
+
}
|
|
2290
|
+
// The backend nulls the opposite field, so only send the side being set.
|
|
2291
|
+
const updates: {
|
|
2292
|
+
assigneeId?: string | null;
|
|
2293
|
+
assignedAgentId?: string | null;
|
|
2294
|
+
} = {};
|
|
2295
|
+
if (args.agentId !== undefined) {
|
|
2296
|
+
updates.assignedAgentId = args.agentId
|
|
2297
|
+
? z.string().uuid().parse(args.agentId)
|
|
2298
|
+
: null;
|
|
2299
|
+
} else {
|
|
2300
|
+
updates.assigneeId = args.assigneeId
|
|
2301
|
+
? z.string().uuid().parse(args.assigneeId)
|
|
2302
|
+
: null;
|
|
2303
|
+
}
|
|
2304
|
+
const result = await client.updateCard(cardId, updates);
|
|
2268
2305
|
return { success: true, ...result };
|
|
2269
2306
|
}
|
|
2270
2307
|
|
|
@@ -2652,6 +2689,12 @@ async function handleToolCall(
|
|
|
2652
2689
|
return { success: true, ...result };
|
|
2653
2690
|
}
|
|
2654
2691
|
|
|
2692
|
+
case "harmony_list_agents": {
|
|
2693
|
+
const workspaceId = getWorkspaceId();
|
|
2694
|
+
const result = await client.listWorkspaceAgents(workspaceId);
|
|
2695
|
+
return { success: true, ...result };
|
|
2696
|
+
}
|
|
2697
|
+
|
|
2655
2698
|
case "harmony_set_workspace_context": {
|
|
2656
2699
|
const workspaceId = z.string().uuid().parse(args.workspaceId);
|
|
2657
2700
|
deps.setActiveWorkspace(workspaceId);
|