@codazen/harmonica-mcp 3.5.0 → 3.6.1
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/index.js +111 -376
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21587,6 +21587,18 @@ async function fetchProjectInOrg(client, projectId, orgId) {
|
|
|
21587
21587
|
}
|
|
21588
21588
|
return project;
|
|
21589
21589
|
}
|
|
21590
|
+
async function fetchSystemInOrg(client, systemId, orgId) {
|
|
21591
|
+
const system = await client.getSystem(systemId);
|
|
21592
|
+
if (!system) {
|
|
21593
|
+
throw new Error(`System not found: "${systemId}"`);
|
|
21594
|
+
}
|
|
21595
|
+
if (system.orgId !== orgId) {
|
|
21596
|
+
throw new Error(
|
|
21597
|
+
`System "${systemId}" does not belong to the configured organization. Access denied.`
|
|
21598
|
+
);
|
|
21599
|
+
}
|
|
21600
|
+
return system;
|
|
21601
|
+
}
|
|
21590
21602
|
async function fetchBeatInOrg(client, beatId, orgId) {
|
|
21591
21603
|
const beat = await client.getBeat(beatId);
|
|
21592
21604
|
if (!beat) {
|
|
@@ -21968,7 +21980,7 @@ function registerActivityTools(server, ctx, client) {
|
|
|
21968
21980
|
},
|
|
21969
21981
|
async ({ projectId, limit, importance }) => {
|
|
21970
21982
|
await assertProjectInOrg(client, projectId, ctx.orgId);
|
|
21971
|
-
const { entries, hasMore } = await client.
|
|
21983
|
+
const { entries, hasMore } = await client.listSystemActivities(projectId, {
|
|
21972
21984
|
limit: limit ?? 30,
|
|
21973
21985
|
minImportance: importance
|
|
21974
21986
|
});
|
|
@@ -22362,7 +22374,7 @@ function registerBeatConvergenceTools(server, ctx, client) {
|
|
|
22362
22374
|
{ beatId: external_exports.string().describe("The beat ID (e.g., TF-B-001)") },
|
|
22363
22375
|
async ({ beatId }) => {
|
|
22364
22376
|
const beat = await fetchBeatInOrg(client, beatId, ctx.orgId);
|
|
22365
|
-
const report = await client.getBeatConvergence(beat.projectId, beatId);
|
|
22377
|
+
const report = await client.getBeatConvergence(beat.systemId ?? beat.projectId, beatId);
|
|
22366
22378
|
if (!report) {
|
|
22367
22379
|
return { content: [{ type: "text", text: `No convergence data for beat "${beatId}".` }], isError: true };
|
|
22368
22380
|
}
|
|
@@ -22689,7 +22701,7 @@ function formatDeliveryPolicy(policy, unresolvedReason) {
|
|
|
22689
22701
|
}
|
|
22690
22702
|
function formatProjectContext(project, notes, orgCoda) {
|
|
22691
22703
|
const sections = [];
|
|
22692
|
-
sections.push(`#
|
|
22704
|
+
sections.push(`# System: ${project.title}`);
|
|
22693
22705
|
sections.push(`**ID:** ${project.projectId}`);
|
|
22694
22706
|
sections.push(`**Status:** ${project.status.replace("_", " ")}`);
|
|
22695
22707
|
if (project.repoOwner && project.repoName) {
|
|
@@ -22977,7 +22989,7 @@ function formatSessionDetail(session) {
|
|
|
22977
22989
|
"",
|
|
22978
22990
|
`**Type:** ${type}`,
|
|
22979
22991
|
`**Status:** ${status}`,
|
|
22980
|
-
`**Project:** ${session.projectId}`,
|
|
22992
|
+
`**Project:** ${session.systemId ?? session.projectId}`,
|
|
22981
22993
|
`**Actor:** ${session.actor.agentPersona}${session.actor.agentRole ? ` (${session.actor.agentRole})` : ""}`
|
|
22982
22994
|
];
|
|
22983
22995
|
if (session.actor.initiator) {
|
|
@@ -23131,7 +23143,7 @@ function registerBeatTools(server, ctx, client) {
|
|
|
23131
23143
|
},
|
|
23132
23144
|
async ({ beatId, projectId }) => {
|
|
23133
23145
|
const beat = await fetchBeatInOrg(client, beatId, ctx.orgId);
|
|
23134
|
-
const resolvedProjectId = projectId ?? beat.projectId;
|
|
23146
|
+
const resolvedProjectId = projectId ?? beat.systemId ?? beat.projectId;
|
|
23135
23147
|
const timeline = await client.getUnifiedBeatTimeline(resolvedProjectId, beatId);
|
|
23136
23148
|
if (timeline.length === 0) {
|
|
23137
23149
|
return { content: [{ type: "text", text: `No history for beat "${beatId}".` }] };
|
|
@@ -23245,7 +23257,7 @@ ${formatBeatDetail(beat)}${similarityWarning}` }] };
|
|
|
23245
23257
|
return { content: [{ type: "text", text: `Beat not found: "${beatId}"` }], isError: true };
|
|
23246
23258
|
}
|
|
23247
23259
|
await logBeatActivity(client, {
|
|
23248
|
-
projectId: beat.projectId,
|
|
23260
|
+
projectId: beat.systemId ?? beat.projectId,
|
|
23249
23261
|
action: "beat_updated",
|
|
23250
23262
|
beatIds: [beatId],
|
|
23251
23263
|
beatTitles: [updated.title],
|
|
@@ -23275,7 +23287,7 @@ ${formatBeatDetail(beat)}${similarityWarning}` }] };
|
|
|
23275
23287
|
async ({ projectId, beatId, status, includeArchived }) => {
|
|
23276
23288
|
try {
|
|
23277
23289
|
await assertProjectInOrg(client, projectId, ctx.orgId);
|
|
23278
|
-
const revisions = beatId ? await client.listBeatRevisions(projectId, beatId, { status, includeArchived }) : await client.
|
|
23290
|
+
const revisions = beatId ? await client.listBeatRevisions(projectId, beatId, { status, includeArchived }) : await client.listSystemRevisions(projectId, { status, includeArchived });
|
|
23279
23291
|
return { content: [{ type: "text", text: formatRevisionSummaryTable(revisions) }] };
|
|
23280
23292
|
} catch (err) {
|
|
23281
23293
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -23464,7 +23476,7 @@ function registerBeatVersionTools(server, ctx, client) {
|
|
|
23464
23476
|
return { content: [{ type: "text", text: `Beat not found: "${beatId}"` }], isError: true };
|
|
23465
23477
|
}
|
|
23466
23478
|
await assertBeatInOrg(client, beatId, ctx.orgId);
|
|
23467
|
-
const beatVersion = await client.createBeatVersion(beat.projectId, beatId, {
|
|
23479
|
+
const beatVersion = await client.createBeatVersion(beat.systemId ?? beat.projectId, beatId, {
|
|
23468
23480
|
title,
|
|
23469
23481
|
description,
|
|
23470
23482
|
scope,
|
|
@@ -23936,7 +23948,7 @@ function registerCheckTools(server, ctx, client) {
|
|
|
23936
23948
|
},
|
|
23937
23949
|
async ({ projectId }) => {
|
|
23938
23950
|
try {
|
|
23939
|
-
const checks = await client.
|
|
23951
|
+
const checks = await client.listLatestSystemChecks(projectId);
|
|
23940
23952
|
if (checks.length === 0) {
|
|
23941
23953
|
return { content: [{ type: "text", text: `No checks found for project ${projectId}.` }] };
|
|
23942
23954
|
}
|
|
@@ -24316,18 +24328,6 @@ ${g.acceptanceCriteria}` : null,
|
|
|
24316
24328
|
};
|
|
24317
24329
|
}
|
|
24318
24330
|
);
|
|
24319
|
-
server.tool(
|
|
24320
|
-
"list_deliverable_group_deliverables",
|
|
24321
|
-
'List all Deliverables assigned to a DeliverableGroup. Use to answer "what deliverables are in this phase/milestone?" or "what has the team committed to in this engagement group?"',
|
|
24322
|
-
{
|
|
24323
|
-
deliverableGroupId: external_exports.string().describe("The DeliverableGroup ID")
|
|
24324
|
-
},
|
|
24325
|
-
async ({ deliverableGroupId }) => {
|
|
24326
|
-
const items = await client.listDeliverableGroupDeliverables(deliverableGroupId);
|
|
24327
|
-
const text = items.length === 0 ? "No deliverables in this group." : items.map((d) => `[${d.deliverableId}] teamspace: ${d.teamspaceId}`).join("\n");
|
|
24328
|
-
return { content: [{ type: "text", text }] };
|
|
24329
|
-
}
|
|
24330
|
-
);
|
|
24331
24331
|
server.tool(
|
|
24332
24332
|
"list_deliverable_group_drops",
|
|
24333
24333
|
'List all Drops linked to a DeliverableGroup. Use to answer "what releases are part of this phase?" or "which software drops are tied to this engagement milestone?"',
|
|
@@ -24385,108 +24385,6 @@ ${g.acceptanceCriteria}` : null,
|
|
|
24385
24385
|
);
|
|
24386
24386
|
}
|
|
24387
24387
|
|
|
24388
|
-
// ../../libs/harmonica-services/src/mcp/tools/deliverable-tools.ts
|
|
24389
|
-
var import_node_crypto = require("node:crypto");
|
|
24390
|
-
function registerDeliverableTools(server, ctx, client) {
|
|
24391
|
-
server.tool(
|
|
24392
|
-
"list_deliverables",
|
|
24393
|
-
"List all Deliverables (tangible client-facing artifacts or milestones owed by a date \u2014 e.g. board deck, roadmap doc, audit report) for a Teamspace.",
|
|
24394
|
-
{
|
|
24395
|
-
teamspaceId: external_exports.string().describe("The teamspace ID")
|
|
24396
|
-
},
|
|
24397
|
-
async ({ teamspaceId }) => {
|
|
24398
|
-
const deliverables = await client.listTeamspaceDeliverables(teamspaceId);
|
|
24399
|
-
const text = deliverables.length === 0 ? "No deliverables found." : deliverables.map(
|
|
24400
|
-
(d) => `[${d.deliverableId}] ${d.title} \u2014 ${d.status}${d.dueDate ? ` (due ${d.dueDate})` : ""}${d.deliverableGroupId ? ` (group: ${d.deliverableGroupId})` : ""}`
|
|
24401
|
-
).join("\n");
|
|
24402
|
-
return { content: [{ type: "text", text }] };
|
|
24403
|
-
}
|
|
24404
|
-
);
|
|
24405
|
-
server.tool(
|
|
24406
|
-
"get_deliverable",
|
|
24407
|
-
"Get a Deliverable (tangible client-facing artifact or milestone) by ID.",
|
|
24408
|
-
{
|
|
24409
|
-
deliverableId: external_exports.string().describe("The deliverable ID")
|
|
24410
|
-
},
|
|
24411
|
-
async ({ deliverableId }) => {
|
|
24412
|
-
const d = await client.getDeliverable(deliverableId);
|
|
24413
|
-
if (!d) return { content: [{ type: "text", text: `Deliverable not found: ${deliverableId}` }] };
|
|
24414
|
-
const text = [
|
|
24415
|
-
`ID: ${d.deliverableId}`,
|
|
24416
|
-
`Title: ${d.title}`,
|
|
24417
|
-
`Teamspace: ${d.teamspaceId}`,
|
|
24418
|
-
`Status: ${d.status}`,
|
|
24419
|
-
d.description ? `Description: ${d.description}` : null,
|
|
24420
|
-
d.dueDate ? `Due: ${d.dueDate}` : null,
|
|
24421
|
-
d.deliverableGroupId ? `Group: ${d.deliverableGroupId}` : null,
|
|
24422
|
-
`Version: ${d.version}`,
|
|
24423
|
-
`Created: ${d.createdAt}`
|
|
24424
|
-
].filter(Boolean).join("\n");
|
|
24425
|
-
return { content: [{ type: "text", text }] };
|
|
24426
|
-
}
|
|
24427
|
-
);
|
|
24428
|
-
server.tool(
|
|
24429
|
-
"create_deliverable",
|
|
24430
|
-
'Create a Deliverable in a Teamspace. A Deliverable is a tangible commitment the agency owes the client by a date \u2014 board presentation, roadmap document, audit report, design mockups, training session, etc. Use this when the user describes something we will hand over. Do NOT use this for software capabilities the product provides to its end users \u2014 those are Beats (use create_beat). Do NOT use this for context, assumptions, constraints, or decisions \u2014 those are Notes (use create_note). Recognition cue: phrases like "we owe them\u2026", "due by\u2026", "the deck", "the report" \u2192 Deliverable. "Users will be able to\u2026", "the screen that\u2026" \u2192 Beat.',
|
|
24431
|
-
{
|
|
24432
|
-
teamspaceId: external_exports.string().describe("The teamspace ID"),
|
|
24433
|
-
title: external_exports.string().min(1).max(300).describe("Deliverable title"),
|
|
24434
|
-
description: external_exports.string().max(2e3).optional().describe("Optional description"),
|
|
24435
|
-
dueDate: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional().describe("Due date (YYYY-MM-DD)"),
|
|
24436
|
-
status: external_exports.enum(["draft", "active", "delivered", "cancelled"]).optional().describe("Initial status (default: draft)"),
|
|
24437
|
-
deliverableGroupId: external_exports.string().optional().describe("Assign to a DeliverableGroup by ID at creation time")
|
|
24438
|
-
},
|
|
24439
|
-
async ({ teamspaceId, title, description, dueDate, status, deliverableGroupId }) => {
|
|
24440
|
-
const deliverableId = `dlv-${(0, import_node_crypto.randomUUID)()}`;
|
|
24441
|
-
const d = await client.createDeliverable({
|
|
24442
|
-
deliverableId,
|
|
24443
|
-
teamspaceId,
|
|
24444
|
-
orgId: ctx.orgId,
|
|
24445
|
-
title,
|
|
24446
|
-
description,
|
|
24447
|
-
dueDate,
|
|
24448
|
-
status,
|
|
24449
|
-
createdBy: ctx.user.userId,
|
|
24450
|
-
...deliverableGroupId !== void 0 && { deliverableGroupId }
|
|
24451
|
-
});
|
|
24452
|
-
return {
|
|
24453
|
-
content: [{
|
|
24454
|
-
type: "text",
|
|
24455
|
-
text: `Created deliverable: [${d.deliverableId}] ${d.title} \u2014 ${d.status}`
|
|
24456
|
-
}]
|
|
24457
|
-
};
|
|
24458
|
-
}
|
|
24459
|
-
);
|
|
24460
|
-
server.tool(
|
|
24461
|
-
"update_deliverable",
|
|
24462
|
-
"Update an existing Deliverable. Transition status as the artifact progresses: draft \u2192 active \u2192 delivered (or cancelled).",
|
|
24463
|
-
{
|
|
24464
|
-
deliverableId: external_exports.string().describe("The deliverable ID"),
|
|
24465
|
-
title: external_exports.string().min(1).max(300).optional().describe("New title"),
|
|
24466
|
-
description: external_exports.string().max(2e3).optional().describe("New description"),
|
|
24467
|
-
dueDate: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional().describe("New due date (YYYY-MM-DD), or null to clear"),
|
|
24468
|
-
status: external_exports.enum(["draft", "active", "delivered", "cancelled"]).optional().describe("New status"),
|
|
24469
|
-
deliverableGroupId: external_exports.string().nullable().optional().describe("Assign to a DeliverableGroup by ID, or null to ungroup")
|
|
24470
|
-
},
|
|
24471
|
-
async ({ deliverableId, title, description, dueDate, status, deliverableGroupId }) => {
|
|
24472
|
-
const updates = {};
|
|
24473
|
-
if (title !== void 0) updates["title"] = title;
|
|
24474
|
-
if (description !== void 0) updates["description"] = description;
|
|
24475
|
-
if (dueDate !== void 0) updates["dueDate"] = dueDate;
|
|
24476
|
-
if (status !== void 0) updates["status"] = status;
|
|
24477
|
-
if (deliverableGroupId !== void 0) updates["deliverableGroupId"] = deliverableGroupId;
|
|
24478
|
-
const d = await client.updateDeliverable(deliverableId, updates);
|
|
24479
|
-
if (!d) return { content: [{ type: "text", text: `Deliverable not found: ${deliverableId}` }] };
|
|
24480
|
-
return {
|
|
24481
|
-
content: [{
|
|
24482
|
-
type: "text",
|
|
24483
|
-
text: `Updated deliverable: [${d.deliverableId}] ${d.title} \u2014 ${d.status}`
|
|
24484
|
-
}]
|
|
24485
|
-
};
|
|
24486
|
-
}
|
|
24487
|
-
);
|
|
24488
|
-
}
|
|
24489
|
-
|
|
24490
24388
|
// ../../libs/harmonica-services/src/mcp/tools/downbeat-harmony-report-tools.ts
|
|
24491
24389
|
function formatQualifyingBeat(b) {
|
|
24492
24390
|
return `- \`${b.beatId}\` ${b.title}: ${b.signals.join(", ")}`;
|
|
@@ -24549,7 +24447,7 @@ function registerDownbeatTools(server, ctx, client) {
|
|
|
24549
24447
|
{ beatId: external_exports.string().describe("The beat ID (e.g., TF-B-001)") },
|
|
24550
24448
|
async ({ beatId }) => {
|
|
24551
24449
|
const beat = await fetchBeatInOrg(client, beatId, ctx.orgId);
|
|
24552
|
-
const downbeat = await client.setDownbeat(beat.projectId, beatId);
|
|
24450
|
+
const downbeat = await client.setDownbeat(beat.systemId ?? beat.projectId, beatId);
|
|
24553
24451
|
if (!downbeat) {
|
|
24554
24452
|
return { content: [{ type: "text", text: `Could not set a Downbeat for beat "${beatId}".` }], isError: true };
|
|
24555
24453
|
}
|
|
@@ -24562,7 +24460,7 @@ function registerDownbeatTools(server, ctx, client) {
|
|
|
24562
24460
|
{ beatId: external_exports.string().describe("The beat ID (e.g., TF-B-001)") },
|
|
24563
24461
|
async ({ beatId }) => {
|
|
24564
24462
|
const beat = await fetchBeatInOrg(client, beatId, ctx.orgId);
|
|
24565
|
-
const result = await client.listIncrementsSinceDownbeat(beat.projectId, beatId);
|
|
24463
|
+
const result = await client.listIncrementsSinceDownbeat(beat.systemId ?? beat.projectId, beatId);
|
|
24566
24464
|
if (!result) {
|
|
24567
24465
|
return { content: [{ type: "text", text: `No such beat "${beatId}".` }], isError: true };
|
|
24568
24466
|
}
|
|
@@ -24575,7 +24473,7 @@ function registerDownbeatTools(server, ctx, client) {
|
|
|
24575
24473
|
{ beatId: external_exports.string().describe("The beat ID (e.g., TF-B-001)") },
|
|
24576
24474
|
async ({ beatId }) => {
|
|
24577
24475
|
const beat = await fetchBeatInOrg(client, beatId, ctx.orgId);
|
|
24578
|
-
const report = await client.getCodaDrift(beat.projectId, beatId);
|
|
24476
|
+
const report = await client.getCodaDrift(beat.systemId ?? beat.projectId, beatId);
|
|
24579
24477
|
if (!report) {
|
|
24580
24478
|
return { content: [{ type: "text", text: `No such beat "${beatId}".` }], isError: true };
|
|
24581
24479
|
}
|
|
@@ -24588,7 +24486,7 @@ function registerDownbeatTools(server, ctx, client) {
|
|
|
24588
24486
|
{ beatId: external_exports.string().describe("The beat ID (e.g., TF-B-001)") },
|
|
24589
24487
|
async ({ beatId }) => {
|
|
24590
24488
|
const beat = await fetchBeatInOrg(client, beatId, ctx.orgId);
|
|
24591
|
-
const report = await client.getRelationalDrift(beat.projectId, beatId);
|
|
24489
|
+
const report = await client.getRelationalDrift(beat.systemId ?? beat.projectId, beatId);
|
|
24592
24490
|
if (!report) {
|
|
24593
24491
|
return { content: [{ type: "text", text: `No such beat "${beatId}".` }], isError: true };
|
|
24594
24492
|
}
|
|
@@ -28513,7 +28411,7 @@ ${lines.join("\n")}` }] };
|
|
|
28513
28411
|
}
|
|
28514
28412
|
|
|
28515
28413
|
// ../../libs/harmonica-services/src/mcp/tools/onboarding-tools.ts
|
|
28516
|
-
var
|
|
28414
|
+
var import_node_crypto = require("node:crypto");
|
|
28517
28415
|
var OnboardingNoteInputSchema = external_exports.object({
|
|
28518
28416
|
noteType: external_exports.enum(["context", "assumption", "constraint", "guidance", "decision"]),
|
|
28519
28417
|
content: external_exports.string().min(1),
|
|
@@ -28525,11 +28423,6 @@ var OnboardingProjectInputSchema = external_exports.object({
|
|
|
28525
28423
|
description: external_exports.string().max(2e3).optional(),
|
|
28526
28424
|
notes: external_exports.array(OnboardingNoteInputSchema).optional()
|
|
28527
28425
|
});
|
|
28528
|
-
var OnboardingDeliverableInputSchema = external_exports.object({
|
|
28529
|
-
title: external_exports.string().min(1).max(300),
|
|
28530
|
-
description: external_exports.string().max(2e3).optional(),
|
|
28531
|
-
dueDate: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional()
|
|
28532
|
-
});
|
|
28533
28426
|
function registerOnboardingTools(server, ctx, client) {
|
|
28534
28427
|
server.tool(
|
|
28535
28428
|
"initiate_teamspace_onboarding",
|
|
@@ -28627,7 +28520,7 @@ function registerOnboardingTools(server, ctx, client) {
|
|
|
28627
28520
|
server.tool(
|
|
28628
28521
|
"create_teamspace_onboarding_batch",
|
|
28629
28522
|
[
|
|
28630
|
-
"Create a Teamspace, Projects,
|
|
28523
|
+
"Create a Teamspace, Projects, and Notes",
|
|
28631
28524
|
"from a PM-approved onboarding payload in a single batch operation.",
|
|
28632
28525
|
"Call this after the PM approves the pre-flight review card from initiate_teamspace_onboarding.",
|
|
28633
28526
|
"Returns a creation receipt with IDs and counts for all created entities.",
|
|
@@ -28636,20 +28529,18 @@ function registerOnboardingTools(server, ctx, client) {
|
|
|
28636
28529
|
{
|
|
28637
28530
|
teamspaceName: external_exports.string().min(1).max(200).describe("Teamspace display name"),
|
|
28638
28531
|
projects: external_exports.array(OnboardingProjectInputSchema).min(1).describe("Phase 1 projects to create, each linked to the Teamspace"),
|
|
28639
|
-
teamspaceNotes: external_exports.array(OnboardingNoteInputSchema).describe("Constraints, assumptions, and context notes at the Teamspace/project level")
|
|
28640
|
-
deliverables: external_exports.array(OnboardingDeliverableInputSchema).describe("Deliverables detected from commitment language in documents")
|
|
28532
|
+
teamspaceNotes: external_exports.array(OnboardingNoteInputSchema).describe("Constraints, assumptions, and context notes at the Teamspace/project level")
|
|
28641
28533
|
},
|
|
28642
28534
|
async ({
|
|
28643
28535
|
teamspaceName,
|
|
28644
28536
|
projects,
|
|
28645
|
-
teamspaceNotes
|
|
28646
|
-
deliverables
|
|
28537
|
+
teamspaceNotes
|
|
28647
28538
|
}) => {
|
|
28648
28539
|
const lines = [];
|
|
28649
28540
|
let teamspace;
|
|
28650
28541
|
try {
|
|
28651
28542
|
teamspace = await client.createTeamspace({
|
|
28652
|
-
teamspaceId: (0,
|
|
28543
|
+
teamspaceId: (0, import_node_crypto.randomUUID)(),
|
|
28653
28544
|
slug: teamspaceName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, ""),
|
|
28654
28545
|
orgId: ctx.orgId,
|
|
28655
28546
|
name: teamspaceName,
|
|
@@ -28666,8 +28557,8 @@ Error: ${msg}`);
|
|
|
28666
28557
|
const createdProjects = [];
|
|
28667
28558
|
for (const p of projects) {
|
|
28668
28559
|
try {
|
|
28669
|
-
const project = await client.
|
|
28670
|
-
projectId: (0,
|
|
28560
|
+
const project = await client.createSystem({
|
|
28561
|
+
projectId: (0, import_node_crypto.randomUUID)(),
|
|
28671
28562
|
orgId: ctx.orgId,
|
|
28672
28563
|
teamspaceId: teamspace.teamspaceId,
|
|
28673
28564
|
ownerUserId: ctx.user?.userId ?? "system",
|
|
@@ -28711,7 +28602,7 @@ Projects (${createdProjects.length}):`);
|
|
|
28711
28602
|
for (const note of projects[i]?.notes ?? []) {
|
|
28712
28603
|
try {
|
|
28713
28604
|
const n = await client.createNote({
|
|
28714
|
-
noteId: `N-TEMP-${(0,
|
|
28605
|
+
noteId: `N-TEMP-${(0, import_node_crypto.randomUUID)()}`,
|
|
28715
28606
|
// overridden server-side
|
|
28716
28607
|
projectId: project.projectId,
|
|
28717
28608
|
noteType: note.noteType,
|
|
@@ -28728,24 +28619,6 @@ Projects (${createdProjects.length}):`);
|
|
|
28728
28619
|
}
|
|
28729
28620
|
lines.push(`
|
|
28730
28621
|
Notes filed: ${createdNotes.length}`);
|
|
28731
|
-
const createdDeliverables = [];
|
|
28732
|
-
for (const d of deliverables) {
|
|
28733
|
-
try {
|
|
28734
|
-
const del = await client.createDeliverable({
|
|
28735
|
-
deliverableId: (0, import_node_crypto2.randomUUID)(),
|
|
28736
|
-
// overridden server-side
|
|
28737
|
-
teamspaceId: teamspace.teamspaceId,
|
|
28738
|
-
orgId: ctx.orgId,
|
|
28739
|
-
title: d.title,
|
|
28740
|
-
description: d.description,
|
|
28741
|
-
dueDate: d.dueDate,
|
|
28742
|
-
createdBy: ctx.user?.userId ?? "mcp"
|
|
28743
|
-
});
|
|
28744
|
-
createdDeliverables.push(del.deliverableId);
|
|
28745
|
-
} catch {
|
|
28746
|
-
}
|
|
28747
|
-
}
|
|
28748
|
-
lines.push(`Deliverables: ${createdDeliverables.length}`);
|
|
28749
28622
|
lines.unshift(`\u2705 Onboarding batch created successfully.`);
|
|
28750
28623
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
28751
28624
|
}
|
|
@@ -29455,11 +29328,11 @@ function registerRevisionLifecycleTools(server, ctx, client) {
|
|
|
29455
29328
|
if (!parentBv) {
|
|
29456
29329
|
return { content: [{ type: "text", text: `Beat Version not found: "${beatVersionId}"` }], isError: true };
|
|
29457
29330
|
}
|
|
29458
|
-
if (parentBv.beatId !== beatId || parentBv.projectId !== beat.projectId) {
|
|
29331
|
+
if (parentBv.beatId !== beatId || (parentBv.systemId ?? parentBv.projectId) !== (beat.systemId ?? beat.projectId)) {
|
|
29459
29332
|
return { content: [{ type: "text", text: `Beat Version "${beatVersionId}" belongs to a different Beat.` }], isError: true };
|
|
29460
29333
|
}
|
|
29461
29334
|
}
|
|
29462
|
-
const { revision, warnings } = await client.createRevision(beat.projectId, beatId, {
|
|
29335
|
+
const { revision, warnings } = await client.createRevision(beat.systemId ?? beat.projectId, beatId, {
|
|
29463
29336
|
title,
|
|
29464
29337
|
description,
|
|
29465
29338
|
changeSummary,
|
|
@@ -29547,7 +29420,7 @@ function registerRevisionLifecycleTools(server, ctx, client) {
|
|
|
29547
29420
|
if (!bv) {
|
|
29548
29421
|
return { content: [{ type: "text", text: `Beat Version not found: "${beatVersionId}"` }], isError: true };
|
|
29549
29422
|
}
|
|
29550
|
-
if (bv.beatId !== revision.beatId || bv.projectId !== revision.projectId) {
|
|
29423
|
+
if (bv.beatId !== revision.beatId || (bv.systemId ?? bv.projectId) !== (revision.systemId ?? revision.projectId)) {
|
|
29551
29424
|
return { content: [{ type: "text", text: `Beat Version "${beatVersionId}" belongs to a different Beat.` }], isError: true };
|
|
29552
29425
|
}
|
|
29553
29426
|
}
|
|
@@ -30051,7 +29924,7 @@ function registerSessionTools(server, ctx, client) {
|
|
|
30051
29924
|
includeTerminal: external_exports.boolean().optional().describe("Include terminal (closed) sessions. Default false.")
|
|
30052
29925
|
},
|
|
30053
29926
|
async ({ systemId, status, includeTerminal }) => {
|
|
30054
|
-
const sessions = await client.
|
|
29927
|
+
const sessions = await client.listSystemSessions(systemId, {
|
|
30055
29928
|
status,
|
|
30056
29929
|
includeTerminal
|
|
30057
29930
|
});
|
|
@@ -30718,7 +30591,7 @@ function registerProjectTools(server, ctx, client) {
|
|
|
30718
30591
|
fetchProjectInOrg(client, systemId, ctx.orgId),
|
|
30719
30592
|
client.getOrg(ctx.orgId)
|
|
30720
30593
|
]);
|
|
30721
|
-
const notes = await client.
|
|
30594
|
+
const notes = await client.listSystemNotes(systemId, {
|
|
30722
30595
|
limit: noteLimit ?? DEFAULT_CONTEXT_NOTE_LIMIT
|
|
30723
30596
|
});
|
|
30724
30597
|
const text = formatProjectContext(project, notes, org?.coda);
|
|
@@ -30886,7 +30759,7 @@ function registerProjectTools(server, ctx, client) {
|
|
|
30886
30759
|
}
|
|
30887
30760
|
|
|
30888
30761
|
// ../../libs/harmonica-services/src/mcp/tools/teamspace-tools.ts
|
|
30889
|
-
var
|
|
30762
|
+
var import_node_crypto2 = require("node:crypto");
|
|
30890
30763
|
var EnsembleMemberSchema = external_exports.discriminatedUnion("type", [
|
|
30891
30764
|
external_exports.object({ type: external_exports.literal("human"), email: external_exports.string().email().max(254), name: external_exports.string().min(1).max(200) }),
|
|
30892
30765
|
external_exports.object({ type: external_exports.literal("agent"), agentId: external_exports.string().min(1).max(100), name: external_exports.string().min(1).max(200) })
|
|
@@ -30925,7 +30798,7 @@ function registerTeamspaceTools(server, ctx, client) {
|
|
|
30925
30798
|
if (!ts || ts.orgId !== ctx.orgId) {
|
|
30926
30799
|
return { content: [{ type: "text", text: `Teamspace not found: ${teamspaceId}` }], isError: true };
|
|
30927
30800
|
}
|
|
30928
|
-
const allProjects = await client.
|
|
30801
|
+
const allProjects = await client.listOrgSystems(ctx.orgId);
|
|
30929
30802
|
const tsProjects = allProjects.filter((p) => p.teamspaceId === teamspaceId);
|
|
30930
30803
|
const lines = [
|
|
30931
30804
|
`ID: ${ts.teamspaceId}`,
|
|
@@ -30962,7 +30835,7 @@ function registerTeamspaceTools(server, ctx, client) {
|
|
|
30962
30835
|
name: external_exports.string().min(1).max(200).describe("Teamspace name")
|
|
30963
30836
|
},
|
|
30964
30837
|
async ({ name }) => {
|
|
30965
|
-
const teamspaceId = `ts-${(0,
|
|
30838
|
+
const teamspaceId = `ts-${(0, import_node_crypto2.randomUUID)()}`;
|
|
30966
30839
|
const slug = generateTeamspaceSlug(name);
|
|
30967
30840
|
const ts = await client.createTeamspace({
|
|
30968
30841
|
teamspaceId,
|
|
@@ -31100,7 +30973,7 @@ function registerValueVelocityTools(server, ctx, client) {
|
|
|
31100
30973
|
try {
|
|
31101
30974
|
await assertProjectInOrg(client, systemId, ctx.orgId);
|
|
31102
30975
|
const [rankedResult, staleWResult] = await Promise.allSettled([
|
|
31103
|
-
withLeverage ? client.
|
|
30976
|
+
withLeverage ? client.rankSystemBeatVersionsWithLeverage(systemId, lens) : client.rankSystemBeatVersions(systemId, lens),
|
|
31104
30977
|
client.getStaleWBeatIds(systemId)
|
|
31105
30978
|
]);
|
|
31106
30979
|
if (rankedResult.status === "rejected") {
|
|
@@ -31594,7 +31467,7 @@ ${JSON.stringify(task.result, null, 2)}
|
|
|
31594
31467
|
},
|
|
31595
31468
|
async ({ projectId, status, limit }) => {
|
|
31596
31469
|
await assertProjectInOrg(client, projectId, ctx.orgId);
|
|
31597
|
-
const tasks = await client.
|
|
31470
|
+
const tasks = await client.listSystemTasks(projectId, {
|
|
31598
31471
|
status,
|
|
31599
31472
|
limit
|
|
31600
31473
|
});
|
|
@@ -31652,7 +31525,7 @@ ${JSON.stringify(task.result, null, 2)}
|
|
|
31652
31525
|
},
|
|
31653
31526
|
async ({ projectId, status, limit }) => {
|
|
31654
31527
|
await assertProjectInOrg(client, projectId, ctx.orgId);
|
|
31655
|
-
const tasks = await client.
|
|
31528
|
+
const tasks = await client.listSystemTasks(projectId, {
|
|
31656
31529
|
status,
|
|
31657
31530
|
limit
|
|
31658
31531
|
});
|
|
@@ -31954,7 +31827,6 @@ var TOOL_PROFILES = Object.freeze({
|
|
|
31954
31827
|
allow(registerBeatVersionTools, ["list_beat_versions", "get_beat_version"]),
|
|
31955
31828
|
allow(registerNoteTools, ["list_notes", "get_note", "create_note", "list_documents"]),
|
|
31956
31829
|
allow(registerDropTools, ["list_drops", "get_drop"]),
|
|
31957
|
-
allow(registerDeliverableTools, ["list_deliverables", "get_deliverable"]),
|
|
31958
31830
|
allow(registerEmbeddingTools, ["search", "find_similar_notes"])
|
|
31959
31831
|
])
|
|
31960
31832
|
});
|
|
@@ -32007,7 +31879,6 @@ function registerAllTools(server, ctx, client, profile) {
|
|
|
32007
31879
|
registerBaselineTools(server, ctx, client);
|
|
32008
31880
|
registerTeamspaceTools(server, ctx, client);
|
|
32009
31881
|
registerDeliverableGroupTools(server, ctx, client);
|
|
32010
|
-
registerDeliverableTools(server, ctx, client);
|
|
32011
31882
|
registerDropTools(server, ctx, client);
|
|
32012
31883
|
registerSessionTools(server, ctx, client);
|
|
32013
31884
|
registerOnboardingTools(server, ctx, client);
|
|
@@ -32026,12 +31897,12 @@ function registerAllTools(server, ctx, client, profile) {
|
|
|
32026
31897
|
// ../../libs/harmonica-services/src/mcp/resources/beat-resources.ts
|
|
32027
31898
|
function registerBeatResources(server, ctx, client) {
|
|
32028
31899
|
server.resource(
|
|
32029
|
-
"
|
|
32030
|
-
new ResourceTemplate("harmonica://
|
|
32031
|
-
async (uri, {
|
|
32032
|
-
const
|
|
32033
|
-
await
|
|
32034
|
-
const beats = await client.listSystemBeats(
|
|
31900
|
+
"system-beats",
|
|
31901
|
+
new ResourceTemplate("harmonica://system/{systemId}/beats", { list: void 0 }),
|
|
31902
|
+
async (uri, { systemId }) => {
|
|
31903
|
+
const sid = String(systemId);
|
|
31904
|
+
await fetchSystemInOrg(client, sid, ctx.orgId);
|
|
31905
|
+
const beats = await client.listSystemBeats(sid);
|
|
32035
31906
|
const text = formatBeatSummaryTable(beats);
|
|
32036
31907
|
return { contents: [{ uri: uri.href, text }] };
|
|
32037
31908
|
}
|
|
@@ -32066,14 +31937,14 @@ function registerGuidelinesResources(server, client) {
|
|
|
32066
31937
|
}
|
|
32067
31938
|
|
|
32068
31939
|
// ../../libs/harmonica-services/src/mcp/resources/system-resources.ts
|
|
32069
|
-
function
|
|
31940
|
+
function registerSystemResources(server, ctx, client) {
|
|
32070
31941
|
server.resource(
|
|
32071
|
-
"
|
|
32072
|
-
new ResourceTemplate("harmonica://
|
|
32073
|
-
async (uri, {
|
|
32074
|
-
const
|
|
32075
|
-
const project = await
|
|
32076
|
-
const notes = await client.listSystemNotes(
|
|
31942
|
+
"system-context",
|
|
31943
|
+
new ResourceTemplate("harmonica://system/{systemId}/context", { list: void 0 }),
|
|
31944
|
+
async (uri, { systemId }) => {
|
|
31945
|
+
const sid = String(systemId);
|
|
31946
|
+
const project = await fetchSystemInOrg(client, sid, ctx.orgId);
|
|
31947
|
+
const notes = await client.listSystemNotes(sid, { limit: DEFAULT_CONTEXT_NOTE_LIMIT });
|
|
32077
31948
|
const text = formatProjectContext(project, notes);
|
|
32078
31949
|
return { contents: [{ uri: uri.href, text }] };
|
|
32079
31950
|
}
|
|
@@ -32082,7 +31953,7 @@ function registerProjectResources(server, ctx, client) {
|
|
|
32082
31953
|
|
|
32083
31954
|
// ../../libs/harmonica-services/src/mcp/resources/index.ts
|
|
32084
31955
|
function registerAllResources(server, ctx, client) {
|
|
32085
|
-
|
|
31956
|
+
registerSystemResources(server, ctx, client);
|
|
32086
31957
|
registerBeatResources(server, ctx, client);
|
|
32087
31958
|
registerGuidelinesResources(server, client);
|
|
32088
31959
|
}
|
|
@@ -32353,46 +32224,11 @@ function createHttpClient(config2) {
|
|
|
32353
32224
|
if (!raw) return void 0;
|
|
32354
32225
|
return { ...raw, projectId: raw.id ?? raw.projectId, title: raw.name ?? raw.title, orgId: raw.organizationId ?? raw.orgId };
|
|
32355
32226
|
},
|
|
32356
|
-
// @deprecated aliases — remove in cleanup increment (BV2)
|
|
32357
|
-
listOrgProjects: async (orgId) => {
|
|
32358
|
-
const raw = await request("GET", `/api/organizations/${encodeURIComponent(orgId)}/projects/summaries`);
|
|
32359
|
-
return (raw ?? []).map((p) => ({ ...p, projectId: p.id, title: p.name, orgId: p.organizationId }));
|
|
32360
|
-
},
|
|
32361
|
-
getProject: async (projectId) => {
|
|
32362
|
-
const raw = await request("GET", `/api/systems/${encodeURIComponent(projectId)}`);
|
|
32363
|
-
if (!raw) return void 0;
|
|
32364
|
-
return {
|
|
32365
|
-
...raw,
|
|
32366
|
-
projectId: raw.id ?? raw.projectId,
|
|
32367
|
-
title: raw.name ?? raw.title,
|
|
32368
|
-
orgId: raw.organizationId ?? raw.orgId
|
|
32369
|
-
};
|
|
32370
|
-
},
|
|
32371
|
-
createProject: async (input) => {
|
|
32372
|
-
const raw = await request("POST", "/api/systems", {
|
|
32373
|
-
organizationId: input.orgId,
|
|
32374
|
-
teamspaceId: input.teamspaceId,
|
|
32375
|
-
name: input.title,
|
|
32376
|
-
description: input.description,
|
|
32377
|
-
strategy: input.strategy,
|
|
32378
|
-
// Without this the owning Account is dropped on the wire and the System
|
|
32379
|
-
// is created unlinked — invisible in the Account's Systems list.
|
|
32380
|
-
...input.accountId !== void 0 && { accountId: input.accountId }
|
|
32381
|
-
});
|
|
32382
|
-
return { ...raw, orgId: raw?.organizationId ?? raw?.orgId };
|
|
32383
|
-
},
|
|
32384
|
-
updateProject: (projectId, updates) => request("PATCH", `/api/systems/${encodeURIComponent(projectId)}`, updates),
|
|
32385
|
-
archiveProject: (projectId) => request("PATCH", `/api/systems/${encodeURIComponent(projectId)}/archive`),
|
|
32386
32227
|
getSystemFact: async (projectId) => {
|
|
32387
32228
|
const result = await request("GET", `/api/systems/${encodeURIComponent(projectId)}/facts`);
|
|
32388
32229
|
return result?.data;
|
|
32389
32230
|
},
|
|
32390
|
-
getProjectFact: async (projectId) => {
|
|
32391
|
-
const result = await request("GET", `/api/systems/${encodeURIComponent(projectId)}/facts`);
|
|
32392
|
-
return result?.data;
|
|
32393
|
-
},
|
|
32394
32231
|
saveSystemFact: (input) => request("PUT", `/api/systems/${encodeURIComponent(String(input.projectId))}/facts`, input),
|
|
32395
|
-
saveProjectFact: (input) => request("PUT", `/api/systems/${encodeURIComponent(String(input.projectId))}/facts`, input),
|
|
32396
32232
|
transitionSystemLifecycleState: async (projectId, targetState, options) => {
|
|
32397
32233
|
return request("POST", `/api/systems/${encodeURIComponent(projectId)}/lifecycle/transitions`, {
|
|
32398
32234
|
targetState,
|
|
@@ -32400,13 +32236,6 @@ function createHttpClient(config2) {
|
|
|
32400
32236
|
decisionNoteId: options.decisionNoteId
|
|
32401
32237
|
});
|
|
32402
32238
|
},
|
|
32403
|
-
transitionProjectLifecycleState: async (projectId, targetState, options) => {
|
|
32404
|
-
return request("POST", `/api/systems/${encodeURIComponent(projectId)}/lifecycle/transitions`, {
|
|
32405
|
-
targetState,
|
|
32406
|
-
reason: options.reason,
|
|
32407
|
-
decisionNoteId: options.decisionNoteId
|
|
32408
|
-
});
|
|
32409
|
-
},
|
|
32410
32239
|
// Beats
|
|
32411
32240
|
getNextBeatId: async (projectId) => {
|
|
32412
32241
|
const result = await request("POST", `/api/systems/${encodeURIComponent(projectId)}/beats/next-id`);
|
|
@@ -32424,7 +32253,7 @@ function createHttpClient(config2) {
|
|
|
32424
32253
|
getBeat: async (beatId) => {
|
|
32425
32254
|
const raw = await request("GET", `/api/beats/${encodeURIComponent(beatId)}`);
|
|
32426
32255
|
if (!raw) return void 0;
|
|
32427
|
-
return { ...raw, beatId: raw.beatId ?? raw.id, status: raw.status ?? "open", beatStatus: coerceBeatStatusLocal(raw.beatStatus) };
|
|
32256
|
+
return { ...raw, beatId: raw.beatId ?? raw.id, projectId: raw.projectId ?? raw.systemId, status: raw.status ?? "open", beatStatus: coerceBeatStatusLocal(raw.beatStatus) };
|
|
32428
32257
|
},
|
|
32429
32258
|
getBeatConvergence: async (projectId, beatId) => {
|
|
32430
32259
|
const raw = await request(
|
|
@@ -32471,7 +32300,9 @@ function createHttpClient(config2) {
|
|
|
32471
32300
|
}
|
|
32472
32301
|
const beat = await request("GET", `/api/beats/${encodeURIComponent(beatId)}`);
|
|
32473
32302
|
if (!beat) return void 0;
|
|
32474
|
-
const
|
|
32303
|
+
const systemId = beat.systemId ?? beat.projectId;
|
|
32304
|
+
if (!systemId) return void 0;
|
|
32305
|
+
const result = await request("PUT", `/api/systems/${encodeURIComponent(systemId)}/beats/${encodeURIComponent(beatId)}`, updates);
|
|
32475
32306
|
const raw = result?.beat ?? result;
|
|
32476
32307
|
return { ...raw, beatStatus: coerceBeatStatusLocal(raw.beatStatus) };
|
|
32477
32308
|
},
|
|
@@ -32584,22 +32415,6 @@ function createHttpClient(config2) {
|
|
|
32584
32415
|
const result = await request("GET", `/api/systems/${encodeURIComponent(projectId)}/notes${qs}`);
|
|
32585
32416
|
return result?.notes ?? [];
|
|
32586
32417
|
},
|
|
32587
|
-
listProjectNotes: async (projectId, filters) => {
|
|
32588
|
-
const params = new URLSearchParams();
|
|
32589
|
-
if (filters?.noteType) {
|
|
32590
|
-
const types = Array.isArray(filters.noteType) ? filters.noteType : [filters.noteType];
|
|
32591
|
-
types.forEach((t) => params.append("type", t));
|
|
32592
|
-
}
|
|
32593
|
-
if (filters?.status) params.set("status", filters.status);
|
|
32594
|
-
if (filters?.revisionId) params.set("revisionId", filters.revisionId);
|
|
32595
|
-
if (filters?.beatVersionId) params.set("beatVersionId", filters.beatVersionId);
|
|
32596
|
-
if (filters?.excludeChildren) params.set("excludeChildren", "true");
|
|
32597
|
-
if (filters?.significance) params.set("significance", filters.significance);
|
|
32598
|
-
if (filters?.limit !== void 0) params.set("limit", String(filters.limit));
|
|
32599
|
-
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
32600
|
-
const result = await request("GET", `/api/systems/${encodeURIComponent(projectId)}/notes${qs}`);
|
|
32601
|
-
return result?.notes ?? [];
|
|
32602
|
-
},
|
|
32603
32418
|
listAllSystemNotes: async (projectId, filters, limit, cursor) => {
|
|
32604
32419
|
const params = new URLSearchParams();
|
|
32605
32420
|
if (filters?.noteType) {
|
|
@@ -32618,27 +32433,11 @@ function createHttpClient(config2) {
|
|
|
32618
32433
|
const result = await request("GET", `/api/systems/${encodeURIComponent(projectId)}/notes/all${qs}`);
|
|
32619
32434
|
return { notes: result?.notes ?? [], cursor: result?.cursor, hasMore: result?.hasMore ?? false };
|
|
32620
32435
|
},
|
|
32621
|
-
listAllProjectNotes: async (projectId, filters, limit, cursor) => {
|
|
32622
|
-
const params = new URLSearchParams();
|
|
32623
|
-
if (filters?.noteType) {
|
|
32624
|
-
const types = Array.isArray(filters.noteType) ? filters.noteType : [filters.noteType];
|
|
32625
|
-
types.forEach((t) => params.append("type", t));
|
|
32626
|
-
}
|
|
32627
|
-
if (filters?.excludeNoteType) params.set("excludeType", filters.excludeNoteType);
|
|
32628
|
-
if (filters?.status) params.set("status", filters.status);
|
|
32629
|
-
if (filters?.revisionId) params.set("revisionId", filters.revisionId);
|
|
32630
|
-
if (filters?.beatVersionId) params.set("beatVersionId", filters.beatVersionId);
|
|
32631
|
-
if (filters?.excludeChildren) params.set("excludeChildren", "true");
|
|
32632
|
-
if (filters?.significance) params.set("significance", filters.significance);
|
|
32633
|
-
if (limit !== void 0) params.set("limit", String(limit));
|
|
32634
|
-
if (cursor !== void 0) params.set("cursor", cursor);
|
|
32635
|
-
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
32636
|
-
const result = await request("GET", `/api/systems/${encodeURIComponent(projectId)}/notes/all${qs}`);
|
|
32637
|
-
return { notes: result?.notes ?? [], cursor: result?.cursor, hasMore: result?.hasMore ?? false };
|
|
32638
|
-
},
|
|
32639
32436
|
listBeatNotes: async (beatId, filters) => {
|
|
32640
32437
|
const beat = await request("GET", `/api/beats/${encodeURIComponent(beatId)}`);
|
|
32641
32438
|
if (!beat) return [];
|
|
32439
|
+
const systemId = beat.systemId ?? beat.projectId;
|
|
32440
|
+
if (!systemId) return [];
|
|
32642
32441
|
const params = new URLSearchParams();
|
|
32643
32442
|
if (filters?.noteType) {
|
|
32644
32443
|
const types = Array.isArray(filters.noteType) ? filters.noteType : [filters.noteType];
|
|
@@ -32650,7 +32449,7 @@ function createHttpClient(config2) {
|
|
|
32650
32449
|
if (filters?.excludeChildren) params.set("excludeChildren", "true");
|
|
32651
32450
|
if (filters?.significance) params.set("significance", filters.significance);
|
|
32652
32451
|
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
32653
|
-
const result = await request("GET", `/api/systems/${encodeURIComponent(
|
|
32452
|
+
const result = await request("GET", `/api/systems/${encodeURIComponent(systemId)}/beats/${encodeURIComponent(beatId)}/notes${qs}`);
|
|
32654
32453
|
return result?.notes ?? [];
|
|
32655
32454
|
},
|
|
32656
32455
|
getNote: async (noteId) => {
|
|
@@ -32728,7 +32527,6 @@ function createHttpClient(config2) {
|
|
|
32728
32527
|
},
|
|
32729
32528
|
// Gaps are deprecated — replaced by assumption Notes. Return empty results.
|
|
32730
32529
|
getSystemGaps: async () => [],
|
|
32731
|
-
getProjectGaps: async () => [],
|
|
32732
32530
|
updateInformationGap: async () => false,
|
|
32733
32531
|
// Revisions
|
|
32734
32532
|
createRevision: async (projectId, beatId, input) => {
|
|
@@ -32753,14 +32551,6 @@ function createHttpClient(config2) {
|
|
|
32753
32551
|
const result = await request("GET", `/api/systems/${encodeURIComponent(projectId)}/revisions${qs}`);
|
|
32754
32552
|
return result ?? [];
|
|
32755
32553
|
},
|
|
32756
|
-
listProjectRevisions: async (projectId, options) => {
|
|
32757
|
-
const params = new URLSearchParams();
|
|
32758
|
-
if (options?.status) params.set("status", options.status);
|
|
32759
|
-
if (options?.includeArchived) params.set("includeArchived", "true");
|
|
32760
|
-
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
32761
|
-
const result = await request("GET", `/api/systems/${encodeURIComponent(projectId)}/revisions${qs}`);
|
|
32762
|
-
return result ?? [];
|
|
32763
|
-
},
|
|
32764
32554
|
listBeatRevisions: async (projectId, beatId, options) => {
|
|
32765
32555
|
const params = new URLSearchParams();
|
|
32766
32556
|
params.set("beatId", beatId);
|
|
@@ -32982,17 +32772,9 @@ function createHttpClient(config2) {
|
|
|
32982
32772
|
// partitions, but the REST surface is unified per the project-level
|
|
32983
32773
|
// "avoid nested/duplicate routes" guidance.
|
|
32984
32774
|
getSession: (sessionId) => request("GET", `/api/sessions/${encodeURIComponent(sessionId)}`),
|
|
32985
|
-
listSystemSessions: async (
|
|
32775
|
+
listSystemSessions: async (systemId, options) => {
|
|
32986
32776
|
const params = new URLSearchParams();
|
|
32987
|
-
params.set("
|
|
32988
|
-
if (options?.status) params.set("status", options.status);
|
|
32989
|
-
if (options?.includeTerminal) params.set("includeTerminal", "true");
|
|
32990
|
-
const result = await request("GET", `/api/sessions?${params.toString()}`);
|
|
32991
|
-
return result ?? [];
|
|
32992
|
-
},
|
|
32993
|
-
listProjectSessions: async (projectId, options) => {
|
|
32994
|
-
const params = new URLSearchParams();
|
|
32995
|
-
params.set("projectId", projectId);
|
|
32777
|
+
params.set("systemId", systemId);
|
|
32996
32778
|
if (options?.status) params.set("status", options.status);
|
|
32997
32779
|
if (options?.includeTerminal) params.set("includeTerminal", "true");
|
|
32998
32780
|
const result = await request("GET", `/api/sessions?${params.toString()}`);
|
|
@@ -33185,14 +32967,6 @@ function createHttpClient(config2) {
|
|
|
33185
32967
|
const result = await request("GET", `/api/systems/${encodeURIComponent(projectId)}/tasks${qs}`);
|
|
33186
32968
|
return result?.tasks ?? [];
|
|
33187
32969
|
},
|
|
33188
|
-
listProjectTasks: async (projectId, options) => {
|
|
33189
|
-
const params = new URLSearchParams();
|
|
33190
|
-
if (options?.status) params.set("status", options.status);
|
|
33191
|
-
if (options?.limit) params.set("limit", String(options.limit));
|
|
33192
|
-
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
33193
|
-
const result = await request("GET", `/api/systems/${encodeURIComponent(projectId)}/tasks${qs}`);
|
|
33194
|
-
return result?.tasks ?? [];
|
|
33195
|
-
},
|
|
33196
32970
|
listTaskEvents: async (taskId, options) => {
|
|
33197
32971
|
const params = new URLSearchParams();
|
|
33198
32972
|
if (options?.afterSeq !== void 0) params.set("after", String(options.afterSeq));
|
|
@@ -33225,15 +32999,6 @@ function createHttpClient(config2) {
|
|
|
33225
32999
|
const result = await request("GET", path);
|
|
33226
33000
|
return { entries: result.activities ?? [], hasMore: false };
|
|
33227
33001
|
},
|
|
33228
|
-
listProjectActivities: async (projectId, options) => {
|
|
33229
|
-
const params = new URLSearchParams();
|
|
33230
|
-
if (options?.limit) params.set("limit", String(options.limit));
|
|
33231
|
-
if (options?.minImportance) params.set("importance", options.minImportance);
|
|
33232
|
-
const qs = params.toString();
|
|
33233
|
-
const path = `/api/systems/${encodeURIComponent(projectId)}/activities${qs ? `?${qs}` : ""}`;
|
|
33234
|
-
const result = await request("GET", path);
|
|
33235
|
-
return { entries: result.activities ?? [], hasMore: false };
|
|
33236
|
-
},
|
|
33237
33002
|
createActivity: async (input) => {
|
|
33238
33003
|
const result = await request("POST", `/api/systems/${encodeURIComponent(input.projectId)}/activities`, {
|
|
33239
33004
|
action: input.action,
|
|
@@ -33308,20 +33073,6 @@ function createHttpClient(config2) {
|
|
|
33308
33073
|
);
|
|
33309
33074
|
return result.ranked ?? [];
|
|
33310
33075
|
},
|
|
33311
|
-
rankProjectBeatVersions: async (projectId, lens) => {
|
|
33312
|
-
const result = await request(
|
|
33313
|
-
"GET",
|
|
33314
|
-
`/api/systems/${encodeURIComponent(projectId)}/beat-versions/ranked?lens=${encodeURIComponent(lens)}`
|
|
33315
|
-
);
|
|
33316
|
-
return result.ranked ?? [];
|
|
33317
|
-
},
|
|
33318
|
-
rankProjectBeatVersionsWithLeverage: async (projectId, lens) => {
|
|
33319
|
-
const result = await request(
|
|
33320
|
-
"GET",
|
|
33321
|
-
`/api/systems/${encodeURIComponent(projectId)}/beat-versions/ranked?lens=${encodeURIComponent(lens)}&withLeverage=true`
|
|
33322
|
-
);
|
|
33323
|
-
return result.ranked ?? [];
|
|
33324
|
-
},
|
|
33325
33076
|
// All four use requestOrThrow, not request. These endpoints answer 404 for a
|
|
33326
33077
|
// missing edge/Beat with a real domain message, and `request()` turns a 404
|
|
33327
33078
|
// into `undefined` — so the old `result.edge` access threw
|
|
@@ -33574,7 +33325,7 @@ function createHttpClient(config2) {
|
|
|
33574
33325
|
},
|
|
33575
33326
|
searchByText: async (scope, query, options) => {
|
|
33576
33327
|
const params = new URLSearchParams({ q: query });
|
|
33577
|
-
if ("projectId" in scope) params.set("
|
|
33328
|
+
if ("projectId" in scope) params.set("systemId", scope.projectId);
|
|
33578
33329
|
else if ("teamspaceId" in scope) params.set("teamspaceId", scope.teamspaceId);
|
|
33579
33330
|
else params.set("orgId", scope.orgId);
|
|
33580
33331
|
if (options?.limit) params.set("limit", String(options.limit));
|
|
@@ -33620,18 +33371,6 @@ function createHttpClient(config2) {
|
|
|
33620
33371
|
);
|
|
33621
33372
|
return { checks: res?.checks ?? [], nextCursor: res?.nextCursor };
|
|
33622
33373
|
},
|
|
33623
|
-
listProjectChecks: async (projectId, checkType, options) => {
|
|
33624
|
-
const params = new URLSearchParams();
|
|
33625
|
-
if (checkType) params.set("type", checkType);
|
|
33626
|
-
if (options?.limit !== void 0) params.set("limit", String(options.limit));
|
|
33627
|
-
if (options?.cursor) params.set("cursor", options.cursor);
|
|
33628
|
-
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
33629
|
-
const res = await request(
|
|
33630
|
-
"GET",
|
|
33631
|
-
`/api/systems/${encodeURIComponent(projectId)}/checks${qs}`
|
|
33632
|
-
);
|
|
33633
|
-
return { checks: res?.checks ?? [], nextCursor: res?.nextCursor };
|
|
33634
|
-
},
|
|
33635
33374
|
listLatestSystemChecks: async (projectId) => {
|
|
33636
33375
|
const res = await request(
|
|
33637
33376
|
"GET",
|
|
@@ -33639,13 +33378,6 @@ function createHttpClient(config2) {
|
|
|
33639
33378
|
);
|
|
33640
33379
|
return res?.checks ?? [];
|
|
33641
33380
|
},
|
|
33642
|
-
listLatestProjectChecks: async (projectId) => {
|
|
33643
|
-
const res = await request(
|
|
33644
|
-
"GET",
|
|
33645
|
-
`/api/checks/latest?projectId=${encodeURIComponent(projectId)}`
|
|
33646
|
-
);
|
|
33647
|
-
return res?.checks ?? [];
|
|
33648
|
-
},
|
|
33649
33381
|
listBeatChecks: async (beatId, projectId, checkType) => {
|
|
33650
33382
|
const qs = checkType ? `?type=${encodeURIComponent(checkType)}` : "";
|
|
33651
33383
|
const res = await request(
|
|
@@ -33705,20 +33437,6 @@ function createHttpClient(config2) {
|
|
|
33705
33437
|
updateTeamspace: async (teamspaceId, updates) => {
|
|
33706
33438
|
return request("PATCH", `/api/teamspaces/${encodeURIComponent(teamspaceId)}`, updates);
|
|
33707
33439
|
},
|
|
33708
|
-
// Deliverables
|
|
33709
|
-
listTeamspaceDeliverables: async (teamspaceId) => {
|
|
33710
|
-
const res = await request("GET", `/api/teamspaces/${encodeURIComponent(teamspaceId)}/deliverables`);
|
|
33711
|
-
return res?.deliverables ?? [];
|
|
33712
|
-
},
|
|
33713
|
-
getDeliverable: async (deliverableId) => {
|
|
33714
|
-
return request("GET", `/api/deliverables/${encodeURIComponent(deliverableId)}`);
|
|
33715
|
-
},
|
|
33716
|
-
createDeliverable: async (input) => {
|
|
33717
|
-
return request("POST", `/api/teamspaces/${encodeURIComponent(input.teamspaceId)}/deliverables`, input);
|
|
33718
|
-
},
|
|
33719
|
-
updateDeliverable: async (deliverableId, updates) => {
|
|
33720
|
-
return request("PATCH", `/api/deliverables/${encodeURIComponent(deliverableId)}`, updates);
|
|
33721
|
-
},
|
|
33722
33440
|
// DeliverableGroups
|
|
33723
33441
|
listTeamspaceDeliverableGroups: async (teamspaceId) => {
|
|
33724
33442
|
const res = await request("GET", `/api/teamspaces/${encodeURIComponent(teamspaceId)}/deliverable-groups`);
|
|
@@ -33730,11 +33448,6 @@ function createHttpClient(config2) {
|
|
|
33730
33448
|
if (res === void 0) throw new Error(`Project ${projectId} not found`);
|
|
33731
33449
|
return res.deliverableGroups;
|
|
33732
33450
|
},
|
|
33733
|
-
listProjectDeliverableGroups: async (projectId) => {
|
|
33734
|
-
const res = await request("GET", `/api/systems/${encodeURIComponent(projectId)}/deliverable-groups`);
|
|
33735
|
-
if (res === void 0) throw new Error(`Project ${projectId} not found`);
|
|
33736
|
-
return res.deliverableGroups;
|
|
33737
|
-
},
|
|
33738
33451
|
listMovementDeliverableGroups: async (movementId) => {
|
|
33739
33452
|
const res = await request("GET", `/api/movements/${encodeURIComponent(movementId)}/deliverable-groups`);
|
|
33740
33453
|
if (res === void 0) throw new Error(`Movement ${movementId} not found`);
|
|
@@ -33771,10 +33484,6 @@ function createHttpClient(config2) {
|
|
|
33771
33484
|
...opts ?? {}
|
|
33772
33485
|
});
|
|
33773
33486
|
},
|
|
33774
|
-
listDeliverableGroupDeliverables: async (deliverableGroupId) => {
|
|
33775
|
-
const res = await request("GET", `/api/deliverable-groups/${encodeURIComponent(deliverableGroupId)}/deliverables`);
|
|
33776
|
-
return res?.deliverables ?? [];
|
|
33777
|
-
},
|
|
33778
33487
|
listDeliverableGroupDrops: async (deliverableGroupId) => {
|
|
33779
33488
|
const res = await request("GET", `/api/deliverable-groups/${encodeURIComponent(deliverableGroupId)}/drops`);
|
|
33780
33489
|
return res?.drops ?? [];
|
|
@@ -34354,28 +34063,54 @@ function createHttpClient(config2) {
|
|
|
34354
34063
|
);
|
|
34355
34064
|
return result?.usedBy;
|
|
34356
34065
|
},
|
|
34357
|
-
// Feature flags (B-135
|
|
34358
|
-
// npm package
|
|
34359
|
-
listFlags: async () => {
|
|
34360
|
-
|
|
34066
|
+
// Feature flags (B-135 v11) — routed through /api/mcp/feature-flags/* so the
|
|
34067
|
+
// published npm package (no DynamoDB credentials) can manage flags via HTTP.
|
|
34068
|
+
listFlags: async (options) => {
|
|
34069
|
+
const params = new URLSearchParams();
|
|
34070
|
+
if (options?.includeArchived) params.set("includeArchived", "true");
|
|
34071
|
+
if (options?.search) params.set("search", options.search);
|
|
34072
|
+
if (options?.cursor) params.set("cursor", options.cursor);
|
|
34073
|
+
if (options?.limit !== void 0) params.set("limit", String(options.limit));
|
|
34074
|
+
const qs = params.toString();
|
|
34075
|
+
return requestOrThrow(
|
|
34076
|
+
"GET",
|
|
34077
|
+
`/api/mcp/feature-flags${qs ? `?${qs}` : ""}`
|
|
34078
|
+
);
|
|
34361
34079
|
},
|
|
34362
|
-
getFlag: async () => {
|
|
34363
|
-
|
|
34080
|
+
getFlag: async (name, options) => {
|
|
34081
|
+
const qs = options?.includeHistory ? "?includeHistory=true" : "";
|
|
34082
|
+
return request("GET", `/api/mcp/feature-flags/${encodeURIComponent(name)}${qs}`);
|
|
34364
34083
|
},
|
|
34365
|
-
checkFlag: async () => {
|
|
34366
|
-
|
|
34084
|
+
checkFlag: async (name, stage) => {
|
|
34085
|
+
const flag = await request(
|
|
34086
|
+
"GET",
|
|
34087
|
+
`/api/mcp/feature-flags/${encodeURIComponent(name)}`
|
|
34088
|
+
);
|
|
34089
|
+
return flag ? flag.enabledIn.includes(stage) : false;
|
|
34367
34090
|
},
|
|
34368
|
-
createFlag: async () => {
|
|
34369
|
-
|
|
34091
|
+
createFlag: async (name, enabledIn, options) => {
|
|
34092
|
+
return requestOrThrow("POST", "/api/mcp/feature-flags", {
|
|
34093
|
+
name,
|
|
34094
|
+
enabledIn,
|
|
34095
|
+
description: options?.description,
|
|
34096
|
+
note: options?.note
|
|
34097
|
+
});
|
|
34370
34098
|
},
|
|
34371
|
-
setFlag: async () => {
|
|
34372
|
-
|
|
34099
|
+
setFlag: async (name, enabledIn, options) => {
|
|
34100
|
+
return requestOrThrow("PUT", `/api/mcp/feature-flags/${encodeURIComponent(name)}`, {
|
|
34101
|
+
enabledIn,
|
|
34102
|
+
note: options?.note
|
|
34103
|
+
});
|
|
34373
34104
|
},
|
|
34374
|
-
archiveFlag: async () => {
|
|
34375
|
-
|
|
34105
|
+
archiveFlag: async (name, options) => {
|
|
34106
|
+
return requestOrThrow("POST", `/api/mcp/feature-flags/${encodeURIComponent(name)}/archive`, {
|
|
34107
|
+
note: options?.note
|
|
34108
|
+
});
|
|
34376
34109
|
},
|
|
34377
|
-
unarchiveFlag: async () => {
|
|
34378
|
-
|
|
34110
|
+
unarchiveFlag: async (name, options) => {
|
|
34111
|
+
return requestOrThrow("POST", `/api/mcp/feature-flags/${encodeURIComponent(name)}/unarchive`, {
|
|
34112
|
+
note: options?.note
|
|
34113
|
+
});
|
|
34379
34114
|
}
|
|
34380
34115
|
};
|
|
34381
34116
|
return client;
|
|
@@ -34426,7 +34161,7 @@ function loadConfig() {
|
|
|
34426
34161
|
};
|
|
34427
34162
|
}
|
|
34428
34163
|
async function main() {
|
|
34429
|
-
console.error(`[harmonica-mcp] v${"3.
|
|
34164
|
+
console.error(`[harmonica-mcp] v${"3.6.1"} starting\u2026`);
|
|
34430
34165
|
const config2 = loadConfig();
|
|
34431
34166
|
const client = createHttpClient({
|
|
34432
34167
|
apiBaseUrl: config2.apiBaseUrl,
|