@codazen/harmonica-mcp 4.4.0 → 4.4.2
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 +91 -57
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21913,7 +21913,7 @@ function registerActivityTools(server, ctx, client) {
|
|
|
21913
21913
|
minImportance: importance
|
|
21914
21914
|
});
|
|
21915
21915
|
if (entries.length === 0) {
|
|
21916
|
-
return { content: [{ type: "text", text: "No activities found for this
|
|
21916
|
+
return { content: [{ type: "text", text: "No activities found for this system." }] };
|
|
21917
21917
|
}
|
|
21918
21918
|
const lines = [
|
|
21919
21919
|
`# Project Activities (${entries.length}${hasMore ? "+" : ""})`,
|
|
@@ -22416,6 +22416,54 @@ var CHECK_MAX_SCORES = {
|
|
|
22416
22416
|
root_coda_quality: 5
|
|
22417
22417
|
};
|
|
22418
22418
|
|
|
22419
|
+
// ../../libs/harmonica-services/src/mcp/errors.ts
|
|
22420
|
+
var BeatQualityGateError = class extends Error {
|
|
22421
|
+
code = "beat_quality_gate_failed";
|
|
22422
|
+
failure;
|
|
22423
|
+
constructor(failure) {
|
|
22424
|
+
super(failure.message);
|
|
22425
|
+
this.failure = failure;
|
|
22426
|
+
}
|
|
22427
|
+
};
|
|
22428
|
+
var PlanVersionsIdempotencyError = class extends Error {
|
|
22429
|
+
code = "plan_versions_already_exist";
|
|
22430
|
+
existingBeatVersionIds;
|
|
22431
|
+
constructor(existingBeatVersionIds) {
|
|
22432
|
+
super(
|
|
22433
|
+
`Beat already has ${existingBeatVersionIds.length} planned Beat Version(s). Pass force=true to plan again.`
|
|
22434
|
+
);
|
|
22435
|
+
this.existingBeatVersionIds = existingBeatVersionIds;
|
|
22436
|
+
}
|
|
22437
|
+
};
|
|
22438
|
+
function isRenderableGateFailure(value) {
|
|
22439
|
+
if (typeof value !== "object" || value === null) return false;
|
|
22440
|
+
const f = value;
|
|
22441
|
+
return typeof f.reason === "string" && typeof f.message === "string";
|
|
22442
|
+
}
|
|
22443
|
+
var CheckResultPendingError = class extends Error {
|
|
22444
|
+
code = "check_result_pending";
|
|
22445
|
+
taskId;
|
|
22446
|
+
constructor(taskId) {
|
|
22447
|
+
super(`Task ${taskId} completed but its scorecard is not yet readable on the blocking path.`);
|
|
22448
|
+
this.name = "CheckResultPendingError";
|
|
22449
|
+
this.taskId = taskId;
|
|
22450
|
+
}
|
|
22451
|
+
};
|
|
22452
|
+
function renderCheckResultPending(err, alsoTry = ["list_checks"]) {
|
|
22453
|
+
const paths = [`get_job_status (jobId="${err.taskId}")`, ...alsoTry].join(" or ");
|
|
22454
|
+
return {
|
|
22455
|
+
content: [{
|
|
22456
|
+
type: "text",
|
|
22457
|
+
text: [
|
|
22458
|
+
`**Status:** completed \u2014 scorecard not yet readable on the blocking path`,
|
|
22459
|
+
`**Job ID:** ${err.taskId}`,
|
|
22460
|
+
"",
|
|
22461
|
+
`The check succeeded on the async path. Retrieve the scorecard with ${paths}.`
|
|
22462
|
+
].join("\n")
|
|
22463
|
+
}]
|
|
22464
|
+
};
|
|
22465
|
+
}
|
|
22466
|
+
|
|
22419
22467
|
// ../../libs/harmonica-services/src/mcp/tools/beat-quality-tools.ts
|
|
22420
22468
|
var POLL_INTERVAL_MS = 4e3;
|
|
22421
22469
|
var POLL_TIMEOUT_MS = 18e4;
|
|
@@ -22438,7 +22486,7 @@ async function pollForCheck(client, taskId) {
|
|
|
22438
22486
|
consecutiveErrors = 0;
|
|
22439
22487
|
if (!task) throw new Error(`Task ${taskId} not found`);
|
|
22440
22488
|
if (task.status === "completed") {
|
|
22441
|
-
if (!task.result) throw new
|
|
22489
|
+
if (!task.result) throw new CheckResultPendingError(taskId);
|
|
22442
22490
|
return task.result;
|
|
22443
22491
|
}
|
|
22444
22492
|
if (task.status === "failed") throw new Error(`Quality check failed: ${task.error ?? "unknown error"}`);
|
|
@@ -22486,6 +22534,7 @@ Use get_job_status with jobId="${taskId}" to poll for results, or list_checks to
|
|
|
22486
22534
|
const check2 = await pollForCheck(client, taskId);
|
|
22487
22535
|
return { content: [{ type: "text", text: formatScorecard(check2) }] };
|
|
22488
22536
|
} catch (err) {
|
|
22537
|
+
if (err instanceof CheckResultPendingError) return renderCheckResultPending(err);
|
|
22489
22538
|
const message = err instanceof Error ? err.message : String(err);
|
|
22490
22539
|
return { content: [{ type: "text", text: `Quality check failed: ${message}` }], isError: true };
|
|
22491
22540
|
}
|
|
@@ -23094,7 +23143,7 @@ function registerBeatTools(server, ctx, client) {
|
|
|
23094
23143
|
beatId: external_exports.string().optional().describe("Override beat ID (auto-generated if omitted)"),
|
|
23095
23144
|
humanAssignee: humanAssigneeSchema.optional().describe('Human assignee (e.g. { email: "lwu@codazen.com", name: "Liam Wu" })'),
|
|
23096
23145
|
agentAssignee: agentAssigneeSchema.optional().describe('Agent assignee (e.g. { agentId: "maya", name: "Maya" })'),
|
|
23097
|
-
branch: external_exports.string().optional().describe('Git branch for code assessment (falls back to
|
|
23146
|
+
branch: external_exports.string().optional().describe('Git branch for code assessment (falls back to System.repoDefaultBranch \u2192 "main")')
|
|
23098
23147
|
},
|
|
23099
23148
|
async ({ systemId, title, description, tags, priority, estimatedEffort, beatId, humanAssignee, agentAssignee, branch }) => {
|
|
23100
23149
|
try {
|
|
@@ -23302,31 +23351,6 @@ var BeatVersionRelocateError = class extends Error {
|
|
|
23302
23351
|
var REVISION_STATUSES = ["active", "archived"];
|
|
23303
23352
|
var BEAT_VERSION_STATUSES = ["active", "archived"];
|
|
23304
23353
|
|
|
23305
|
-
// ../../libs/harmonica-services/src/mcp/errors.ts
|
|
23306
|
-
var BeatQualityGateError = class extends Error {
|
|
23307
|
-
code = "beat_quality_gate_failed";
|
|
23308
|
-
failure;
|
|
23309
|
-
constructor(failure) {
|
|
23310
|
-
super(failure.message);
|
|
23311
|
-
this.failure = failure;
|
|
23312
|
-
}
|
|
23313
|
-
};
|
|
23314
|
-
var PlanVersionsIdempotencyError = class extends Error {
|
|
23315
|
-
code = "plan_versions_already_exist";
|
|
23316
|
-
existingBeatVersionIds;
|
|
23317
|
-
constructor(existingBeatVersionIds) {
|
|
23318
|
-
super(
|
|
23319
|
-
`Beat already has ${existingBeatVersionIds.length} planned Beat Version(s). Pass force=true to plan again.`
|
|
23320
|
-
);
|
|
23321
|
-
this.existingBeatVersionIds = existingBeatVersionIds;
|
|
23322
|
-
}
|
|
23323
|
-
};
|
|
23324
|
-
function isRenderableGateFailure(value) {
|
|
23325
|
-
if (typeof value !== "object" || value === null) return false;
|
|
23326
|
-
const f = value;
|
|
23327
|
-
return typeof f.reason === "string" && typeof f.message === "string";
|
|
23328
|
-
}
|
|
23329
|
-
|
|
23330
23354
|
// ../../libs/harmonica-services/src/mcp/tools/beat-version-tools.ts
|
|
23331
23355
|
function registerBeatVersionTools(server, ctx, client) {
|
|
23332
23356
|
server.tool(
|
|
@@ -24150,7 +24174,7 @@ ${g.acceptanceCriteria}` : null,
|
|
|
24150
24174
|
deliverables: external_exports.string().max(2e4).optional().describe("The Track's deliverables as Markdown bullet points (parallel to acceptanceCriteria)"),
|
|
24151
24175
|
acceptanceCriteria: external_exports.string().max(2e4).optional().describe("The Track's acceptance criteria (Markdown), parallel to its deliverables"),
|
|
24152
24176
|
vuRate: external_exports.number().nonnegative().describe("Value-Unit rate (billing rate for this engagement)"),
|
|
24153
|
-
systemId: external_exports.string().optional().describe("Optional
|
|
24177
|
+
systemId: external_exports.string().optional().describe("Optional System to scope this Track to"),
|
|
24154
24178
|
movementId: external_exports.string().optional().describe("Optional Movement (client SOW) to scope this Track to"),
|
|
24155
24179
|
parentGroupId: external_exports.string().optional().describe("Optional parent Track ID for nested grouping (Phase 0 scaffolding)")
|
|
24156
24180
|
};
|
|
@@ -24464,7 +24488,7 @@ async function pollForCheck2(client, taskId) {
|
|
|
24464
24488
|
consecutiveErrors = 0;
|
|
24465
24489
|
if (!task) throw new Error(`Task ${taskId} not found`);
|
|
24466
24490
|
if (task.status === "completed") {
|
|
24467
|
-
if (!task.result) throw new
|
|
24491
|
+
if (!task.result) throw new CheckResultPendingError(taskId);
|
|
24468
24492
|
return task.result;
|
|
24469
24493
|
}
|
|
24470
24494
|
if (task.status === "failed") throw new Error(`Drop quality check failed: ${task.error ?? "unknown error"}`);
|
|
@@ -24520,7 +24544,7 @@ function registerDropQualityTools(server, ctx, client) {
|
|
|
24520
24544
|
`Drop quality check enqueued for ${dropId}.`,
|
|
24521
24545
|
`Task ID: ${taskId}`,
|
|
24522
24546
|
"",
|
|
24523
|
-
`Use get_job_status with jobId="${taskId}" to
|
|
24547
|
+
`Use get_job_status with jobId="${taskId}" to view results \u2014 list_checks has no dropId filter.`
|
|
24524
24548
|
].join("\n")
|
|
24525
24549
|
}]
|
|
24526
24550
|
};
|
|
@@ -24528,6 +24552,7 @@ function registerDropQualityTools(server, ctx, client) {
|
|
|
24528
24552
|
const check2 = await pollForCheck2(client, taskId);
|
|
24529
24553
|
return { content: [{ type: "text", text: formatReport(check2) }] };
|
|
24530
24554
|
} catch (err) {
|
|
24555
|
+
if (err instanceof CheckResultPendingError) return renderCheckResultPending(err, []);
|
|
24531
24556
|
const message = err instanceof Error ? err.message : String(err);
|
|
24532
24557
|
return { content: [{ type: "text", text: `Drop quality check failed: ${message}` }], isError: true };
|
|
24533
24558
|
}
|
|
@@ -24914,8 +24939,8 @@ function registerEmbeddingTools(server, ctx, client) {
|
|
|
24914
24939
|
"search",
|
|
24915
24940
|
"Free-text semantic search across system, teamspace, or org scope. Provide exactly one of systemId / teamspaceId / orgId. Teamspace and org searches fan out across child projects and merge by score. Cross-project results carry the source project name.",
|
|
24916
24941
|
{
|
|
24917
|
-
systemId: external_exports.string().optional().describe("Search within a single
|
|
24918
|
-
teamspaceId: external_exports.string().optional().describe("Search across all
|
|
24942
|
+
systemId: external_exports.string().optional().describe("Search within a single System"),
|
|
24943
|
+
teamspaceId: external_exports.string().optional().describe("Search across all Systems in a teamspace"),
|
|
24919
24944
|
orgId: external_exports.string().optional().describe("Search across every system in this organization \u2014 see list_organizations"),
|
|
24920
24945
|
query: external_exports.string().describe("Natural language search query"),
|
|
24921
24946
|
limit: external_exports.coerce.number().int().min(1).max(50).optional().default(10).describe("Max results to return. Default 10"),
|
|
@@ -27464,7 +27489,7 @@ function registerNoteTools(server, ctx, client) {
|
|
|
27464
27489
|
{
|
|
27465
27490
|
systemId: external_exports.string().describe("The system ID"),
|
|
27466
27491
|
beatId: external_exports.string().optional().describe("Scope to a specific beat (omit for all system notes)"),
|
|
27467
|
-
noteType: external_exports.union([external_exports.enum(NOTE_TYPE_VALUES), external_exports.array(external_exports.enum(NOTE_TYPE_VALUES)).min(1)]).optional().describe('Filter by note type \u2014 single value or array for multi-select (e.g. ["constraint", "
|
|
27492
|
+
noteType: external_exports.union([external_exports.enum(NOTE_TYPE_VALUES), external_exports.array(external_exports.enum(NOTE_TYPE_VALUES)).min(1)]).optional().describe('Filter by note type \u2014 single value or array for multi-select (e.g. ["constraint", "guidance"])'),
|
|
27468
27493
|
status: external_exports.enum(NOTE_STATUS_VALUES).optional().describe("Filter by status"),
|
|
27469
27494
|
revisionId: external_exports.string().optional().describe("Filter to notes scoped to a specific revision"),
|
|
27470
27495
|
beatVersionId: external_exports.string().optional().describe("Filter to notes scoped to a specific Beat Version (planning increment)"),
|
|
@@ -27632,12 +27657,12 @@ function registerNoteTools(server, ctx, client) {
|
|
|
27632
27657
|
},
|
|
27633
27658
|
async ({ systemId }) => {
|
|
27634
27659
|
await assertSystemExists(client, systemId);
|
|
27635
|
-
const
|
|
27636
|
-
const { notes: docs, hasMore: truncated } = await client.listAllSystemNotes(systemId, { noteType: "document" }, DOCUMENT_FETCH_LIMIT);
|
|
27660
|
+
const { notes: docs, hasMore } = await client.listAllSystemNotes(systemId, { noteType: "document" });
|
|
27637
27661
|
const visibleDocs = docs.filter((d) => d.status !== DISMISSED_NOTE_STATUS);
|
|
27638
|
-
|
|
27639
|
-
|
|
27640
|
-
|
|
27662
|
+
if (hasMore) {
|
|
27663
|
+
return { content: [{ type: "text", text: `Unexpected: listAllSystemNotes returned hasMore=true on the no-limit path for system ${systemId} \u2014 the document list may be incomplete. This is a server-side regression.` }], isError: true };
|
|
27664
|
+
}
|
|
27665
|
+
return { content: [{ type: "text", text: formatDocumentList(visibleDocs) }] };
|
|
27641
27666
|
}
|
|
27642
27667
|
);
|
|
27643
27668
|
server.tool(
|
|
@@ -27780,7 +27805,7 @@ ${text}` }] };
|
|
|
27780
27805
|
systemId: external_exports.string().optional().describe("The system ID (for access control). Provide systemId or orgId, not both."),
|
|
27781
27806
|
orgId: external_exports.string().optional().describe("The org ID (for org-level notes). Provide orgId or systemId, not both."),
|
|
27782
27807
|
noteId: external_exports.string().describe("The note ID to update"),
|
|
27783
|
-
noteType: external_exports.enum(NOTE_TYPE_VALUES).optional().describe("Reclassify the note type (e.g.
|
|
27808
|
+
noteType: external_exports.enum(NOTE_TYPE_VALUES).optional().describe("Reclassify the note type (e.g. context \u2192 guidance)"),
|
|
27784
27809
|
status: external_exports.enum(NOTE_STATUS_VALUES).optional().describe("New status"),
|
|
27785
27810
|
content: external_exports.string().optional().describe("Updated content"),
|
|
27786
27811
|
rationale: external_exports.string().optional().describe("Why this note exists or why this decision was made"),
|
|
@@ -28226,7 +28251,7 @@ ${formatTree(tree.root)}` }] };
|
|
|
28226
28251
|
heading: external_exports.string().min(1).max(200).describe('Section label, e.g. "Decision Log"'),
|
|
28227
28252
|
parentNoteId: external_exports.string().optional().describe("Parent page's Note ID; defaults to the notebook root"),
|
|
28228
28253
|
noteType: external_exports.enum(["context", "constraint", "guidance", "decision", "document"]).optional().describe("Note type to collect (default: decision)"),
|
|
28229
|
-
systemId: external_exports.string().optional().describe("
|
|
28254
|
+
systemId: external_exports.string().optional().describe("System scope; if omitted, the Notebook's first bound system scope is used"),
|
|
28230
28255
|
limit: external_exports.number().int().min(1).max(500).optional().describe("Max members to show (default: 25)"),
|
|
28231
28256
|
order: external_exports.enum(["newest", "oldest"]).optional().describe("Sort order (default: newest)"),
|
|
28232
28257
|
significance: external_exports.enum(["strategic", "structural", "implementation"]).optional().describe("Only for decision notes \u2014 filter to a significance tier (e.g. strategic). Omit to include all.")
|
|
@@ -28244,15 +28269,15 @@ ${formatTree(tree.root)}` }] };
|
|
|
28244
28269
|
isError: true
|
|
28245
28270
|
};
|
|
28246
28271
|
}
|
|
28247
|
-
let
|
|
28248
|
-
if (!
|
|
28272
|
+
let scopeSystemId = systemId;
|
|
28273
|
+
if (!scopeSystemId) {
|
|
28249
28274
|
try {
|
|
28250
28275
|
const bindings = await client.getNotebookScopeBindings(notebookId);
|
|
28251
|
-
|
|
28276
|
+
scopeSystemId = bindings?.find((b) => b.scopeType === "system" || b.scopeType === "project")?.scopeId;
|
|
28252
28277
|
} catch {
|
|
28253
28278
|
}
|
|
28254
28279
|
}
|
|
28255
|
-
if (!
|
|
28280
|
+
if (!scopeSystemId) {
|
|
28256
28281
|
return { content: [{ type: "text", text: "No system scope: pass systemId or bind the notebook to a system first." }], isError: true };
|
|
28257
28282
|
}
|
|
28258
28283
|
let tree;
|
|
@@ -28282,7 +28307,7 @@ ${formatTree(tree.root)}` }] };
|
|
|
28282
28307
|
parentId: placement.parentNoteId,
|
|
28283
28308
|
query: {
|
|
28284
28309
|
source: "notes",
|
|
28285
|
-
scope: `
|
|
28310
|
+
scope: `system:${scopeSystemId}`,
|
|
28286
28311
|
noteType: noteType ?? "decision",
|
|
28287
28312
|
limit: limit ?? 25,
|
|
28288
28313
|
sortBy: order === "oldest" ? "createdAt_asc" : "createdAt_desc",
|
|
@@ -28301,7 +28326,7 @@ ${formatTree(tree.root)}` }] };
|
|
|
28301
28326
|
return { content: [{ type: "text", text: `Failed to add collection: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
28302
28327
|
}
|
|
28303
28328
|
return {
|
|
28304
|
-
content: [{ type: "text", text: `Live collection added: **${heading}** (${noteType ?? "decision"} @
|
|
28329
|
+
content: [{ type: "text", text: `Live collection added: **${heading}** (${noteType ?? "decision"} @ system:${scopeSystemId}) under ${placement.parentNoteId} at depth ${placement.childDepth}, position ${position}.` }]
|
|
28305
28330
|
};
|
|
28306
28331
|
}
|
|
28307
28332
|
);
|
|
@@ -28314,7 +28339,7 @@ ${formatTree(tree.root)}` }] };
|
|
|
28314
28339
|
parentNoteId: external_exports.string().optional().describe("The page Note ID the section sits under; defaults to the notebook root"),
|
|
28315
28340
|
heading: external_exports.string().min(1).max(200).optional().describe("New section label"),
|
|
28316
28341
|
noteType: external_exports.enum(["context", "constraint", "guidance", "decision", "document"]).optional().describe("New note type to collect"),
|
|
28317
|
-
systemId: external_exports.string().optional().describe("New
|
|
28342
|
+
systemId: external_exports.string().optional().describe("New system scope"),
|
|
28318
28343
|
limit: external_exports.number().int().min(1).max(500).optional().describe("New max members to show"),
|
|
28319
28344
|
order: external_exports.enum(["newest", "oldest"]).optional().describe("New sort order"),
|
|
28320
28345
|
significance: external_exports.enum(["strategic", "structural", "implementation"]).optional().describe("New significance-tier filter (decision notes only)")
|
|
@@ -28356,9 +28381,14 @@ ${formatTree(tree.root)}` }] };
|
|
|
28356
28381
|
return { content: [{ type: "text", text: `Element "${elementId}" is not a live collection \u2014 its configuration cannot be edited here.` }], isError: true };
|
|
28357
28382
|
}
|
|
28358
28383
|
const base = existing.query;
|
|
28384
|
+
const normalizedScope = systemId ? `system:${systemId}` : base.scope.replace(/^project:/, "system:");
|
|
28385
|
+
const colonIdx = normalizedScope.indexOf(":");
|
|
28386
|
+
if (colonIdx <= 0 || colonIdx === normalizedScope.length - 1) {
|
|
28387
|
+
return { content: [{ type: "text", text: `Stored scope '${base.scope}' has no system id \u2014 pass an explicit systemId to re-bind this collection.` }], isError: true };
|
|
28388
|
+
}
|
|
28359
28389
|
const mergedQuery = {
|
|
28360
28390
|
source: "notes",
|
|
28361
|
-
scope:
|
|
28391
|
+
scope: normalizedScope,
|
|
28362
28392
|
noteType: noteType ?? base.noteType,
|
|
28363
28393
|
limit: limit ?? base.limit,
|
|
28364
28394
|
sortBy: order !== void 0 ? order === "oldest" ? "createdAt_asc" : "createdAt_desc" : base.sortBy,
|
|
@@ -28933,7 +28963,7 @@ async function pollForRootCodaCheck(client, taskId) {
|
|
|
28933
28963
|
consecutiveErrors = 0;
|
|
28934
28964
|
if (!task) throw new Error(`Task ${taskId} not found`);
|
|
28935
28965
|
if (task.status === "completed") {
|
|
28936
|
-
if (!task.result) throw new
|
|
28966
|
+
if (!task.result) throw new CheckResultPendingError(taskId);
|
|
28937
28967
|
const result = task.result;
|
|
28938
28968
|
if (!Array.isArray(result.dimensions) || typeof result.overallScore !== "number") {
|
|
28939
28969
|
throw new Error(`Task ${taskId} did not return a root Coda scorecard \u2014 was it a run_check task?`);
|
|
@@ -29138,7 +29168,7 @@ function registerOrganizationTools(server, ctx, client) {
|
|
|
29138
29168
|
`Root Coda quality check enqueued for ${orgId}.`,
|
|
29139
29169
|
`Task ID: ${taskId}`,
|
|
29140
29170
|
"",
|
|
29141
|
-
`Use get_job_status with jobId="${taskId}" to
|
|
29171
|
+
`Use get_job_status with jobId="${taskId}" to view results \u2014 org-scoped checks are not listed by list_checks.`
|
|
29142
29172
|
].join("\n")
|
|
29143
29173
|
}]
|
|
29144
29174
|
};
|
|
@@ -29146,6 +29176,7 @@ function registerOrganizationTools(server, ctx, client) {
|
|
|
29146
29176
|
const check2 = await pollForRootCodaCheck(client, taskId);
|
|
29147
29177
|
return { content: [{ type: "text", text: formatRootCodaReport(check2) }] };
|
|
29148
29178
|
} catch (err) {
|
|
29179
|
+
if (err instanceof CheckResultPendingError) return renderCheckResultPending(err, []);
|
|
29149
29180
|
const message = err instanceof Error ? err.message : String(err);
|
|
29150
29181
|
return { content: [{ type: "text", text: `Root Coda quality check failed: ${message}` }], isError: true };
|
|
29151
29182
|
}
|
|
@@ -29181,7 +29212,7 @@ async function pollForCheck3(client, taskId) {
|
|
|
29181
29212
|
}
|
|
29182
29213
|
consecutiveErrors = 0;
|
|
29183
29214
|
if (task.status === "completed") {
|
|
29184
|
-
if (!task.result) throw new
|
|
29215
|
+
if (!task.result) throw new CheckResultPendingError(taskId);
|
|
29185
29216
|
return task.result;
|
|
29186
29217
|
}
|
|
29187
29218
|
if (task.status === "failed") throw new Error(`Beat version quality check failed: ${task.error ?? "unknown error"}`);
|
|
@@ -29242,6 +29273,7 @@ Use get_job_status with jobId="${task.taskId}" to poll for results, or list_chec
|
|
|
29242
29273
|
const check2 = await pollForCheck3(client, task.taskId);
|
|
29243
29274
|
return { content: [{ type: "text", text: formatScorecard2(check2) }] };
|
|
29244
29275
|
} catch (err) {
|
|
29276
|
+
if (err instanceof CheckResultPendingError) return renderCheckResultPending(err);
|
|
29245
29277
|
const message = err instanceof Error ? err.message : String(err);
|
|
29246
29278
|
return { content: [{ type: "text", text: `Beat version quality check failed: ${message}` }], isError: true };
|
|
29247
29279
|
}
|
|
@@ -29286,7 +29318,7 @@ async function pollForCheck4(client, taskId) {
|
|
|
29286
29318
|
consecutiveErrors = 0;
|
|
29287
29319
|
if (!task) throw new Error(`Task ${taskId} not found`);
|
|
29288
29320
|
if (task.status === "completed") {
|
|
29289
|
-
if (!task.result) throw new
|
|
29321
|
+
if (!task.result) throw new CheckResultPendingError(taskId);
|
|
29290
29322
|
return task.result;
|
|
29291
29323
|
}
|
|
29292
29324
|
if (task.status === "failed") throw new Error(`Portfolio coherence check failed: ${task.error ?? "unknown error"}`);
|
|
@@ -29390,6 +29422,7 @@ function registerPortfolioCoherenceTools(server, ctx, client) {
|
|
|
29390
29422
|
const check2 = await pollForCheck4(client, taskId);
|
|
29391
29423
|
return { content: [{ type: "text", text: formatReport2(check2) }] };
|
|
29392
29424
|
} catch (err) {
|
|
29425
|
+
if (err instanceof CheckResultPendingError) return renderCheckResultPending(err);
|
|
29393
29426
|
const message = err instanceof Error ? err.message : String(err);
|
|
29394
29427
|
return { content: [{ type: "text", text: `Portfolio coherence check failed: ${message}` }], isError: true };
|
|
29395
29428
|
}
|
|
@@ -30149,7 +30182,7 @@ async function pollForCheck5(client, taskId) {
|
|
|
30149
30182
|
}
|
|
30150
30183
|
consecutiveErrors = 0;
|
|
30151
30184
|
if (task.status === "completed") {
|
|
30152
|
-
if (!task.result) throw new
|
|
30185
|
+
if (!task.result) throw new CheckResultPendingError(taskId);
|
|
30153
30186
|
return task.result;
|
|
30154
30187
|
}
|
|
30155
30188
|
if (task.status === "failed") throw new Error(`Revision quality check failed: ${task.error ?? "unknown error"}`);
|
|
@@ -30211,6 +30244,7 @@ Use get_job_status with jobId="${task.taskId}" to poll for results, or list_chec
|
|
|
30211
30244
|
const check2 = await pollForCheck5(client, task.taskId);
|
|
30212
30245
|
return { content: [{ type: "text", text: formatScorecard3(check2) }] };
|
|
30213
30246
|
} catch (err) {
|
|
30247
|
+
if (err instanceof CheckResultPendingError) return renderCheckResultPending(err);
|
|
30214
30248
|
const message = err instanceof Error ? err.message : String(err);
|
|
30215
30249
|
return { content: [{ type: "text", text: `Revision quality check failed: ${message}` }], isError: true };
|
|
30216
30250
|
}
|
|
@@ -34218,7 +34252,7 @@ function createHttpClient(config2) {
|
|
|
34218
34252
|
},
|
|
34219
34253
|
listSystemDeliverableGroups: async (systemId) => {
|
|
34220
34254
|
const res = await request("GET", `/api/systems/${encodeURIComponent(systemId)}/deliverable-groups`);
|
|
34221
|
-
if (res === void 0) throw new Error(`
|
|
34255
|
+
if (res === void 0) throw new Error(`System ${systemId} not found`);
|
|
34222
34256
|
return res.deliverableGroups;
|
|
34223
34257
|
},
|
|
34224
34258
|
listMovementDeliverableGroups: async (movementId) => {
|
|
@@ -34798,7 +34832,7 @@ function createHttpClient(config2) {
|
|
|
34798
34832
|
`/api/systems/${encodeURIComponent(systemId)}/beats/draft`,
|
|
34799
34833
|
input
|
|
34800
34834
|
);
|
|
34801
|
-
if (!result) throw new Error(`Beat draft failed:
|
|
34835
|
+
if (!result) throw new Error(`Beat draft failed: system ${systemId} not found`);
|
|
34802
34836
|
return result;
|
|
34803
34837
|
},
|
|
34804
34838
|
triggerSystemEmbedding: async (systemId) => {
|
|
@@ -35064,7 +35098,7 @@ function loadConfig() {
|
|
|
35064
35098
|
};
|
|
35065
35099
|
}
|
|
35066
35100
|
async function main() {
|
|
35067
|
-
console.error(`[harmonica-mcp] v${"4.4.
|
|
35101
|
+
console.error(`[harmonica-mcp] v${"4.4.2"} starting\u2026`);
|
|
35068
35102
|
const config2 = loadConfig();
|
|
35069
35103
|
const client = createHttpClient({
|
|
35070
35104
|
apiBaseUrl: config2.apiBaseUrl,
|