@gethmy/mcp 2.11.2 → 2.12.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/dist/cli.js +266 -0
- package/dist/index.js +266 -0
- package/dist/lib/api-client.js +26 -0
- package/package.json +1 -1
- package/src/api-client.ts +72 -0
- package/src/server.ts +296 -0
package/dist/cli.js
CHANGED
|
@@ -1858,6 +1858,14 @@ class HarmonyApiClient {
|
|
|
1858
1858
|
async getCardExternalLinks(cardId) {
|
|
1859
1859
|
return this.request("GET", `/cards/${cardId}/external-links`);
|
|
1860
1860
|
}
|
|
1861
|
+
async uploadArtifact(data) {
|
|
1862
|
+
return this.request("POST", "/artifacts", data);
|
|
1863
|
+
}
|
|
1864
|
+
async createArtifactShareLink(artifactId, expiresAt) {
|
|
1865
|
+
return this.request("POST", `/artifacts/${artifactId}/share`, {
|
|
1866
|
+
expires_at: expiresAt
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1861
1869
|
async classifyCard(cardId) {
|
|
1862
1870
|
return this.request("POST", `/cards/${cardId}/classify`);
|
|
1863
1871
|
}
|
|
@@ -2324,6 +2332,24 @@ ${planContent.trim()}`;
|
|
|
2324
2332
|
title: cardData.title
|
|
2325
2333
|
};
|
|
2326
2334
|
}
|
|
2335
|
+
async listPlaybooks(workspaceId) {
|
|
2336
|
+
return this.request("GET", `/playbooks?workspaceId=${encodeURIComponent(workspaceId)}`);
|
|
2337
|
+
}
|
|
2338
|
+
async getPlaybook(playbookId) {
|
|
2339
|
+
return this.request("GET", `/playbooks/${playbookId}`);
|
|
2340
|
+
}
|
|
2341
|
+
async createPlaybook(data) {
|
|
2342
|
+
return this.request("POST", "/playbooks", data);
|
|
2343
|
+
}
|
|
2344
|
+
async updatePlaybook(playbookId, updates) {
|
|
2345
|
+
return this.request("PATCH", `/playbooks/${playbookId}`, updates);
|
|
2346
|
+
}
|
|
2347
|
+
async runPlaybook(playbookId) {
|
|
2348
|
+
return this.request("POST", `/playbooks/${playbookId}/run`);
|
|
2349
|
+
}
|
|
2350
|
+
async savePlaybookFromCard(data) {
|
|
2351
|
+
return this.request("POST", "/playbooks/from-card", data);
|
|
2352
|
+
}
|
|
2327
2353
|
}
|
|
2328
2354
|
var _promptModules = null;
|
|
2329
2355
|
async function loadPromptModules() {
|
|
@@ -3905,6 +3931,47 @@ var TOOLS = {
|
|
|
3905
3931
|
required: ["cardId"]
|
|
3906
3932
|
}
|
|
3907
3933
|
},
|
|
3934
|
+
harmony_upload_artifact: {
|
|
3935
|
+
description: "Host a self-contained HTML document (e.g. a visual design draft or diagram) in Harmony and link it to a card, a plan, or a workspace. The file is stored privately and rendered in-app inside a sandboxed cross-origin iframe. Provide exactly one of cardId, planId, or workspaceId. Supply the HTML as `filePath` (a local path the MCP server can read) or `base64Data`. Only text/html, max 2MB. Returns the stored artifact with a short-lived signed URL; call harmony_share_artifact to mint a public link.",
|
|
3936
|
+
inputSchema: {
|
|
3937
|
+
type: "object",
|
|
3938
|
+
properties: {
|
|
3939
|
+
title: {
|
|
3940
|
+
type: "string",
|
|
3941
|
+
description: "Display title (defaults to the file basename)."
|
|
3942
|
+
},
|
|
3943
|
+
cardId: { type: "string", description: "Link to this card (UUID)." },
|
|
3944
|
+
planId: { type: "string", description: "Link to this plan (UUID)." },
|
|
3945
|
+
workspaceId: {
|
|
3946
|
+
type: "string",
|
|
3947
|
+
description: "Attach to this workspace as a standalone artifact (UUID)."
|
|
3948
|
+
},
|
|
3949
|
+
filePath: {
|
|
3950
|
+
type: "string",
|
|
3951
|
+
description: "Absolute path to a local .html file the MCP server process can read. Mutually exclusive with base64Data."
|
|
3952
|
+
},
|
|
3953
|
+
base64Data: {
|
|
3954
|
+
type: "string",
|
|
3955
|
+
description: "Base64-encoded HTML bytes (a `data:` URL prefix is accepted and stripped). Mutually exclusive with filePath."
|
|
3956
|
+
}
|
|
3957
|
+
},
|
|
3958
|
+
required: []
|
|
3959
|
+
}
|
|
3960
|
+
},
|
|
3961
|
+
harmony_share_artifact: {
|
|
3962
|
+
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.",
|
|
3963
|
+
inputSchema: {
|
|
3964
|
+
type: "object",
|
|
3965
|
+
properties: {
|
|
3966
|
+
artifactId: { type: "string", description: "Artifact UUID" },
|
|
3967
|
+
expiresInDays: {
|
|
3968
|
+
type: "number",
|
|
3969
|
+
description: "Optional expiry in days. Omit for a link that never expires."
|
|
3970
|
+
}
|
|
3971
|
+
},
|
|
3972
|
+
required: ["artifactId"]
|
|
3973
|
+
}
|
|
3974
|
+
},
|
|
3908
3975
|
harmony_get_card_external_links: {
|
|
3909
3976
|
description: "Get external URL references attached to a card (links to docs, gists, dashboards, etc.).",
|
|
3910
3977
|
inputSchema: {
|
|
@@ -4864,6 +4931,110 @@ var TOOLS = {
|
|
|
4864
4931
|
required: ["planId"]
|
|
4865
4932
|
}
|
|
4866
4933
|
},
|
|
4934
|
+
harmony_list_playbook: {
|
|
4935
|
+
description: "List a workspace's playbooks (reusable process definitions). Returns each playbook's name, version, steps_version, and state. Read-only.",
|
|
4936
|
+
inputSchema: {
|
|
4937
|
+
type: "object",
|
|
4938
|
+
properties: {
|
|
4939
|
+
workspaceId: {
|
|
4940
|
+
type: "string",
|
|
4941
|
+
description: "Workspace ID (optional if context set)"
|
|
4942
|
+
}
|
|
4943
|
+
},
|
|
4944
|
+
required: []
|
|
4945
|
+
}
|
|
4946
|
+
},
|
|
4947
|
+
harmony_get_playbook: {
|
|
4948
|
+
description: "Get one playbook by ID, including its steps/stages definition and its recent runs. Read-only.",
|
|
4949
|
+
inputSchema: {
|
|
4950
|
+
type: "object",
|
|
4951
|
+
properties: {
|
|
4952
|
+
playbookId: { type: "string", description: "Playbook ID (UUID)" }
|
|
4953
|
+
},
|
|
4954
|
+
required: ["playbookId"]
|
|
4955
|
+
}
|
|
4956
|
+
},
|
|
4957
|
+
harmony_run_playbook: {
|
|
4958
|
+
description: "Run a playbook server-side and return the finalized run. Only legacy automation playbooks (steps_version 1) are runnable; stage playbooks (steps_version 2) are rejected. The server drives every step to completion.",
|
|
4959
|
+
inputSchema: {
|
|
4960
|
+
type: "object",
|
|
4961
|
+
properties: {
|
|
4962
|
+
playbookId: {
|
|
4963
|
+
type: "string",
|
|
4964
|
+
description: "Playbook ID to run (UUID)"
|
|
4965
|
+
}
|
|
4966
|
+
},
|
|
4967
|
+
required: ["playbookId"]
|
|
4968
|
+
}
|
|
4969
|
+
},
|
|
4970
|
+
harmony_create_playbook: {
|
|
4971
|
+
description: "Create a new playbook in a workspace. Default steps_version 1 is a legacy automation macro (an array of tool steps); steps_version 2 is the Method stage model (an array of stage objects).",
|
|
4972
|
+
inputSchema: {
|
|
4973
|
+
type: "object",
|
|
4974
|
+
properties: {
|
|
4975
|
+
workspaceId: {
|
|
4976
|
+
type: "string",
|
|
4977
|
+
description: "Workspace ID (optional if context set)"
|
|
4978
|
+
},
|
|
4979
|
+
name: { type: "string", description: "Playbook name" },
|
|
4980
|
+
description: { type: "string", description: "Playbook description" },
|
|
4981
|
+
stepsVersion: {
|
|
4982
|
+
type: "number",
|
|
4983
|
+
enum: [1, 2],
|
|
4984
|
+
description: "1 = automation macro (tool steps), 2 = Method stage model (stage objects). Default 1."
|
|
4985
|
+
},
|
|
4986
|
+
steps: {
|
|
4987
|
+
type: "array",
|
|
4988
|
+
description: "Steps (steps_version 1: tool-step objects) or stages (steps_version 2: stage objects).",
|
|
4989
|
+
items: { type: "object" }
|
|
4990
|
+
}
|
|
4991
|
+
},
|
|
4992
|
+
required: ["name"]
|
|
4993
|
+
}
|
|
4994
|
+
},
|
|
4995
|
+
harmony_update_playbook: {
|
|
4996
|
+
description: "Update a playbook's name, description, steps/stages, enabled flag, or lifecycle state ('active'|'deprecated').",
|
|
4997
|
+
inputSchema: {
|
|
4998
|
+
type: "object",
|
|
4999
|
+
properties: {
|
|
5000
|
+
playbookId: {
|
|
5001
|
+
type: "string",
|
|
5002
|
+
description: "Playbook ID to update (UUID)"
|
|
5003
|
+
},
|
|
5004
|
+
name: { type: "string", description: "New name" },
|
|
5005
|
+
description: { type: "string", description: "New description" },
|
|
5006
|
+
steps: {
|
|
5007
|
+
type: "array",
|
|
5008
|
+
description: "New steps (v1) or stages (v2) array.",
|
|
5009
|
+
items: { type: "object" }
|
|
5010
|
+
},
|
|
5011
|
+
enabled: {
|
|
5012
|
+
type: "boolean",
|
|
5013
|
+
description: "Enable/disable the playbook"
|
|
5014
|
+
},
|
|
5015
|
+
state: {
|
|
5016
|
+
type: "string",
|
|
5017
|
+
enum: ["active", "deprecated"],
|
|
5018
|
+
description: "Lifecycle state"
|
|
5019
|
+
}
|
|
5020
|
+
},
|
|
5021
|
+
required: ["playbookId"]
|
|
5022
|
+
}
|
|
5023
|
+
},
|
|
5024
|
+
harmony_save_card_as_playbook: {
|
|
5025
|
+
description: "Save an existing card as a new steps_version 1 (automation) playbook, seeding one create-card step from the card. Returns the created playbook.",
|
|
5026
|
+
inputSchema: {
|
|
5027
|
+
type: "object",
|
|
5028
|
+
properties: {
|
|
5029
|
+
cardId: { type: "string", description: "Card ID to template (UUID)" },
|
|
5030
|
+
name: {
|
|
5031
|
+
type: "string",
|
|
5032
|
+
description: "Name for the new playbook (defaults to the card title)"
|
|
5033
|
+
}
|
|
5034
|
+
},
|
|
5035
|
+
required: ["cardId"]
|
|
5036
|
+
}
|
|
5037
|
+
},
|
|
4867
5038
|
harmony_signup: {
|
|
4868
5039
|
description: "Create a new user account. Returns a JWT session for subsequent authenticated calls. No API key required.",
|
|
4869
5040
|
inputSchema: {
|
|
@@ -5412,6 +5583,50 @@ async function handleToolCall(name, args, deps) {
|
|
|
5412
5583
|
});
|
|
5413
5584
|
return result;
|
|
5414
5585
|
}
|
|
5586
|
+
case "harmony_upload_artifact": {
|
|
5587
|
+
const title = args.title != null ? z.string().parse(args.title) : undefined;
|
|
5588
|
+
const cardId = args.cardId != null ? z.string().uuid().parse(args.cardId) : undefined;
|
|
5589
|
+
const planId = args.planId != null ? z.string().uuid().parse(args.planId) : undefined;
|
|
5590
|
+
const workspaceId = args.workspaceId != null ? z.string().uuid().parse(args.workspaceId) : undefined;
|
|
5591
|
+
const anchors = [cardId, planId, workspaceId].filter(Boolean);
|
|
5592
|
+
if (anchors.length !== 1) {
|
|
5593
|
+
throw new Error("Provide exactly one of cardId, planId, or workspaceId.");
|
|
5594
|
+
}
|
|
5595
|
+
const filePath = args.filePath != null ? z.string().parse(args.filePath) : undefined;
|
|
5596
|
+
const base64Data = args.base64Data != null ? z.string().parse(args.base64Data) : undefined;
|
|
5597
|
+
if (filePath && base64Data) {
|
|
5598
|
+
throw new Error("Provide either filePath or base64Data, not both.");
|
|
5599
|
+
}
|
|
5600
|
+
let data;
|
|
5601
|
+
let inferredTitle = title;
|
|
5602
|
+
if (filePath) {
|
|
5603
|
+
const bytes = await readFile(filePath);
|
|
5604
|
+
if (bytes.byteLength === 0) {
|
|
5605
|
+
throw new Error(`File is empty: ${filePath}`);
|
|
5606
|
+
}
|
|
5607
|
+
data = bytes.toString("base64");
|
|
5608
|
+
inferredTitle = inferredTitle || basename(filePath);
|
|
5609
|
+
} else if (base64Data) {
|
|
5610
|
+
data = base64Data;
|
|
5611
|
+
} else {
|
|
5612
|
+
throw new Error("Provide either filePath or base64Data.");
|
|
5613
|
+
}
|
|
5614
|
+
const result = await client3.uploadArtifact({
|
|
5615
|
+
title: inferredTitle,
|
|
5616
|
+
cardId,
|
|
5617
|
+
planId,
|
|
5618
|
+
workspaceId,
|
|
5619
|
+
data
|
|
5620
|
+
});
|
|
5621
|
+
return result;
|
|
5622
|
+
}
|
|
5623
|
+
case "harmony_share_artifact": {
|
|
5624
|
+
const artifactId = z.string().uuid().parse(args.artifactId);
|
|
5625
|
+
const expiresInDays = args.expiresInDays != null ? z.number().positive().parse(args.expiresInDays) : undefined;
|
|
5626
|
+
const expiresAt = expiresInDays ? new Date(Date.now() + expiresInDays * 86400000).toISOString() : undefined;
|
|
5627
|
+
const result = await client3.createArtifactShareLink(artifactId, expiresAt);
|
|
5628
|
+
return result;
|
|
5629
|
+
}
|
|
5415
5630
|
case "harmony_get_card_external_links": {
|
|
5416
5631
|
const cardId = z.string().uuid().parse(args.cardId);
|
|
5417
5632
|
const result = await client3.getCardExternalLinks(cardId);
|
|
@@ -6315,6 +6530,57 @@ async function handleToolCall(name, args, deps) {
|
|
|
6315
6530
|
...results
|
|
6316
6531
|
};
|
|
6317
6532
|
}
|
|
6533
|
+
case "harmony_list_playbook": {
|
|
6534
|
+
const workspaceId = args.workspaceId || getWorkspaceId();
|
|
6535
|
+
const result = await client3.listPlaybooks(workspaceId);
|
|
6536
|
+
return {
|
|
6537
|
+
success: true,
|
|
6538
|
+
playbooks: result.playbooks,
|
|
6539
|
+
count: result.playbooks.length
|
|
6540
|
+
};
|
|
6541
|
+
}
|
|
6542
|
+
case "harmony_get_playbook": {
|
|
6543
|
+
const playbookId = z.string().uuid().parse(args.playbookId);
|
|
6544
|
+
const result = await client3.getPlaybook(playbookId);
|
|
6545
|
+
return { success: true, playbook: result.playbook, runs: result.runs };
|
|
6546
|
+
}
|
|
6547
|
+
case "harmony_run_playbook": {
|
|
6548
|
+
const playbookId = z.string().uuid().parse(args.playbookId);
|
|
6549
|
+
const result = await client3.runPlaybook(playbookId);
|
|
6550
|
+
return { success: true, run: result.run };
|
|
6551
|
+
}
|
|
6552
|
+
case "harmony_create_playbook": {
|
|
6553
|
+
const workspaceId = args.workspaceId || getWorkspaceId();
|
|
6554
|
+
const name2 = z.string().min(1).max(200).parse(args.name);
|
|
6555
|
+
const stepsVersion = args.stepsVersion !== undefined ? z.union([z.literal(1), z.literal(2)]).parse(args.stepsVersion) : undefined;
|
|
6556
|
+
const result = await client3.createPlaybook({
|
|
6557
|
+
workspaceId,
|
|
6558
|
+
name: name2,
|
|
6559
|
+
description: args.description,
|
|
6560
|
+
steps: args.steps,
|
|
6561
|
+
stepsVersion
|
|
6562
|
+
});
|
|
6563
|
+
return { success: true, playbook: result.playbook };
|
|
6564
|
+
}
|
|
6565
|
+
case "harmony_update_playbook": {
|
|
6566
|
+
const playbookId = z.string().uuid().parse(args.playbookId);
|
|
6567
|
+
const result = await client3.updatePlaybook(playbookId, {
|
|
6568
|
+
name: args.name,
|
|
6569
|
+
description: args.description,
|
|
6570
|
+
steps: args.steps,
|
|
6571
|
+
enabled: args.enabled,
|
|
6572
|
+
state: args.state
|
|
6573
|
+
});
|
|
6574
|
+
return { success: true, playbook: result.playbook };
|
|
6575
|
+
}
|
|
6576
|
+
case "harmony_save_card_as_playbook": {
|
|
6577
|
+
const cardId = z.string().uuid().parse(args.cardId);
|
|
6578
|
+
const result = await client3.savePlaybookFromCard({
|
|
6579
|
+
cardId,
|
|
6580
|
+
name: args.name
|
|
6581
|
+
});
|
|
6582
|
+
return { success: true, playbook: result.playbook };
|
|
6583
|
+
}
|
|
6318
6584
|
case "harmony_signup": {
|
|
6319
6585
|
const email = z.string().email().max(254).parse(args.email);
|
|
6320
6586
|
const password = z.string().min(8).max(128).parse(args.password);
|
package/dist/index.js
CHANGED
|
@@ -1853,6 +1853,14 @@ class HarmonyApiClient {
|
|
|
1853
1853
|
async getCardExternalLinks(cardId) {
|
|
1854
1854
|
return this.request("GET", `/cards/${cardId}/external-links`);
|
|
1855
1855
|
}
|
|
1856
|
+
async uploadArtifact(data) {
|
|
1857
|
+
return this.request("POST", "/artifacts", data);
|
|
1858
|
+
}
|
|
1859
|
+
async createArtifactShareLink(artifactId, expiresAt) {
|
|
1860
|
+
return this.request("POST", `/artifacts/${artifactId}/share`, {
|
|
1861
|
+
expires_at: expiresAt
|
|
1862
|
+
});
|
|
1863
|
+
}
|
|
1856
1864
|
async classifyCard(cardId) {
|
|
1857
1865
|
return this.request("POST", `/cards/${cardId}/classify`);
|
|
1858
1866
|
}
|
|
@@ -2319,6 +2327,24 @@ ${planContent.trim()}`;
|
|
|
2319
2327
|
title: cardData.title
|
|
2320
2328
|
};
|
|
2321
2329
|
}
|
|
2330
|
+
async listPlaybooks(workspaceId) {
|
|
2331
|
+
return this.request("GET", `/playbooks?workspaceId=${encodeURIComponent(workspaceId)}`);
|
|
2332
|
+
}
|
|
2333
|
+
async getPlaybook(playbookId) {
|
|
2334
|
+
return this.request("GET", `/playbooks/${playbookId}`);
|
|
2335
|
+
}
|
|
2336
|
+
async createPlaybook(data) {
|
|
2337
|
+
return this.request("POST", "/playbooks", data);
|
|
2338
|
+
}
|
|
2339
|
+
async updatePlaybook(playbookId, updates) {
|
|
2340
|
+
return this.request("PATCH", `/playbooks/${playbookId}`, updates);
|
|
2341
|
+
}
|
|
2342
|
+
async runPlaybook(playbookId) {
|
|
2343
|
+
return this.request("POST", `/playbooks/${playbookId}/run`);
|
|
2344
|
+
}
|
|
2345
|
+
async savePlaybookFromCard(data) {
|
|
2346
|
+
return this.request("POST", "/playbooks/from-card", data);
|
|
2347
|
+
}
|
|
2322
2348
|
}
|
|
2323
2349
|
var _promptModules = null;
|
|
2324
2350
|
async function loadPromptModules() {
|
|
@@ -3900,6 +3926,47 @@ var TOOLS = {
|
|
|
3900
3926
|
required: ["cardId"]
|
|
3901
3927
|
}
|
|
3902
3928
|
},
|
|
3929
|
+
harmony_upload_artifact: {
|
|
3930
|
+
description: "Host a self-contained HTML document (e.g. a visual design draft or diagram) in Harmony and link it to a card, a plan, or a workspace. The file is stored privately and rendered in-app inside a sandboxed cross-origin iframe. Provide exactly one of cardId, planId, or workspaceId. Supply the HTML as `filePath` (a local path the MCP server can read) or `base64Data`. Only text/html, max 2MB. Returns the stored artifact with a short-lived signed URL; call harmony_share_artifact to mint a public link.",
|
|
3931
|
+
inputSchema: {
|
|
3932
|
+
type: "object",
|
|
3933
|
+
properties: {
|
|
3934
|
+
title: {
|
|
3935
|
+
type: "string",
|
|
3936
|
+
description: "Display title (defaults to the file basename)."
|
|
3937
|
+
},
|
|
3938
|
+
cardId: { type: "string", description: "Link to this card (UUID)." },
|
|
3939
|
+
planId: { type: "string", description: "Link to this plan (UUID)." },
|
|
3940
|
+
workspaceId: {
|
|
3941
|
+
type: "string",
|
|
3942
|
+
description: "Attach to this workspace as a standalone artifact (UUID)."
|
|
3943
|
+
},
|
|
3944
|
+
filePath: {
|
|
3945
|
+
type: "string",
|
|
3946
|
+
description: "Absolute path to a local .html file the MCP server process can read. Mutually exclusive with base64Data."
|
|
3947
|
+
},
|
|
3948
|
+
base64Data: {
|
|
3949
|
+
type: "string",
|
|
3950
|
+
description: "Base64-encoded HTML bytes (a `data:` URL prefix is accepted and stripped). Mutually exclusive with filePath."
|
|
3951
|
+
}
|
|
3952
|
+
},
|
|
3953
|
+
required: []
|
|
3954
|
+
}
|
|
3955
|
+
},
|
|
3956
|
+
harmony_share_artifact: {
|
|
3957
|
+
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.",
|
|
3958
|
+
inputSchema: {
|
|
3959
|
+
type: "object",
|
|
3960
|
+
properties: {
|
|
3961
|
+
artifactId: { type: "string", description: "Artifact UUID" },
|
|
3962
|
+
expiresInDays: {
|
|
3963
|
+
type: "number",
|
|
3964
|
+
description: "Optional expiry in days. Omit for a link that never expires."
|
|
3965
|
+
}
|
|
3966
|
+
},
|
|
3967
|
+
required: ["artifactId"]
|
|
3968
|
+
}
|
|
3969
|
+
},
|
|
3903
3970
|
harmony_get_card_external_links: {
|
|
3904
3971
|
description: "Get external URL references attached to a card (links to docs, gists, dashboards, etc.).",
|
|
3905
3972
|
inputSchema: {
|
|
@@ -4859,6 +4926,110 @@ var TOOLS = {
|
|
|
4859
4926
|
required: ["planId"]
|
|
4860
4927
|
}
|
|
4861
4928
|
},
|
|
4929
|
+
harmony_list_playbook: {
|
|
4930
|
+
description: "List a workspace's playbooks (reusable process definitions). Returns each playbook's name, version, steps_version, and state. Read-only.",
|
|
4931
|
+
inputSchema: {
|
|
4932
|
+
type: "object",
|
|
4933
|
+
properties: {
|
|
4934
|
+
workspaceId: {
|
|
4935
|
+
type: "string",
|
|
4936
|
+
description: "Workspace ID (optional if context set)"
|
|
4937
|
+
}
|
|
4938
|
+
},
|
|
4939
|
+
required: []
|
|
4940
|
+
}
|
|
4941
|
+
},
|
|
4942
|
+
harmony_get_playbook: {
|
|
4943
|
+
description: "Get one playbook by ID, including its steps/stages definition and its recent runs. Read-only.",
|
|
4944
|
+
inputSchema: {
|
|
4945
|
+
type: "object",
|
|
4946
|
+
properties: {
|
|
4947
|
+
playbookId: { type: "string", description: "Playbook ID (UUID)" }
|
|
4948
|
+
},
|
|
4949
|
+
required: ["playbookId"]
|
|
4950
|
+
}
|
|
4951
|
+
},
|
|
4952
|
+
harmony_run_playbook: {
|
|
4953
|
+
description: "Run a playbook server-side and return the finalized run. Only legacy automation playbooks (steps_version 1) are runnable; stage playbooks (steps_version 2) are rejected. The server drives every step to completion.",
|
|
4954
|
+
inputSchema: {
|
|
4955
|
+
type: "object",
|
|
4956
|
+
properties: {
|
|
4957
|
+
playbookId: {
|
|
4958
|
+
type: "string",
|
|
4959
|
+
description: "Playbook ID to run (UUID)"
|
|
4960
|
+
}
|
|
4961
|
+
},
|
|
4962
|
+
required: ["playbookId"]
|
|
4963
|
+
}
|
|
4964
|
+
},
|
|
4965
|
+
harmony_create_playbook: {
|
|
4966
|
+
description: "Create a new playbook in a workspace. Default steps_version 1 is a legacy automation macro (an array of tool steps); steps_version 2 is the Method stage model (an array of stage objects).",
|
|
4967
|
+
inputSchema: {
|
|
4968
|
+
type: "object",
|
|
4969
|
+
properties: {
|
|
4970
|
+
workspaceId: {
|
|
4971
|
+
type: "string",
|
|
4972
|
+
description: "Workspace ID (optional if context set)"
|
|
4973
|
+
},
|
|
4974
|
+
name: { type: "string", description: "Playbook name" },
|
|
4975
|
+
description: { type: "string", description: "Playbook description" },
|
|
4976
|
+
stepsVersion: {
|
|
4977
|
+
type: "number",
|
|
4978
|
+
enum: [1, 2],
|
|
4979
|
+
description: "1 = automation macro (tool steps), 2 = Method stage model (stage objects). Default 1."
|
|
4980
|
+
},
|
|
4981
|
+
steps: {
|
|
4982
|
+
type: "array",
|
|
4983
|
+
description: "Steps (steps_version 1: tool-step objects) or stages (steps_version 2: stage objects).",
|
|
4984
|
+
items: { type: "object" }
|
|
4985
|
+
}
|
|
4986
|
+
},
|
|
4987
|
+
required: ["name"]
|
|
4988
|
+
}
|
|
4989
|
+
},
|
|
4990
|
+
harmony_update_playbook: {
|
|
4991
|
+
description: "Update a playbook's name, description, steps/stages, enabled flag, or lifecycle state ('active'|'deprecated').",
|
|
4992
|
+
inputSchema: {
|
|
4993
|
+
type: "object",
|
|
4994
|
+
properties: {
|
|
4995
|
+
playbookId: {
|
|
4996
|
+
type: "string",
|
|
4997
|
+
description: "Playbook ID to update (UUID)"
|
|
4998
|
+
},
|
|
4999
|
+
name: { type: "string", description: "New name" },
|
|
5000
|
+
description: { type: "string", description: "New description" },
|
|
5001
|
+
steps: {
|
|
5002
|
+
type: "array",
|
|
5003
|
+
description: "New steps (v1) or stages (v2) array.",
|
|
5004
|
+
items: { type: "object" }
|
|
5005
|
+
},
|
|
5006
|
+
enabled: {
|
|
5007
|
+
type: "boolean",
|
|
5008
|
+
description: "Enable/disable the playbook"
|
|
5009
|
+
},
|
|
5010
|
+
state: {
|
|
5011
|
+
type: "string",
|
|
5012
|
+
enum: ["active", "deprecated"],
|
|
5013
|
+
description: "Lifecycle state"
|
|
5014
|
+
}
|
|
5015
|
+
},
|
|
5016
|
+
required: ["playbookId"]
|
|
5017
|
+
}
|
|
5018
|
+
},
|
|
5019
|
+
harmony_save_card_as_playbook: {
|
|
5020
|
+
description: "Save an existing card as a new steps_version 1 (automation) playbook, seeding one create-card step from the card. Returns the created playbook.",
|
|
5021
|
+
inputSchema: {
|
|
5022
|
+
type: "object",
|
|
5023
|
+
properties: {
|
|
5024
|
+
cardId: { type: "string", description: "Card ID to template (UUID)" },
|
|
5025
|
+
name: {
|
|
5026
|
+
type: "string",
|
|
5027
|
+
description: "Name for the new playbook (defaults to the card title)"
|
|
5028
|
+
}
|
|
5029
|
+
},
|
|
5030
|
+
required: ["cardId"]
|
|
5031
|
+
}
|
|
5032
|
+
},
|
|
4862
5033
|
harmony_signup: {
|
|
4863
5034
|
description: "Create a new user account. Returns a JWT session for subsequent authenticated calls. No API key required.",
|
|
4864
5035
|
inputSchema: {
|
|
@@ -5407,6 +5578,50 @@ async function handleToolCall(name, args, deps) {
|
|
|
5407
5578
|
});
|
|
5408
5579
|
return result;
|
|
5409
5580
|
}
|
|
5581
|
+
case "harmony_upload_artifact": {
|
|
5582
|
+
const title = args.title != null ? z.string().parse(args.title) : undefined;
|
|
5583
|
+
const cardId = args.cardId != null ? z.string().uuid().parse(args.cardId) : undefined;
|
|
5584
|
+
const planId = args.planId != null ? z.string().uuid().parse(args.planId) : undefined;
|
|
5585
|
+
const workspaceId = args.workspaceId != null ? z.string().uuid().parse(args.workspaceId) : undefined;
|
|
5586
|
+
const anchors = [cardId, planId, workspaceId].filter(Boolean);
|
|
5587
|
+
if (anchors.length !== 1) {
|
|
5588
|
+
throw new Error("Provide exactly one of cardId, planId, or workspaceId.");
|
|
5589
|
+
}
|
|
5590
|
+
const filePath = args.filePath != null ? z.string().parse(args.filePath) : undefined;
|
|
5591
|
+
const base64Data = args.base64Data != null ? z.string().parse(args.base64Data) : undefined;
|
|
5592
|
+
if (filePath && base64Data) {
|
|
5593
|
+
throw new Error("Provide either filePath or base64Data, not both.");
|
|
5594
|
+
}
|
|
5595
|
+
let data;
|
|
5596
|
+
let inferredTitle = title;
|
|
5597
|
+
if (filePath) {
|
|
5598
|
+
const bytes = await readFile(filePath);
|
|
5599
|
+
if (bytes.byteLength === 0) {
|
|
5600
|
+
throw new Error(`File is empty: ${filePath}`);
|
|
5601
|
+
}
|
|
5602
|
+
data = bytes.toString("base64");
|
|
5603
|
+
inferredTitle = inferredTitle || basename(filePath);
|
|
5604
|
+
} else if (base64Data) {
|
|
5605
|
+
data = base64Data;
|
|
5606
|
+
} else {
|
|
5607
|
+
throw new Error("Provide either filePath or base64Data.");
|
|
5608
|
+
}
|
|
5609
|
+
const result = await client3.uploadArtifact({
|
|
5610
|
+
title: inferredTitle,
|
|
5611
|
+
cardId,
|
|
5612
|
+
planId,
|
|
5613
|
+
workspaceId,
|
|
5614
|
+
data
|
|
5615
|
+
});
|
|
5616
|
+
return result;
|
|
5617
|
+
}
|
|
5618
|
+
case "harmony_share_artifact": {
|
|
5619
|
+
const artifactId = z.string().uuid().parse(args.artifactId);
|
|
5620
|
+
const expiresInDays = args.expiresInDays != null ? z.number().positive().parse(args.expiresInDays) : undefined;
|
|
5621
|
+
const expiresAt = expiresInDays ? new Date(Date.now() + expiresInDays * 86400000).toISOString() : undefined;
|
|
5622
|
+
const result = await client3.createArtifactShareLink(artifactId, expiresAt);
|
|
5623
|
+
return result;
|
|
5624
|
+
}
|
|
5410
5625
|
case "harmony_get_card_external_links": {
|
|
5411
5626
|
const cardId = z.string().uuid().parse(args.cardId);
|
|
5412
5627
|
const result = await client3.getCardExternalLinks(cardId);
|
|
@@ -6310,6 +6525,57 @@ async function handleToolCall(name, args, deps) {
|
|
|
6310
6525
|
...results
|
|
6311
6526
|
};
|
|
6312
6527
|
}
|
|
6528
|
+
case "harmony_list_playbook": {
|
|
6529
|
+
const workspaceId = args.workspaceId || getWorkspaceId();
|
|
6530
|
+
const result = await client3.listPlaybooks(workspaceId);
|
|
6531
|
+
return {
|
|
6532
|
+
success: true,
|
|
6533
|
+
playbooks: result.playbooks,
|
|
6534
|
+
count: result.playbooks.length
|
|
6535
|
+
};
|
|
6536
|
+
}
|
|
6537
|
+
case "harmony_get_playbook": {
|
|
6538
|
+
const playbookId = z.string().uuid().parse(args.playbookId);
|
|
6539
|
+
const result = await client3.getPlaybook(playbookId);
|
|
6540
|
+
return { success: true, playbook: result.playbook, runs: result.runs };
|
|
6541
|
+
}
|
|
6542
|
+
case "harmony_run_playbook": {
|
|
6543
|
+
const playbookId = z.string().uuid().parse(args.playbookId);
|
|
6544
|
+
const result = await client3.runPlaybook(playbookId);
|
|
6545
|
+
return { success: true, run: result.run };
|
|
6546
|
+
}
|
|
6547
|
+
case "harmony_create_playbook": {
|
|
6548
|
+
const workspaceId = args.workspaceId || getWorkspaceId();
|
|
6549
|
+
const name2 = z.string().min(1).max(200).parse(args.name);
|
|
6550
|
+
const stepsVersion = args.stepsVersion !== undefined ? z.union([z.literal(1), z.literal(2)]).parse(args.stepsVersion) : undefined;
|
|
6551
|
+
const result = await client3.createPlaybook({
|
|
6552
|
+
workspaceId,
|
|
6553
|
+
name: name2,
|
|
6554
|
+
description: args.description,
|
|
6555
|
+
steps: args.steps,
|
|
6556
|
+
stepsVersion
|
|
6557
|
+
});
|
|
6558
|
+
return { success: true, playbook: result.playbook };
|
|
6559
|
+
}
|
|
6560
|
+
case "harmony_update_playbook": {
|
|
6561
|
+
const playbookId = z.string().uuid().parse(args.playbookId);
|
|
6562
|
+
const result = await client3.updatePlaybook(playbookId, {
|
|
6563
|
+
name: args.name,
|
|
6564
|
+
description: args.description,
|
|
6565
|
+
steps: args.steps,
|
|
6566
|
+
enabled: args.enabled,
|
|
6567
|
+
state: args.state
|
|
6568
|
+
});
|
|
6569
|
+
return { success: true, playbook: result.playbook };
|
|
6570
|
+
}
|
|
6571
|
+
case "harmony_save_card_as_playbook": {
|
|
6572
|
+
const cardId = z.string().uuid().parse(args.cardId);
|
|
6573
|
+
const result = await client3.savePlaybookFromCard({
|
|
6574
|
+
cardId,
|
|
6575
|
+
name: args.name
|
|
6576
|
+
});
|
|
6577
|
+
return { success: true, playbook: result.playbook };
|
|
6578
|
+
}
|
|
6313
6579
|
case "harmony_signup": {
|
|
6314
6580
|
const email = z.string().email().max(254).parse(args.email);
|
|
6315
6581
|
const password = z.string().min(8).max(128).parse(args.password);
|
package/dist/lib/api-client.js
CHANGED
|
@@ -1306,6 +1306,14 @@ class HarmonyApiClient {
|
|
|
1306
1306
|
async getCardExternalLinks(cardId) {
|
|
1307
1307
|
return this.request("GET", `/cards/${cardId}/external-links`);
|
|
1308
1308
|
}
|
|
1309
|
+
async uploadArtifact(data) {
|
|
1310
|
+
return this.request("POST", "/artifacts", data);
|
|
1311
|
+
}
|
|
1312
|
+
async createArtifactShareLink(artifactId, expiresAt) {
|
|
1313
|
+
return this.request("POST", `/artifacts/${artifactId}/share`, {
|
|
1314
|
+
expires_at: expiresAt
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1309
1317
|
async classifyCard(cardId) {
|
|
1310
1318
|
return this.request("POST", `/cards/${cardId}/classify`);
|
|
1311
1319
|
}
|
|
@@ -1772,6 +1780,24 @@ ${planContent.trim()}`;
|
|
|
1772
1780
|
title: cardData.title
|
|
1773
1781
|
};
|
|
1774
1782
|
}
|
|
1783
|
+
async listPlaybooks(workspaceId) {
|
|
1784
|
+
return this.request("GET", `/playbooks?workspaceId=${encodeURIComponent(workspaceId)}`);
|
|
1785
|
+
}
|
|
1786
|
+
async getPlaybook(playbookId) {
|
|
1787
|
+
return this.request("GET", `/playbooks/${playbookId}`);
|
|
1788
|
+
}
|
|
1789
|
+
async createPlaybook(data) {
|
|
1790
|
+
return this.request("POST", "/playbooks", data);
|
|
1791
|
+
}
|
|
1792
|
+
async updatePlaybook(playbookId, updates) {
|
|
1793
|
+
return this.request("PATCH", `/playbooks/${playbookId}`, updates);
|
|
1794
|
+
}
|
|
1795
|
+
async runPlaybook(playbookId) {
|
|
1796
|
+
return this.request("POST", `/playbooks/${playbookId}/run`);
|
|
1797
|
+
}
|
|
1798
|
+
async savePlaybookFromCard(data) {
|
|
1799
|
+
return this.request("POST", "/playbooks/from-card", data);
|
|
1800
|
+
}
|
|
1775
1801
|
}
|
|
1776
1802
|
var _promptModules = null;
|
|
1777
1803
|
async function loadPromptModules() {
|
package/package.json
CHANGED
package/src/api-client.ts
CHANGED
|
@@ -681,6 +681,28 @@ export class HarmonyApiClient {
|
|
|
681
681
|
return this.request("GET", `/cards/${cardId}/external-links`);
|
|
682
682
|
}
|
|
683
683
|
|
|
684
|
+
// ============ ARTIFACTS (hosted HTML documents) ============
|
|
685
|
+
|
|
686
|
+
async uploadArtifact(data: {
|
|
687
|
+
title?: string;
|
|
688
|
+
cardId?: string;
|
|
689
|
+
planId?: string;
|
|
690
|
+
workspaceId?: string;
|
|
691
|
+
contentType?: string;
|
|
692
|
+
data: string;
|
|
693
|
+
}): Promise<{ artifact: Record<string, unknown> }> {
|
|
694
|
+
return this.request("POST", "/artifacts", data);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
async createArtifactShareLink(
|
|
698
|
+
artifactId: string,
|
|
699
|
+
expiresAt?: string,
|
|
700
|
+
): Promise<{ link: Record<string, unknown> }> {
|
|
701
|
+
return this.request("POST", `/artifacts/${artifactId}/share`, {
|
|
702
|
+
expires_at: expiresAt,
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
|
|
684
706
|
async classifyCard(
|
|
685
707
|
cardId: string,
|
|
686
708
|
): Promise<{ classification: CardClassificationResult }> {
|
|
@@ -1709,6 +1731,56 @@ export class HarmonyApiClient {
|
|
|
1709
1731
|
title: cardData.title,
|
|
1710
1732
|
};
|
|
1711
1733
|
}
|
|
1734
|
+
|
|
1735
|
+
// ============ PLAYBOOKS (Method/Loop layer) ============
|
|
1736
|
+
|
|
1737
|
+
async listPlaybooks(workspaceId: string): Promise<{ playbooks: unknown[] }> {
|
|
1738
|
+
return this.request(
|
|
1739
|
+
"GET",
|
|
1740
|
+
`/playbooks?workspaceId=${encodeURIComponent(workspaceId)}`,
|
|
1741
|
+
);
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
async getPlaybook(
|
|
1745
|
+
playbookId: string,
|
|
1746
|
+
): Promise<{ playbook: unknown; runs: unknown[] }> {
|
|
1747
|
+
return this.request("GET", `/playbooks/${playbookId}`);
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
async createPlaybook(data: {
|
|
1751
|
+
workspaceId: string;
|
|
1752
|
+
name: string;
|
|
1753
|
+
description?: string;
|
|
1754
|
+
steps?: unknown;
|
|
1755
|
+
stepsVersion?: number;
|
|
1756
|
+
triggerType?: string;
|
|
1757
|
+
}): Promise<{ playbook: unknown }> {
|
|
1758
|
+
return this.request("POST", "/playbooks", data);
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
async updatePlaybook(
|
|
1762
|
+
playbookId: string,
|
|
1763
|
+
updates: {
|
|
1764
|
+
name?: string;
|
|
1765
|
+
description?: string;
|
|
1766
|
+
steps?: unknown;
|
|
1767
|
+
enabled?: boolean;
|
|
1768
|
+
state?: string;
|
|
1769
|
+
},
|
|
1770
|
+
): Promise<{ playbook: unknown }> {
|
|
1771
|
+
return this.request("PATCH", `/playbooks/${playbookId}`, updates);
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
async runPlaybook(playbookId: string): Promise<{ run: unknown }> {
|
|
1775
|
+
return this.request("POST", `/playbooks/${playbookId}/run`);
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
async savePlaybookFromCard(data: {
|
|
1779
|
+
cardId: string;
|
|
1780
|
+
name?: string;
|
|
1781
|
+
}): Promise<{ playbook: unknown }> {
|
|
1782
|
+
return this.request("POST", "/playbooks/from-card", data);
|
|
1783
|
+
}
|
|
1712
1784
|
}
|
|
1713
1785
|
|
|
1714
1786
|
// Shared types for generateCardPrompt to avoid inline assertions
|
package/src/server.ts
CHANGED
|
@@ -705,6 +705,53 @@ export const TOOLS = {
|
|
|
705
705
|
required: ["cardId"],
|
|
706
706
|
},
|
|
707
707
|
},
|
|
708
|
+
harmony_upload_artifact: {
|
|
709
|
+
description:
|
|
710
|
+
"Host a self-contained HTML document (e.g. a visual design draft or diagram) in Harmony and link it to a card, a plan, or a workspace. The file is stored privately and rendered in-app inside a sandboxed cross-origin iframe. Provide exactly one of cardId, planId, or workspaceId. Supply the HTML as `filePath` (a local path the MCP server can read) or `base64Data`. Only text/html, max 2MB. Returns the stored artifact with a short-lived signed URL; call harmony_share_artifact to mint a public link.",
|
|
711
|
+
inputSchema: {
|
|
712
|
+
type: "object",
|
|
713
|
+
properties: {
|
|
714
|
+
title: {
|
|
715
|
+
type: "string",
|
|
716
|
+
description: "Display title (defaults to the file basename).",
|
|
717
|
+
},
|
|
718
|
+
cardId: { type: "string", description: "Link to this card (UUID)." },
|
|
719
|
+
planId: { type: "string", description: "Link to this plan (UUID)." },
|
|
720
|
+
workspaceId: {
|
|
721
|
+
type: "string",
|
|
722
|
+
description:
|
|
723
|
+
"Attach to this workspace as a standalone artifact (UUID).",
|
|
724
|
+
},
|
|
725
|
+
filePath: {
|
|
726
|
+
type: "string",
|
|
727
|
+
description:
|
|
728
|
+
"Absolute path to a local .html file the MCP server process can read. Mutually exclusive with base64Data.",
|
|
729
|
+
},
|
|
730
|
+
base64Data: {
|
|
731
|
+
type: "string",
|
|
732
|
+
description:
|
|
733
|
+
"Base64-encoded HTML bytes (a `data:` URL prefix is accepted and stripped). Mutually exclusive with filePath.",
|
|
734
|
+
},
|
|
735
|
+
},
|
|
736
|
+
required: [],
|
|
737
|
+
},
|
|
738
|
+
},
|
|
739
|
+
harmony_share_artifact: {
|
|
740
|
+
description:
|
|
741
|
+
"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.",
|
|
742
|
+
inputSchema: {
|
|
743
|
+
type: "object",
|
|
744
|
+
properties: {
|
|
745
|
+
artifactId: { type: "string", description: "Artifact UUID" },
|
|
746
|
+
expiresInDays: {
|
|
747
|
+
type: "number",
|
|
748
|
+
description:
|
|
749
|
+
"Optional expiry in days. Omit for a link that never expires.",
|
|
750
|
+
},
|
|
751
|
+
},
|
|
752
|
+
required: ["artifactId"],
|
|
753
|
+
},
|
|
754
|
+
},
|
|
708
755
|
harmony_get_card_external_links: {
|
|
709
756
|
description:
|
|
710
757
|
"Get external URL references attached to a card (links to docs, gists, dashboards, etc.).",
|
|
@@ -1754,6 +1801,126 @@ export const TOOLS = {
|
|
|
1754
1801
|
},
|
|
1755
1802
|
},
|
|
1756
1803
|
|
|
1804
|
+
// ============ PLAYBOOK TOOLS (Method/Loop layer) ============
|
|
1805
|
+
|
|
1806
|
+
harmony_list_playbook: {
|
|
1807
|
+
description:
|
|
1808
|
+
"List a workspace's playbooks (reusable process definitions). Returns each playbook's name, version, steps_version, and state. Read-only.",
|
|
1809
|
+
inputSchema: {
|
|
1810
|
+
type: "object",
|
|
1811
|
+
properties: {
|
|
1812
|
+
workspaceId: {
|
|
1813
|
+
type: "string",
|
|
1814
|
+
description: "Workspace ID (optional if context set)",
|
|
1815
|
+
},
|
|
1816
|
+
},
|
|
1817
|
+
required: [],
|
|
1818
|
+
},
|
|
1819
|
+
},
|
|
1820
|
+
|
|
1821
|
+
harmony_get_playbook: {
|
|
1822
|
+
description:
|
|
1823
|
+
"Get one playbook by ID, including its steps/stages definition and its recent runs. Read-only.",
|
|
1824
|
+
inputSchema: {
|
|
1825
|
+
type: "object",
|
|
1826
|
+
properties: {
|
|
1827
|
+
playbookId: { type: "string", description: "Playbook ID (UUID)" },
|
|
1828
|
+
},
|
|
1829
|
+
required: ["playbookId"],
|
|
1830
|
+
},
|
|
1831
|
+
},
|
|
1832
|
+
|
|
1833
|
+
harmony_run_playbook: {
|
|
1834
|
+
description:
|
|
1835
|
+
"Run a playbook server-side and return the finalized run. Only legacy automation playbooks (steps_version 1) are runnable; stage playbooks (steps_version 2) are rejected. The server drives every step to completion.",
|
|
1836
|
+
inputSchema: {
|
|
1837
|
+
type: "object",
|
|
1838
|
+
properties: {
|
|
1839
|
+
playbookId: {
|
|
1840
|
+
type: "string",
|
|
1841
|
+
description: "Playbook ID to run (UUID)",
|
|
1842
|
+
},
|
|
1843
|
+
},
|
|
1844
|
+
required: ["playbookId"],
|
|
1845
|
+
},
|
|
1846
|
+
},
|
|
1847
|
+
|
|
1848
|
+
harmony_create_playbook: {
|
|
1849
|
+
description:
|
|
1850
|
+
"Create a new playbook in a workspace. Default steps_version 1 is a legacy automation macro (an array of tool steps); steps_version 2 is the Method stage model (an array of stage objects).",
|
|
1851
|
+
inputSchema: {
|
|
1852
|
+
type: "object",
|
|
1853
|
+
properties: {
|
|
1854
|
+
workspaceId: {
|
|
1855
|
+
type: "string",
|
|
1856
|
+
description: "Workspace ID (optional if context set)",
|
|
1857
|
+
},
|
|
1858
|
+
name: { type: "string", description: "Playbook name" },
|
|
1859
|
+
description: { type: "string", description: "Playbook description" },
|
|
1860
|
+
stepsVersion: {
|
|
1861
|
+
type: "number",
|
|
1862
|
+
enum: [1, 2],
|
|
1863
|
+
description:
|
|
1864
|
+
"1 = automation macro (tool steps), 2 = Method stage model (stage objects). Default 1.",
|
|
1865
|
+
},
|
|
1866
|
+
steps: {
|
|
1867
|
+
type: "array",
|
|
1868
|
+
description:
|
|
1869
|
+
"Steps (steps_version 1: tool-step objects) or stages (steps_version 2: stage objects).",
|
|
1870
|
+
items: { type: "object" },
|
|
1871
|
+
},
|
|
1872
|
+
},
|
|
1873
|
+
required: ["name"],
|
|
1874
|
+
},
|
|
1875
|
+
},
|
|
1876
|
+
|
|
1877
|
+
harmony_update_playbook: {
|
|
1878
|
+
description:
|
|
1879
|
+
"Update a playbook's name, description, steps/stages, enabled flag, or lifecycle state ('active'|'deprecated').",
|
|
1880
|
+
inputSchema: {
|
|
1881
|
+
type: "object",
|
|
1882
|
+
properties: {
|
|
1883
|
+
playbookId: {
|
|
1884
|
+
type: "string",
|
|
1885
|
+
description: "Playbook ID to update (UUID)",
|
|
1886
|
+
},
|
|
1887
|
+
name: { type: "string", description: "New name" },
|
|
1888
|
+
description: { type: "string", description: "New description" },
|
|
1889
|
+
steps: {
|
|
1890
|
+
type: "array",
|
|
1891
|
+
description: "New steps (v1) or stages (v2) array.",
|
|
1892
|
+
items: { type: "object" },
|
|
1893
|
+
},
|
|
1894
|
+
enabled: {
|
|
1895
|
+
type: "boolean",
|
|
1896
|
+
description: "Enable/disable the playbook",
|
|
1897
|
+
},
|
|
1898
|
+
state: {
|
|
1899
|
+
type: "string",
|
|
1900
|
+
enum: ["active", "deprecated"],
|
|
1901
|
+
description: "Lifecycle state",
|
|
1902
|
+
},
|
|
1903
|
+
},
|
|
1904
|
+
required: ["playbookId"],
|
|
1905
|
+
},
|
|
1906
|
+
},
|
|
1907
|
+
|
|
1908
|
+
harmony_save_card_as_playbook: {
|
|
1909
|
+
description:
|
|
1910
|
+
"Save an existing card as a new steps_version 1 (automation) playbook, seeding one create-card step from the card. Returns the created playbook.",
|
|
1911
|
+
inputSchema: {
|
|
1912
|
+
type: "object",
|
|
1913
|
+
properties: {
|
|
1914
|
+
cardId: { type: "string", description: "Card ID to template (UUID)" },
|
|
1915
|
+
name: {
|
|
1916
|
+
type: "string",
|
|
1917
|
+
description: "Name for the new playbook (defaults to the card title)",
|
|
1918
|
+
},
|
|
1919
|
+
},
|
|
1920
|
+
required: ["cardId"],
|
|
1921
|
+
},
|
|
1922
|
+
},
|
|
1923
|
+
|
|
1757
1924
|
// ============ ONBOARDING TOOLS ============
|
|
1758
1925
|
harmony_signup: {
|
|
1759
1926
|
description:
|
|
@@ -2559,6 +2726,73 @@ async function handleToolCall(
|
|
|
2559
2726
|
return result;
|
|
2560
2727
|
}
|
|
2561
2728
|
|
|
2729
|
+
case "harmony_upload_artifact": {
|
|
2730
|
+
const title =
|
|
2731
|
+
args.title != null ? z.string().parse(args.title) : undefined;
|
|
2732
|
+
const cardId =
|
|
2733
|
+
args.cardId != null ? z.string().uuid().parse(args.cardId) : undefined;
|
|
2734
|
+
const planId =
|
|
2735
|
+
args.planId != null ? z.string().uuid().parse(args.planId) : undefined;
|
|
2736
|
+
const workspaceId =
|
|
2737
|
+
args.workspaceId != null
|
|
2738
|
+
? z.string().uuid().parse(args.workspaceId)
|
|
2739
|
+
: undefined;
|
|
2740
|
+
const anchors = [cardId, planId, workspaceId].filter(Boolean);
|
|
2741
|
+
if (anchors.length !== 1) {
|
|
2742
|
+
throw new Error(
|
|
2743
|
+
"Provide exactly one of cardId, planId, or workspaceId.",
|
|
2744
|
+
);
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2747
|
+
const filePath =
|
|
2748
|
+
args.filePath != null ? z.string().parse(args.filePath) : undefined;
|
|
2749
|
+
const base64Data =
|
|
2750
|
+
args.base64Data != null ? z.string().parse(args.base64Data) : undefined;
|
|
2751
|
+
if (filePath && base64Data) {
|
|
2752
|
+
throw new Error("Provide either filePath or base64Data, not both.");
|
|
2753
|
+
}
|
|
2754
|
+
|
|
2755
|
+
let data: string;
|
|
2756
|
+
let inferredTitle = title;
|
|
2757
|
+
if (filePath) {
|
|
2758
|
+
const bytes = await readFile(filePath);
|
|
2759
|
+
if (bytes.byteLength === 0) {
|
|
2760
|
+
throw new Error(`File is empty: ${filePath}`);
|
|
2761
|
+
}
|
|
2762
|
+
data = bytes.toString("base64");
|
|
2763
|
+
inferredTitle = inferredTitle || basename(filePath);
|
|
2764
|
+
} else if (base64Data) {
|
|
2765
|
+
data = base64Data;
|
|
2766
|
+
} else {
|
|
2767
|
+
throw new Error("Provide either filePath or base64Data.");
|
|
2768
|
+
}
|
|
2769
|
+
|
|
2770
|
+
const result = await client.uploadArtifact({
|
|
2771
|
+
title: inferredTitle,
|
|
2772
|
+
cardId,
|
|
2773
|
+
planId,
|
|
2774
|
+
workspaceId,
|
|
2775
|
+
data,
|
|
2776
|
+
});
|
|
2777
|
+
return result;
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
case "harmony_share_artifact": {
|
|
2781
|
+
const artifactId = z.string().uuid().parse(args.artifactId);
|
|
2782
|
+
const expiresInDays =
|
|
2783
|
+
args.expiresInDays != null
|
|
2784
|
+
? z.number().positive().parse(args.expiresInDays)
|
|
2785
|
+
: undefined;
|
|
2786
|
+
const expiresAt = expiresInDays
|
|
2787
|
+
? new Date(Date.now() + expiresInDays * 86_400_000).toISOString()
|
|
2788
|
+
: undefined;
|
|
2789
|
+
const result = await client.createArtifactShareLink(
|
|
2790
|
+
artifactId,
|
|
2791
|
+
expiresAt,
|
|
2792
|
+
);
|
|
2793
|
+
return result;
|
|
2794
|
+
}
|
|
2795
|
+
|
|
2562
2796
|
case "harmony_get_card_external_links": {
|
|
2563
2797
|
const cardId = z.string().uuid().parse(args.cardId);
|
|
2564
2798
|
const result = await client.getCardExternalLinks(cardId);
|
|
@@ -4028,6 +4262,68 @@ async function handleToolCall(
|
|
|
4028
4262
|
};
|
|
4029
4263
|
}
|
|
4030
4264
|
|
|
4265
|
+
// ============ PLAYBOOK TOOLS (Method/Loop layer) ============
|
|
4266
|
+
|
|
4267
|
+
case "harmony_list_playbook": {
|
|
4268
|
+
const workspaceId = (args.workspaceId as string) || getWorkspaceId();
|
|
4269
|
+
const result = await client.listPlaybooks(workspaceId);
|
|
4270
|
+
return {
|
|
4271
|
+
success: true,
|
|
4272
|
+
playbooks: result.playbooks,
|
|
4273
|
+
count: (result.playbooks as unknown[]).length,
|
|
4274
|
+
};
|
|
4275
|
+
}
|
|
4276
|
+
|
|
4277
|
+
case "harmony_get_playbook": {
|
|
4278
|
+
const playbookId = z.string().uuid().parse(args.playbookId);
|
|
4279
|
+
const result = await client.getPlaybook(playbookId);
|
|
4280
|
+
return { success: true, playbook: result.playbook, runs: result.runs };
|
|
4281
|
+
}
|
|
4282
|
+
|
|
4283
|
+
case "harmony_run_playbook": {
|
|
4284
|
+
const playbookId = z.string().uuid().parse(args.playbookId);
|
|
4285
|
+
const result = await client.runPlaybook(playbookId);
|
|
4286
|
+
return { success: true, run: result.run };
|
|
4287
|
+
}
|
|
4288
|
+
|
|
4289
|
+
case "harmony_create_playbook": {
|
|
4290
|
+
const workspaceId = (args.workspaceId as string) || getWorkspaceId();
|
|
4291
|
+
const name = z.string().min(1).max(200).parse(args.name);
|
|
4292
|
+
const stepsVersion =
|
|
4293
|
+
args.stepsVersion !== undefined
|
|
4294
|
+
? z.union([z.literal(1), z.literal(2)]).parse(args.stepsVersion)
|
|
4295
|
+
: undefined;
|
|
4296
|
+
const result = await client.createPlaybook({
|
|
4297
|
+
workspaceId,
|
|
4298
|
+
name,
|
|
4299
|
+
description: args.description as string | undefined,
|
|
4300
|
+
steps: args.steps,
|
|
4301
|
+
stepsVersion,
|
|
4302
|
+
});
|
|
4303
|
+
return { success: true, playbook: result.playbook };
|
|
4304
|
+
}
|
|
4305
|
+
|
|
4306
|
+
case "harmony_update_playbook": {
|
|
4307
|
+
const playbookId = z.string().uuid().parse(args.playbookId);
|
|
4308
|
+
const result = await client.updatePlaybook(playbookId, {
|
|
4309
|
+
name: args.name as string | undefined,
|
|
4310
|
+
description: args.description as string | undefined,
|
|
4311
|
+
steps: args.steps,
|
|
4312
|
+
enabled: args.enabled as boolean | undefined,
|
|
4313
|
+
state: args.state as string | undefined,
|
|
4314
|
+
});
|
|
4315
|
+
return { success: true, playbook: result.playbook };
|
|
4316
|
+
}
|
|
4317
|
+
|
|
4318
|
+
case "harmony_save_card_as_playbook": {
|
|
4319
|
+
const cardId = z.string().uuid().parse(args.cardId);
|
|
4320
|
+
const result = await client.savePlaybookFromCard({
|
|
4321
|
+
cardId,
|
|
4322
|
+
name: args.name as string | undefined,
|
|
4323
|
+
});
|
|
4324
|
+
return { success: true, playbook: result.playbook };
|
|
4325
|
+
}
|
|
4326
|
+
|
|
4031
4327
|
// ============ ONBOARDING TOOLS ============
|
|
4032
4328
|
case "harmony_signup": {
|
|
4033
4329
|
const email = z.string().email().max(254).parse(args.email);
|