@gethmy/mcp 2.26.0 → 3.0.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 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
- - **78 MCP Tools** for full board control, knowledge graph, and workflow plans
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 78 Harmony tools become available in your conversation
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
@@ -2053,9 +2053,6 @@ class HarmonyApiClient {
2053
2053
  expires_at: expiresAt
2054
2054
  });
2055
2055
  }
2056
- async classifyCard(cardId) {
2057
- return this.request("POST", `/cards/${cardId}/classify`);
2058
- }
2059
2056
  async createColumn(projectId, name) {
2060
2057
  return this.request("POST", "/columns", { projectId, name });
2061
2058
  }
@@ -3780,7 +3777,8 @@ function warnDeprecatedTool(oldName) {
3780
3777
  }
3781
3778
  var DEPRECATED_REMOVED_TOOLS = {
3782
3779
  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."
3780
+ harmony_save_card_as_playbook: "The steps_version=1 automation macro was removed. Build a stage playbook with harmony_create_playbook instead.",
3781
+ 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
3782
  };
3785
3783
  var _warnedRemovedTools = new Set;
3786
3784
  function deprecatedRemovedToolResult(name) {
@@ -4488,16 +4486,6 @@ var TOOLS = {
4488
4486
  required: ["target", "storagePath"]
4489
4487
  }
4490
4488
  },
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
4489
  harmony_share_artifact: {
4502
4490
  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
4491
  inputSchema: {
@@ -5563,7 +5551,7 @@ var TOOLS = {
5563
5551
  },
5564
5552
  autoBind: {
5565
5553
  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), intent, complexity_score and priority with the gate operators eq/neq/gte/gt/lte/lt/contains/exists; 'contains' on labels is membership. Stored even while triggerType is 'manual', so a rule can be armed later without re-authoring it."
5554
+ 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
5555
  },
5568
5556
  catalogId: {
5569
5557
  type: "string",
@@ -6369,11 +6357,8 @@ ${list}
6369
6357
  const result = await client3.addExternalLink(cardId, url, title);
6370
6358
  return { success: true, ...result };
6371
6359
  }
6372
- case "harmony_classify_card": {
6373
- const cardId = z.string().uuid().parse(args.cardId);
6374
- const result = await client3.classifyCard(cardId);
6375
- return result;
6376
- }
6360
+ case "harmony_classify_card":
6361
+ return deprecatedRemovedToolResult("harmony_classify_card");
6377
6362
  case "harmony_create_subtask": {
6378
6363
  const cardId = z.string().uuid().parse(args.cardId);
6379
6364
  const title = z.string().min(1).max(500).parse(args.title);
package/dist/index.js CHANGED
@@ -2048,9 +2048,6 @@ class HarmonyApiClient {
2048
2048
  expires_at: expiresAt
2049
2049
  });
2050
2050
  }
2051
- async classifyCard(cardId) {
2052
- return this.request("POST", `/cards/${cardId}/classify`);
2053
- }
2054
2051
  async createColumn(projectId, name) {
2055
2052
  return this.request("POST", "/columns", { projectId, name });
2056
2053
  }
@@ -3775,7 +3772,8 @@ function warnDeprecatedTool(oldName) {
3775
3772
  }
3776
3773
  var DEPRECATED_REMOVED_TOOLS = {
3777
3774
  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."
3775
+ harmony_save_card_as_playbook: "The steps_version=1 automation macro was removed. Build a stage playbook with harmony_create_playbook instead.",
3776
+ 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
3777
  };
3780
3778
  var _warnedRemovedTools = new Set;
3781
3779
  function deprecatedRemovedToolResult(name) {
@@ -4483,16 +4481,6 @@ var TOOLS = {
4483
4481
  required: ["target", "storagePath"]
4484
4482
  }
4485
4483
  },
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
4484
  harmony_share_artifact: {
4497
4485
  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
4486
  inputSchema: {
@@ -5558,7 +5546,7 @@ var TOOLS = {
5558
5546
  },
5559
5547
  autoBind: {
5560
5548
  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), intent, complexity_score and priority with the gate operators eq/neq/gte/gt/lte/lt/contains/exists; 'contains' on labels is membership. Stored even while triggerType is 'manual', so a rule can be armed later without re-authoring it."
5549
+ 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
5550
  },
5563
5551
  catalogId: {
5564
5552
  type: "string",
@@ -6364,11 +6352,8 @@ ${list}
6364
6352
  const result = await client3.addExternalLink(cardId, url, title);
6365
6353
  return { success: true, ...result };
6366
6354
  }
6367
- case "harmony_classify_card": {
6368
- const cardId = z.string().uuid().parse(args.cardId);
6369
- const result = await client3.classifyCard(cardId);
6370
- return result;
6371
- }
6355
+ case "harmony_classify_card":
6356
+ return deprecatedRemovedToolResult("harmony_classify_card");
6372
6357
  case "harmony_create_subtask": {
6373
6358
  const cardId = z.string().uuid().parse(args.cardId);
6374
6359
  const title = z.string().min(1).max(500).parse(args.title);
@@ -1418,9 +1418,6 @@ class HarmonyApiClient {
1418
1418
  expires_at: expiresAt
1419
1419
  });
1420
1420
  }
1421
- async classifyCard(cardId) {
1422
- return this.request("POST", `/cards/${cardId}/classify`);
1423
- }
1424
1421
  async createColumn(projectId, name) {
1425
1422
  return this.request("POST", "/columns", { projectId, name });
1426
1423
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gethmy/mcp",
3
- "version": "2.26.0",
3
+ "version": "3.0.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.3.13",
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`
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), intent, complexity_score and priority with the gate operators eq/neq/gte/gt/lte/lt/contains/exists; 'contains' on labels is membership. Stored even while triggerType is 'manual', so a rule can be armed later without re-authoring it.",
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 "harmony_classify_card": {
3632
- const cardId = z.string().uuid().parse(args.cardId);
3633
- const result = await client.classifyCard(cardId);
3634
- return result;
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": {