@gethmy/mcp 2.26.0 → 3.1.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 -2
- package/dist/cli.js +7 -20
- package/dist/index.js +7 -20
- package/dist/lib/api-client.js +2 -3
- package/package.json +2 -2
- package/src/api-client.ts +19 -18
- package/src/server.ts +8 -17
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Claude Code, OpenAI Codex, Cursor, and any MCP client claim cards, report progre
|
|
|
5
5
|
|
|
6
6
|
## Features
|
|
7
7
|
|
|
8
|
-
- **
|
|
8
|
+
- **77 MCP Tools** for full board control, knowledge graph, and workflow plans
|
|
9
9
|
- **Global Skills** — installable in one command, 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
|
|
@@ -89,7 +89,7 @@ If you prefer to configure manually (e.g., in Claude.ai's UI):
|
|
|
89
89
|
1. Get an API key from [Harmony](https://gethmy.com/user/keys)
|
|
90
90
|
2. In Claude.ai, add a remote MCP server with URL `https://mcp.gethmy.com/mcp`
|
|
91
91
|
3. Set the Authorization header to `Bearer hmy_your_key_here`
|
|
92
|
-
4. All
|
|
92
|
+
4. All 77 Harmony tools become available in your conversation
|
|
93
93
|
|
|
94
94
|
**Session management** is automatic - sessions have a 1-hour TTL and are created/renewed transparently.
|
|
95
95
|
|
package/dist/cli.js
CHANGED
|
@@ -1598,6 +1598,8 @@ function referencedGateMetrics(def) {
|
|
|
1598
1598
|
}
|
|
1599
1599
|
return out;
|
|
1600
1600
|
}
|
|
1601
|
+
// ../harmony-shared/dist/realtimeChannel.js
|
|
1602
|
+
var inFlightDetach = new WeakMap;
|
|
1601
1603
|
// ../harmony-shared/dist/reviewTools.js
|
|
1602
1604
|
var REVIEW_DISALLOWED_TOOLS = [
|
|
1603
1605
|
...STAGE_DAEMON_OWNED_TOOLS,
|
|
@@ -2053,9 +2055,6 @@ class HarmonyApiClient {
|
|
|
2053
2055
|
expires_at: expiresAt
|
|
2054
2056
|
});
|
|
2055
2057
|
}
|
|
2056
|
-
async classifyCard(cardId) {
|
|
2057
|
-
return this.request("POST", `/cards/${cardId}/classify`);
|
|
2058
|
-
}
|
|
2059
2058
|
async createColumn(projectId, name) {
|
|
2060
2059
|
return this.request("POST", "/columns", { projectId, name });
|
|
2061
2060
|
}
|
|
@@ -3780,7 +3779,8 @@ function warnDeprecatedTool(oldName) {
|
|
|
3780
3779
|
}
|
|
3781
3780
|
var DEPRECATED_REMOVED_TOOLS = {
|
|
3782
3781
|
harmony_run_playbook: "Playbooks are stage models run by the board and agent daemon as a card moves through their stages — there is no server-side macro to trigger. This tool no longer runs anything.",
|
|
3783
|
-
harmony_save_card_as_playbook: "The steps_version=1 automation macro was removed. Build a stage playbook with harmony_create_playbook instead."
|
|
3782
|
+
harmony_save_card_as_playbook: "The steps_version=1 automation macro was removed. Build a stage playbook with harmony_create_playbook instead.",
|
|
3783
|
+
harmony_classify_card: "Card classification was retired. Run sizing happens at daemon pickup and is run-scoped, and the cards.intent / complexity_score / model_tier / classified_at columns it wrote have been dropped. The feature/bug/idea label — the only output anything read — is applied at card creation, so there is nothing left to trigger."
|
|
3784
3784
|
};
|
|
3785
3785
|
var _warnedRemovedTools = new Set;
|
|
3786
3786
|
function deprecatedRemovedToolResult(name) {
|
|
@@ -4488,16 +4488,6 @@ var TOOLS = {
|
|
|
4488
4488
|
required: ["target", "storagePath"]
|
|
4489
4489
|
}
|
|
4490
4490
|
},
|
|
4491
|
-
harmony_classify_card: {
|
|
4492
|
-
description: "DEPRECATED — run sizing now happens at daemon pickup and is run-scoped, so nothing reads `model_tier`, `intent` or `complexity_score` any more; this tool still writes them, but only the type label has an effect. Prefer letting card creation apply the type label. Sets `intent` (plan/think/implement/review), `complexity_score` (0-10), `model_tier` (simple/advanced/research), stamps `classified_at`, and applies the type label (feature/bug/idea). Idempotent; never touches the user-owned `model_override`.",
|
|
4493
|
-
inputSchema: {
|
|
4494
|
-
type: "object",
|
|
4495
|
-
properties: {
|
|
4496
|
-
cardId: { type: "string", description: "Card UUID" }
|
|
4497
|
-
},
|
|
4498
|
-
required: ["cardId"]
|
|
4499
|
-
}
|
|
4500
|
-
},
|
|
4501
4491
|
harmony_share_artifact: {
|
|
4502
4492
|
description: "Create a public, unauthenticated share link for a hosted artifact. Anyone with the link can view the rendered HTML without a Harmony account. Returns the share token and the full public URL. Only needed for a recipient OUTSIDE the workspace — for a teammate, hand over the `app_url` the upload already returned instead of exposing the document publicly.",
|
|
4503
4493
|
inputSchema: {
|
|
@@ -5563,7 +5553,7 @@ var TOOLS = {
|
|
|
5563
5553
|
},
|
|
5564
5554
|
autoBind: {
|
|
5565
5555
|
type: "object",
|
|
5566
|
-
description: "Auto-bind rule: {priority?: number, mode?: 'all'|'any', when: [{path, op, value}]}. Conditions are evaluated against the card's labels (lowercased)
|
|
5556
|
+
description: "Auto-bind rule: {priority?: number, mode?: 'all'|'any', when: [{path, op, value}]}. Conditions are evaluated against the card's labels (lowercased) and priority with the gate operators eq/neq/gte/gt/lte/lt/contains/exists; 'contains' on labels is membership. `intent` and `complexity_score` are NOT addressable — run sizing is run-scoped and those card columns were dropped, so a rule naming either fails closed and never binds. Stored even while triggerType is 'manual', so a rule can be armed later without re-authoring it."
|
|
5567
5557
|
},
|
|
5568
5558
|
catalogId: {
|
|
5569
5559
|
type: "string",
|
|
@@ -6369,11 +6359,8 @@ ${list}
|
|
|
6369
6359
|
const result = await client3.addExternalLink(cardId, url, title);
|
|
6370
6360
|
return { success: true, ...result };
|
|
6371
6361
|
}
|
|
6372
|
-
case "harmony_classify_card":
|
|
6373
|
-
|
|
6374
|
-
const result = await client3.classifyCard(cardId);
|
|
6375
|
-
return result;
|
|
6376
|
-
}
|
|
6362
|
+
case "harmony_classify_card":
|
|
6363
|
+
return deprecatedRemovedToolResult("harmony_classify_card");
|
|
6377
6364
|
case "harmony_create_subtask": {
|
|
6378
6365
|
const cardId = z.string().uuid().parse(args.cardId);
|
|
6379
6366
|
const title = z.string().min(1).max(500).parse(args.title);
|
package/dist/index.js
CHANGED
|
@@ -1593,6 +1593,8 @@ function referencedGateMetrics(def) {
|
|
|
1593
1593
|
}
|
|
1594
1594
|
return out;
|
|
1595
1595
|
}
|
|
1596
|
+
// ../harmony-shared/dist/realtimeChannel.js
|
|
1597
|
+
var inFlightDetach = new WeakMap;
|
|
1596
1598
|
// ../harmony-shared/dist/reviewTools.js
|
|
1597
1599
|
var REVIEW_DISALLOWED_TOOLS = [
|
|
1598
1600
|
...STAGE_DAEMON_OWNED_TOOLS,
|
|
@@ -2048,9 +2050,6 @@ class HarmonyApiClient {
|
|
|
2048
2050
|
expires_at: expiresAt
|
|
2049
2051
|
});
|
|
2050
2052
|
}
|
|
2051
|
-
async classifyCard(cardId) {
|
|
2052
|
-
return this.request("POST", `/cards/${cardId}/classify`);
|
|
2053
|
-
}
|
|
2054
2053
|
async createColumn(projectId, name) {
|
|
2055
2054
|
return this.request("POST", "/columns", { projectId, name });
|
|
2056
2055
|
}
|
|
@@ -3775,7 +3774,8 @@ function warnDeprecatedTool(oldName) {
|
|
|
3775
3774
|
}
|
|
3776
3775
|
var DEPRECATED_REMOVED_TOOLS = {
|
|
3777
3776
|
harmony_run_playbook: "Playbooks are stage models run by the board and agent daemon as a card moves through their stages — there is no server-side macro to trigger. This tool no longer runs anything.",
|
|
3778
|
-
harmony_save_card_as_playbook: "The steps_version=1 automation macro was removed. Build a stage playbook with harmony_create_playbook instead."
|
|
3777
|
+
harmony_save_card_as_playbook: "The steps_version=1 automation macro was removed. Build a stage playbook with harmony_create_playbook instead.",
|
|
3778
|
+
harmony_classify_card: "Card classification was retired. Run sizing happens at daemon pickup and is run-scoped, and the cards.intent / complexity_score / model_tier / classified_at columns it wrote have been dropped. The feature/bug/idea label — the only output anything read — is applied at card creation, so there is nothing left to trigger."
|
|
3779
3779
|
};
|
|
3780
3780
|
var _warnedRemovedTools = new Set;
|
|
3781
3781
|
function deprecatedRemovedToolResult(name) {
|
|
@@ -4483,16 +4483,6 @@ var TOOLS = {
|
|
|
4483
4483
|
required: ["target", "storagePath"]
|
|
4484
4484
|
}
|
|
4485
4485
|
},
|
|
4486
|
-
harmony_classify_card: {
|
|
4487
|
-
description: "DEPRECATED — run sizing now happens at daemon pickup and is run-scoped, so nothing reads `model_tier`, `intent` or `complexity_score` any more; this tool still writes them, but only the type label has an effect. Prefer letting card creation apply the type label. Sets `intent` (plan/think/implement/review), `complexity_score` (0-10), `model_tier` (simple/advanced/research), stamps `classified_at`, and applies the type label (feature/bug/idea). Idempotent; never touches the user-owned `model_override`.",
|
|
4488
|
-
inputSchema: {
|
|
4489
|
-
type: "object",
|
|
4490
|
-
properties: {
|
|
4491
|
-
cardId: { type: "string", description: "Card UUID" }
|
|
4492
|
-
},
|
|
4493
|
-
required: ["cardId"]
|
|
4494
|
-
}
|
|
4495
|
-
},
|
|
4496
4486
|
harmony_share_artifact: {
|
|
4497
4487
|
description: "Create a public, unauthenticated share link for a hosted artifact. Anyone with the link can view the rendered HTML without a Harmony account. Returns the share token and the full public URL. Only needed for a recipient OUTSIDE the workspace — for a teammate, hand over the `app_url` the upload already returned instead of exposing the document publicly.",
|
|
4498
4488
|
inputSchema: {
|
|
@@ -5558,7 +5548,7 @@ var TOOLS = {
|
|
|
5558
5548
|
},
|
|
5559
5549
|
autoBind: {
|
|
5560
5550
|
type: "object",
|
|
5561
|
-
description: "Auto-bind rule: {priority?: number, mode?: 'all'|'any', when: [{path, op, value}]}. Conditions are evaluated against the card's labels (lowercased)
|
|
5551
|
+
description: "Auto-bind rule: {priority?: number, mode?: 'all'|'any', when: [{path, op, value}]}. Conditions are evaluated against the card's labels (lowercased) and priority with the gate operators eq/neq/gte/gt/lte/lt/contains/exists; 'contains' on labels is membership. `intent` and `complexity_score` are NOT addressable — run sizing is run-scoped and those card columns were dropped, so a rule naming either fails closed and never binds. Stored even while triggerType is 'manual', so a rule can be armed later without re-authoring it."
|
|
5562
5552
|
},
|
|
5563
5553
|
catalogId: {
|
|
5564
5554
|
type: "string",
|
|
@@ -6364,11 +6354,8 @@ ${list}
|
|
|
6364
6354
|
const result = await client3.addExternalLink(cardId, url, title);
|
|
6365
6355
|
return { success: true, ...result };
|
|
6366
6356
|
}
|
|
6367
|
-
case "harmony_classify_card":
|
|
6368
|
-
|
|
6369
|
-
const result = await client3.classifyCard(cardId);
|
|
6370
|
-
return result;
|
|
6371
|
-
}
|
|
6357
|
+
case "harmony_classify_card":
|
|
6358
|
+
return deprecatedRemovedToolResult("harmony_classify_card");
|
|
6372
6359
|
case "harmony_create_subtask": {
|
|
6373
6360
|
const cardId = z.string().uuid().parse(args.cardId);
|
|
6374
6361
|
const title = z.string().min(1).max(500).parse(args.title);
|
package/dist/lib/api-client.js
CHANGED
|
@@ -963,6 +963,8 @@ var STAGE_DAEMON_OWNED_TOOLS = [
|
|
|
963
963
|
"mcp__harmony__harmony_start_agent_session",
|
|
964
964
|
"mcp__harmony__harmony_move_card"
|
|
965
965
|
];
|
|
966
|
+
// ../harmony-shared/dist/realtimeChannel.js
|
|
967
|
+
var inFlightDetach = new WeakMap;
|
|
966
968
|
// ../harmony-shared/dist/reviewTools.js
|
|
967
969
|
var REVIEW_DISALLOWED_TOOLS = [
|
|
968
970
|
...STAGE_DAEMON_OWNED_TOOLS,
|
|
@@ -1418,9 +1420,6 @@ class HarmonyApiClient {
|
|
|
1418
1420
|
expires_at: expiresAt
|
|
1419
1421
|
});
|
|
1420
1422
|
}
|
|
1421
|
-
async classifyCard(cardId) {
|
|
1422
|
-
return this.request("POST", `/cards/${cardId}/classify`);
|
|
1423
|
-
}
|
|
1424
1423
|
async createColumn(projectId, name) {
|
|
1425
1424
|
return this.request("POST", "/columns", { projectId, name });
|
|
1426
1425
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gethmy/mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "MCP server for Harmony, the shared surface for human–agent teams — agents claim cards, report progress, and move work on your board.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@harmony/memory": "workspace:*",
|
|
83
|
-
"@types/bun": "^1.
|
|
83
|
+
"@types/bun": "^1.4.0",
|
|
84
84
|
"@types/node": "^25.5.0",
|
|
85
85
|
"typescript": "^6.0.1"
|
|
86
86
|
}
|
package/src/api-client.ts
CHANGED
|
@@ -227,18 +227,6 @@ export type ResolveCardApiResult =
|
|
|
227
227
|
candidates: ResolveCardCandidate[];
|
|
228
228
|
};
|
|
229
229
|
|
|
230
|
-
/** Result of the classify-card classifier (card #415). Any field may be null
|
|
231
|
-
* if the LLM didn't return a usable value. `model_override` is never touched. */
|
|
232
|
-
export interface CardClassificationResult {
|
|
233
|
-
type: "feature" | "bug" | "idea" | null;
|
|
234
|
-
intent: "plan" | "think" | "implement" | "review" | null;
|
|
235
|
-
complexity_score: number | null;
|
|
236
|
-
model_tier: "simple" | "advanced" | "research" | null;
|
|
237
|
-
classified_at: string;
|
|
238
|
-
applied_type_label_id: string | null;
|
|
239
|
-
reasoning: string | null;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
230
|
export class HarmonyApiClient {
|
|
243
231
|
private apiKey: string;
|
|
244
232
|
private apiUrl: string;
|
|
@@ -986,12 +974,6 @@ export class HarmonyApiClient {
|
|
|
986
974
|
});
|
|
987
975
|
}
|
|
988
976
|
|
|
989
|
-
async classifyCard(
|
|
990
|
-
cardId: string,
|
|
991
|
-
): Promise<{ classification: CardClassificationResult }> {
|
|
992
|
-
return this.request("POST", `/cards/${cardId}/classify`);
|
|
993
|
-
}
|
|
994
|
-
|
|
995
977
|
// ============ COLUMN OPERATIONS ============
|
|
996
978
|
|
|
997
979
|
async createColumn(
|
|
@@ -1133,6 +1115,19 @@ export class HarmonyApiClient {
|
|
|
1133
1115
|
* NULL until the terminal cost frame reported the observed model.
|
|
1134
1116
|
*/
|
|
1135
1117
|
modelName?: string;
|
|
1118
|
+
/**
|
|
1119
|
+
* Which side of the daemon's pipeline opened this session (card #950):
|
|
1120
|
+
* `implement` (`worker.ts`) or `review` (`review-worker.ts`). Persisted to
|
|
1121
|
+
* `card_agent_context.session_kind`, which is what lets the board name the
|
|
1122
|
+
* model the card's WORK ran on rather than the newest model reported —
|
|
1123
|
+
* review always runs last, so without this the review model (often the
|
|
1124
|
+
* bare alias `sonnet`) passed as the card's model.
|
|
1125
|
+
*
|
|
1126
|
+
* Omit it from an `/hmy` or other MCP session: NULL means "unattributed"
|
|
1127
|
+
* and reads as "not a review" everywhere, which is the right default for a
|
|
1128
|
+
* session that is doing the card's actual work.
|
|
1129
|
+
*/
|
|
1130
|
+
sessionKind?: "implement" | "review";
|
|
1136
1131
|
/**
|
|
1137
1132
|
* Who is calling (Task 5, "the drivers"): `daemon` (the local agent
|
|
1138
1133
|
* daemon), `interactive` (a human-driven `/hmy` session), or `script`
|
|
@@ -1306,6 +1301,12 @@ export class HarmonyApiClient {
|
|
|
1306
1301
|
* deferred the respawn by 10 minutes (#770). Reply carries `stopped: true`.
|
|
1307
1302
|
*/
|
|
1308
1303
|
implicitCreate?: boolean;
|
|
1304
|
+
/**
|
|
1305
|
+
* Which driver holds this session. `"notice"` marks a row that is not a
|
|
1306
|
+
* run at all but a pool-level hold reason (#947) — instantly yieldable,
|
|
1307
|
+
* so a real run displaces it instead of meeting a 409.
|
|
1308
|
+
*/
|
|
1309
|
+
driver?: "daemon" | "interactive" | "script" | "notice";
|
|
1309
1310
|
/**
|
|
1310
1311
|
* Set while the session waits for a human budget decision (#915),
|
|
1311
1312
|
* cleared (null) once one arrives. Exempts the row from the daemon's
|
package/src/server.ts
CHANGED
|
@@ -167,6 +167,8 @@ const DEPRECATED_REMOVED_TOOLS: Record<string, string> = {
|
|
|
167
167
|
"Playbooks are stage models run by the board and agent daemon as a card moves through their stages — there is no server-side macro to trigger. This tool no longer runs anything.",
|
|
168
168
|
harmony_save_card_as_playbook:
|
|
169
169
|
"The steps_version=1 automation macro was removed. Build a stage playbook with harmony_create_playbook instead.",
|
|
170
|
+
harmony_classify_card:
|
|
171
|
+
"Card classification was retired. Run sizing happens at daemon pickup and is run-scoped, and the cards.intent / complexity_score / model_tier / classified_at columns it wrote have been dropped. The feature/bug/idea label — the only output anything read — is applied at card creation, so there is nothing left to trigger.",
|
|
170
172
|
};
|
|
171
173
|
const _warnedRemovedTools = new Set<string>();
|
|
172
174
|
function deprecatedRemovedToolResult(name: string): {
|
|
@@ -1205,17 +1207,6 @@ export const TOOLS = {
|
|
|
1205
1207
|
required: ["target", "storagePath"],
|
|
1206
1208
|
},
|
|
1207
1209
|
},
|
|
1208
|
-
harmony_classify_card: {
|
|
1209
|
-
description:
|
|
1210
|
-
"DEPRECATED — run sizing now happens at daemon pickup and is run-scoped, so nothing reads `model_tier`, `intent` or `complexity_score` any more; this tool still writes them, but only the type label has an effect. Prefer letting card creation apply the type label. Sets `intent` (plan/think/implement/review), `complexity_score` (0-10), `model_tier` (simple/advanced/research), stamps `classified_at`, and applies the type label (feature/bug/idea). Idempotent; never touches the user-owned `model_override`.",
|
|
1211
|
-
inputSchema: {
|
|
1212
|
-
type: "object",
|
|
1213
|
-
properties: {
|
|
1214
|
-
cardId: { type: "string", description: "Card UUID" },
|
|
1215
|
-
},
|
|
1216
|
-
required: ["cardId"],
|
|
1217
|
-
},
|
|
1218
|
-
},
|
|
1219
1210
|
harmony_share_artifact: {
|
|
1220
1211
|
description:
|
|
1221
1212
|
"Create a public, unauthenticated share link for a hosted artifact. Anyone with the link can view the rendered HTML without a Harmony account. Returns the share token and the full public URL. Only needed for a recipient OUTSIDE the workspace — for a teammate, hand over the `app_url` the upload already returned instead of exposing the document publicly.",
|
|
@@ -2390,7 +2381,7 @@ export const TOOLS = {
|
|
|
2390
2381
|
autoBind: {
|
|
2391
2382
|
type: "object",
|
|
2392
2383
|
description:
|
|
2393
|
-
"Auto-bind rule: {priority?: number, mode?: 'all'|'any', when: [{path, op, value}]}. Conditions are evaluated against the card's labels (lowercased)
|
|
2384
|
+
"Auto-bind rule: {priority?: number, mode?: 'all'|'any', when: [{path, op, value}]}. Conditions are evaluated against the card's labels (lowercased) and priority with the gate operators eq/neq/gte/gt/lte/lt/contains/exists; 'contains' on labels is membership. `intent` and `complexity_score` are NOT addressable — run sizing is run-scoped and those card columns were dropped, so a rule naming either fails closed and never binds. Stored even while triggerType is 'manual', so a rule can be armed later without re-authoring it.",
|
|
2394
2385
|
},
|
|
2395
2386
|
catalogId: {
|
|
2396
2387
|
type: "string",
|
|
@@ -3628,11 +3619,11 @@ async function handleToolCall(
|
|
|
3628
3619
|
return { success: true, ...result };
|
|
3629
3620
|
}
|
|
3630
3621
|
|
|
3631
|
-
case
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3622
|
+
// Removed — dropped from the advertised TOOLS list; the case remains so an
|
|
3623
|
+
// older `hmy-new` install that still calls it gets a legible notice rather
|
|
3624
|
+
// than an unknown-tool error.
|
|
3625
|
+
case "harmony_classify_card":
|
|
3626
|
+
return deprecatedRemovedToolResult("harmony_classify_card");
|
|
3636
3627
|
|
|
3637
3628
|
// Subtask operations
|
|
3638
3629
|
case "harmony_create_subtask": {
|