@gethmy/mcp 2.25.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 +2 -2
- package/dist/cli.js +14 -22
- package/dist/index.js +14 -22
- package/dist/lib/api-client.js +9 -5
- package/package.json +2 -2
- package/src/api-client.ts +26 -19
- 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
|
@@ -1520,6 +1520,9 @@ function declaredGateMetricsFromAgents(agents) {
|
|
|
1520
1520
|
}
|
|
1521
1521
|
return { names, known };
|
|
1522
1522
|
}
|
|
1523
|
+
// ../harmony-shared/dist/fanoutSource.js
|
|
1524
|
+
var FANOUT_KEY_MARKER = "harmony:fanout-item";
|
|
1525
|
+
var FANOUT_KEY_RE = new RegExp(`^\\[${FANOUT_KEY_MARKER}\\]:\\s*#(\\S+)\\s*$`, "m");
|
|
1523
1526
|
// ../harmony-shared/dist/gateConfigError.js
|
|
1524
1527
|
var GATE_CONFIG_ERROR_KEY = "configError";
|
|
1525
1528
|
var GATE_CONFIG_ERROR_MARK = Object.freeze({ [GATE_CONFIG_ERROR_KEY]: true });
|
|
@@ -1947,8 +1950,12 @@ class HarmonyApiClient {
|
|
|
1947
1950
|
async updateCard(cardId, updates) {
|
|
1948
1951
|
return this.request("PATCH", `/cards/${cardId}`, updates);
|
|
1949
1952
|
}
|
|
1950
|
-
async claimCard(cardId, agentId) {
|
|
1951
|
-
const res = await this.request("PATCH", `/cards/${cardId}`, {
|
|
1953
|
+
async claimCard(cardId, agentId, opts) {
|
|
1954
|
+
const res = await this.request("PATCH", `/cards/${cardId}`, {
|
|
1955
|
+
assignedAgentId: agentId,
|
|
1956
|
+
ifAssignedAgentNull: true,
|
|
1957
|
+
...opts?.requireUnassigned ? { ifAssigneeNull: true } : {}
|
|
1958
|
+
});
|
|
1952
1959
|
return { claimed: res.claimed !== false };
|
|
1953
1960
|
}
|
|
1954
1961
|
async moveCard(cardId, columnId, position) {
|
|
@@ -2046,9 +2053,6 @@ class HarmonyApiClient {
|
|
|
2046
2053
|
expires_at: expiresAt
|
|
2047
2054
|
});
|
|
2048
2055
|
}
|
|
2049
|
-
async classifyCard(cardId) {
|
|
2050
|
-
return this.request("POST", `/cards/${cardId}/classify`);
|
|
2051
|
-
}
|
|
2052
2056
|
async createColumn(projectId, name) {
|
|
2053
2057
|
return this.request("POST", "/columns", { projectId, name });
|
|
2054
2058
|
}
|
|
@@ -3773,7 +3777,8 @@ function warnDeprecatedTool(oldName) {
|
|
|
3773
3777
|
}
|
|
3774
3778
|
var DEPRECATED_REMOVED_TOOLS = {
|
|
3775
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.",
|
|
3776
|
-
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."
|
|
3777
3782
|
};
|
|
3778
3783
|
var _warnedRemovedTools = new Set;
|
|
3779
3784
|
function deprecatedRemovedToolResult(name) {
|
|
@@ -4481,16 +4486,6 @@ var TOOLS = {
|
|
|
4481
4486
|
required: ["target", "storagePath"]
|
|
4482
4487
|
}
|
|
4483
4488
|
},
|
|
4484
|
-
harmony_classify_card: {
|
|
4485
|
-
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`.",
|
|
4486
|
-
inputSchema: {
|
|
4487
|
-
type: "object",
|
|
4488
|
-
properties: {
|
|
4489
|
-
cardId: { type: "string", description: "Card UUID" }
|
|
4490
|
-
},
|
|
4491
|
-
required: ["cardId"]
|
|
4492
|
-
}
|
|
4493
|
-
},
|
|
4494
4489
|
harmony_share_artifact: {
|
|
4495
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.",
|
|
4496
4491
|
inputSchema: {
|
|
@@ -5556,7 +5551,7 @@ var TOOLS = {
|
|
|
5556
5551
|
},
|
|
5557
5552
|
autoBind: {
|
|
5558
5553
|
type: "object",
|
|
5559
|
-
description: "Auto-bind rule: {priority?: number, mode?: 'all'|'any', when: [{path, op, value}]}. Conditions are evaluated against the card's labels (lowercased)
|
|
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."
|
|
5560
5555
|
},
|
|
5561
5556
|
catalogId: {
|
|
5562
5557
|
type: "string",
|
|
@@ -6362,11 +6357,8 @@ ${list}
|
|
|
6362
6357
|
const result = await client3.addExternalLink(cardId, url, title);
|
|
6363
6358
|
return { success: true, ...result };
|
|
6364
6359
|
}
|
|
6365
|
-
case "harmony_classify_card":
|
|
6366
|
-
|
|
6367
|
-
const result = await client3.classifyCard(cardId);
|
|
6368
|
-
return result;
|
|
6369
|
-
}
|
|
6360
|
+
case "harmony_classify_card":
|
|
6361
|
+
return deprecatedRemovedToolResult("harmony_classify_card");
|
|
6370
6362
|
case "harmony_create_subtask": {
|
|
6371
6363
|
const cardId = z.string().uuid().parse(args.cardId);
|
|
6372
6364
|
const title = z.string().min(1).max(500).parse(args.title);
|
package/dist/index.js
CHANGED
|
@@ -1515,6 +1515,9 @@ function declaredGateMetricsFromAgents(agents) {
|
|
|
1515
1515
|
}
|
|
1516
1516
|
return { names, known };
|
|
1517
1517
|
}
|
|
1518
|
+
// ../harmony-shared/dist/fanoutSource.js
|
|
1519
|
+
var FANOUT_KEY_MARKER = "harmony:fanout-item";
|
|
1520
|
+
var FANOUT_KEY_RE = new RegExp(`^\\[${FANOUT_KEY_MARKER}\\]:\\s*#(\\S+)\\s*$`, "m");
|
|
1518
1521
|
// ../harmony-shared/dist/gateConfigError.js
|
|
1519
1522
|
var GATE_CONFIG_ERROR_KEY = "configError";
|
|
1520
1523
|
var GATE_CONFIG_ERROR_MARK = Object.freeze({ [GATE_CONFIG_ERROR_KEY]: true });
|
|
@@ -1942,8 +1945,12 @@ class HarmonyApiClient {
|
|
|
1942
1945
|
async updateCard(cardId, updates) {
|
|
1943
1946
|
return this.request("PATCH", `/cards/${cardId}`, updates);
|
|
1944
1947
|
}
|
|
1945
|
-
async claimCard(cardId, agentId) {
|
|
1946
|
-
const res = await this.request("PATCH", `/cards/${cardId}`, {
|
|
1948
|
+
async claimCard(cardId, agentId, opts) {
|
|
1949
|
+
const res = await this.request("PATCH", `/cards/${cardId}`, {
|
|
1950
|
+
assignedAgentId: agentId,
|
|
1951
|
+
ifAssignedAgentNull: true,
|
|
1952
|
+
...opts?.requireUnassigned ? { ifAssigneeNull: true } : {}
|
|
1953
|
+
});
|
|
1947
1954
|
return { claimed: res.claimed !== false };
|
|
1948
1955
|
}
|
|
1949
1956
|
async moveCard(cardId, columnId, position) {
|
|
@@ -2041,9 +2048,6 @@ class HarmonyApiClient {
|
|
|
2041
2048
|
expires_at: expiresAt
|
|
2042
2049
|
});
|
|
2043
2050
|
}
|
|
2044
|
-
async classifyCard(cardId) {
|
|
2045
|
-
return this.request("POST", `/cards/${cardId}/classify`);
|
|
2046
|
-
}
|
|
2047
2051
|
async createColumn(projectId, name) {
|
|
2048
2052
|
return this.request("POST", "/columns", { projectId, name });
|
|
2049
2053
|
}
|
|
@@ -3768,7 +3772,8 @@ function warnDeprecatedTool(oldName) {
|
|
|
3768
3772
|
}
|
|
3769
3773
|
var DEPRECATED_REMOVED_TOOLS = {
|
|
3770
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.",
|
|
3771
|
-
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."
|
|
3772
3777
|
};
|
|
3773
3778
|
var _warnedRemovedTools = new Set;
|
|
3774
3779
|
function deprecatedRemovedToolResult(name) {
|
|
@@ -4476,16 +4481,6 @@ var TOOLS = {
|
|
|
4476
4481
|
required: ["target", "storagePath"]
|
|
4477
4482
|
}
|
|
4478
4483
|
},
|
|
4479
|
-
harmony_classify_card: {
|
|
4480
|
-
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`.",
|
|
4481
|
-
inputSchema: {
|
|
4482
|
-
type: "object",
|
|
4483
|
-
properties: {
|
|
4484
|
-
cardId: { type: "string", description: "Card UUID" }
|
|
4485
|
-
},
|
|
4486
|
-
required: ["cardId"]
|
|
4487
|
-
}
|
|
4488
|
-
},
|
|
4489
4484
|
harmony_share_artifact: {
|
|
4490
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.",
|
|
4491
4486
|
inputSchema: {
|
|
@@ -5551,7 +5546,7 @@ var TOOLS = {
|
|
|
5551
5546
|
},
|
|
5552
5547
|
autoBind: {
|
|
5553
5548
|
type: "object",
|
|
5554
|
-
description: "Auto-bind rule: {priority?: number, mode?: 'all'|'any', when: [{path, op, value}]}. Conditions are evaluated against the card's labels (lowercased)
|
|
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."
|
|
5555
5550
|
},
|
|
5556
5551
|
catalogId: {
|
|
5557
5552
|
type: "string",
|
|
@@ -6357,11 +6352,8 @@ ${list}
|
|
|
6357
6352
|
const result = await client3.addExternalLink(cardId, url, title);
|
|
6358
6353
|
return { success: true, ...result };
|
|
6359
6354
|
}
|
|
6360
|
-
case "harmony_classify_card":
|
|
6361
|
-
|
|
6362
|
-
const result = await client3.classifyCard(cardId);
|
|
6363
|
-
return result;
|
|
6364
|
-
}
|
|
6355
|
+
case "harmony_classify_card":
|
|
6356
|
+
return deprecatedRemovedToolResult("harmony_classify_card");
|
|
6365
6357
|
case "harmony_create_subtask": {
|
|
6366
6358
|
const cardId = z.string().uuid().parse(args.cardId);
|
|
6367
6359
|
const title = z.string().min(1).max(500).parse(args.title);
|
package/dist/lib/api-client.js
CHANGED
|
@@ -951,6 +951,9 @@ var TIMINGS = {
|
|
|
951
951
|
QUERY_STALE_TIME: 1000 * 60 * 5,
|
|
952
952
|
QUERY_GC_TIME: 1000 * 60 * 60 * 24
|
|
953
953
|
};
|
|
954
|
+
// ../harmony-shared/dist/fanoutSource.js
|
|
955
|
+
var FANOUT_KEY_MARKER = "harmony:fanout-item";
|
|
956
|
+
var FANOUT_KEY_RE = new RegExp(`^\\[${FANOUT_KEY_MARKER}\\]:\\s*#(\\S+)\\s*$`, "m");
|
|
954
957
|
// ../harmony-shared/dist/gateConfigError.js
|
|
955
958
|
var GATE_CONFIG_ERROR_KEY = "configError";
|
|
956
959
|
var GATE_CONFIG_ERROR_MARK = Object.freeze({ [GATE_CONFIG_ERROR_KEY]: true });
|
|
@@ -1312,8 +1315,12 @@ class HarmonyApiClient {
|
|
|
1312
1315
|
async updateCard(cardId, updates) {
|
|
1313
1316
|
return this.request("PATCH", `/cards/${cardId}`, updates);
|
|
1314
1317
|
}
|
|
1315
|
-
async claimCard(cardId, agentId) {
|
|
1316
|
-
const res = await this.request("PATCH", `/cards/${cardId}`, {
|
|
1318
|
+
async claimCard(cardId, agentId, opts) {
|
|
1319
|
+
const res = await this.request("PATCH", `/cards/${cardId}`, {
|
|
1320
|
+
assignedAgentId: agentId,
|
|
1321
|
+
ifAssignedAgentNull: true,
|
|
1322
|
+
...opts?.requireUnassigned ? { ifAssigneeNull: true } : {}
|
|
1323
|
+
});
|
|
1317
1324
|
return { claimed: res.claimed !== false };
|
|
1318
1325
|
}
|
|
1319
1326
|
async moveCard(cardId, columnId, position) {
|
|
@@ -1411,9 +1418,6 @@ class HarmonyApiClient {
|
|
|
1411
1418
|
expires_at: expiresAt
|
|
1412
1419
|
});
|
|
1413
1420
|
}
|
|
1414
|
-
async classifyCard(cardId) {
|
|
1415
|
-
return this.request("POST", `/cards/${cardId}/classify`);
|
|
1416
|
-
}
|
|
1417
1421
|
async createColumn(projectId, name) {
|
|
1418
1422
|
return this.request("POST", "/columns", { projectId, name });
|
|
1419
1423
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gethmy/mcp",
|
|
3
|
-
"version": "
|
|
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.
|
|
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;
|
|
@@ -724,15 +712,27 @@ export class HarmonyApiClient {
|
|
|
724
712
|
* Compare-and-set claim of a card for a virtual agent: sets assigned_agent_id
|
|
725
713
|
* only if it is currently NULL (server-side guard). Returns `{ claimed: false }`
|
|
726
714
|
* when another daemon already owns it. Used by the agent-agnostic review pickup.
|
|
715
|
+
*
|
|
716
|
+
* `requireUnassigned` additionally guards `assignee_id IS NULL`, so the claim
|
|
717
|
+
* also loses to a PERSON who took the card. Self-selection (sweep, card #978)
|
|
718
|
+
* needs it: this write clears `assignee_id` as a side effect, so the agent-only
|
|
719
|
+
* guard does not merely let the daemon co-own a person's card — it lets the
|
|
720
|
+
* daemon erase their assignment. Default false keeps the review-strand claim
|
|
721
|
+
* (which reaches only cards no one holds) byte-unchanged.
|
|
727
722
|
*/
|
|
728
723
|
async claimCard(
|
|
729
724
|
cardId: string,
|
|
730
725
|
agentId: string,
|
|
726
|
+
opts?: { requireUnassigned?: boolean },
|
|
731
727
|
): Promise<{ claimed: boolean }> {
|
|
732
728
|
const res = await this.request<{ card?: unknown; claimed?: boolean }>(
|
|
733
729
|
"PATCH",
|
|
734
730
|
`/cards/${cardId}`,
|
|
735
|
-
{
|
|
731
|
+
{
|
|
732
|
+
assignedAgentId: agentId,
|
|
733
|
+
ifAssignedAgentNull: true,
|
|
734
|
+
...(opts?.requireUnassigned ? { ifAssigneeNull: true } : {}),
|
|
735
|
+
},
|
|
736
736
|
);
|
|
737
737
|
// Success body is `{ card }` (no `claimed` key) → won. Lost-race body is
|
|
738
738
|
// `{ claimed: false }`.
|
|
@@ -974,12 +974,6 @@ export class HarmonyApiClient {
|
|
|
974
974
|
});
|
|
975
975
|
}
|
|
976
976
|
|
|
977
|
-
async classifyCard(
|
|
978
|
-
cardId: string,
|
|
979
|
-
): Promise<{ classification: CardClassificationResult }> {
|
|
980
|
-
return this.request("POST", `/cards/${cardId}/classify`);
|
|
981
|
-
}
|
|
982
|
-
|
|
983
977
|
// ============ COLUMN OPERATIONS ============
|
|
984
978
|
|
|
985
979
|
async createColumn(
|
|
@@ -1121,6 +1115,19 @@ export class HarmonyApiClient {
|
|
|
1121
1115
|
* NULL until the terminal cost frame reported the observed model.
|
|
1122
1116
|
*/
|
|
1123
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";
|
|
1124
1131
|
/**
|
|
1125
1132
|
* Who is calling (Task 5, "the drivers"): `daemon` (the local agent
|
|
1126
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)
|
|
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": {
|