@codazen/harmonica-mcp 4.1.0 → 4.3.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/index.js +36 -17
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -26623,6 +26623,7 @@ var CHECK_TARGET_TYPES = [
|
|
|
26623
26623
|
"revision",
|
|
26624
26624
|
"beat_version",
|
|
26625
26625
|
"project",
|
|
26626
|
+
"system",
|
|
26626
26627
|
"drop",
|
|
26627
26628
|
"organization"
|
|
26628
26629
|
];
|
|
@@ -26937,6 +26938,8 @@ var StartSessionRequestBodySchema = external_exports.object({
|
|
|
26937
26938
|
systemId: external_exports.string().min(1),
|
|
26938
26939
|
message: external_exports.string().min(1),
|
|
26939
26940
|
revisionId: external_exports.string().min(1).optional(),
|
|
26941
|
+
/** Caller's own Session id — nests the new Session under it (B-231). */
|
|
26942
|
+
parentSessionId: external_exports.string().min(1).optional(),
|
|
26940
26943
|
enableWebSearch: external_exports.boolean().optional()
|
|
26941
26944
|
});
|
|
26942
26945
|
var StartSessionResponseSchema = external_exports.object({
|
|
@@ -28168,9 +28171,9 @@ ${trimmed}` : `# ${title}`;
|
|
|
28168
28171
|
}
|
|
28169
28172
|
|
|
28170
28173
|
// ../../libs/harmonica-services/src/mcp/tools/notebook-tools.ts
|
|
28171
|
-
var SCOPE_TYPE_VALUES = ["org", "teamspace", "
|
|
28174
|
+
var SCOPE_TYPE_VALUES = ["org", "teamspace", "system", "account", "project"];
|
|
28172
28175
|
var scopeRefSchema = external_exports.object({
|
|
28173
|
-
scopeType: external_exports.enum(SCOPE_TYPE_VALUES).describe("Scope type \u2014 org, teamspace,
|
|
28176
|
+
scopeType: external_exports.enum(SCOPE_TYPE_VALUES).describe("Scope type \u2014 org, teamspace, system, or account"),
|
|
28174
28177
|
scopeId: external_exports.string().min(1).describe("ID of the scope entity")
|
|
28175
28178
|
});
|
|
28176
28179
|
function formatNotebook(nb) {
|
|
@@ -28395,7 +28398,7 @@ ${formatTree(tree.root)}` }] };
|
|
|
28395
28398
|
if (!scopeProjectId) {
|
|
28396
28399
|
try {
|
|
28397
28400
|
const bindings = await client.getNotebookScopeBindings(notebookId);
|
|
28398
|
-
scopeProjectId = bindings?.find((b) => b.scopeType === "project")?.scopeId;
|
|
28401
|
+
scopeProjectId = bindings?.find((b) => b.scopeType === "system" || b.scopeType === "project")?.scopeId;
|
|
28399
28402
|
} catch {
|
|
28400
28403
|
}
|
|
28401
28404
|
}
|
|
@@ -28561,7 +28564,7 @@ ${formatNotebook(updated)}` }] };
|
|
|
28561
28564
|
);
|
|
28562
28565
|
server.tool(
|
|
28563
28566
|
"set_notebook_scopes",
|
|
28564
|
-
"Replace all scope bindings for a Notebook. Pass an empty array to remove all bindings. Bindable scope types: org, teamspace,
|
|
28567
|
+
"Replace all scope bindings for a Notebook. Pass an empty array to remove all bindings. Bindable scope types: org, teamspace, system. (systemContainer is reserved.)",
|
|
28565
28568
|
{
|
|
28566
28569
|
notebookId: external_exports.string().describe("The Notebook ID"),
|
|
28567
28570
|
scopes: external_exports.array(scopeRefSchema).max(45).describe("New complete set of scope bindings (max 45)")
|
|
@@ -29983,9 +29986,10 @@ Accepts the full PR metadata (number, url, branch, state, optional mergeSha). Fi
|
|
|
29983
29986
|
revisionId: external_exports.string().describe("The Revision ID whose PR to review (e.g., rev-abc123)"),
|
|
29984
29987
|
autoMerge: external_exports.boolean().optional().describe("Merge automatically once converged. Default false \u2192 stop at ready-for-review."),
|
|
29985
29988
|
maxIterations: external_exports.number().int().min(1).max(3).optional().describe("Review rounds (default and hard cap: 3)."),
|
|
29986
|
-
confirm: external_exports.boolean().optional().describe("Set true to start the review. Omitted/false performs a dry-run \u2014 no session, scan, or task is created.")
|
|
29989
|
+
confirm: external_exports.boolean().optional().describe("Set true to start the review. Omitted/false performs a dry-run \u2014 no session, scan, or task is created."),
|
|
29990
|
+
requestingSessionId: external_exports.string().min(1).optional().describe("Your current Session ID (sess-<uuid>). Pass it so the review Session nests under yours and reports its outcome back to you when it finishes \u2014 otherwise you have no way to learn how the review turned out.")
|
|
29987
29991
|
},
|
|
29988
|
-
async ({ revisionId, autoMerge, maxIterations, confirm }) => {
|
|
29992
|
+
async ({ revisionId, autoMerge, maxIterations, confirm, requestingSessionId }) => {
|
|
29989
29993
|
try {
|
|
29990
29994
|
const revision = await client.getRevision(revisionId);
|
|
29991
29995
|
if (!revision) {
|
|
@@ -29996,7 +30000,7 @@ Accepts the full PR metadata (number, url, branch, state, optional mergeSha). Fi
|
|
|
29996
30000
|
if ("refusal" in latitude) {
|
|
29997
30001
|
return { content: [{ type: "text", text: latitude.refusal }], isError: true };
|
|
29998
30002
|
}
|
|
29999
|
-
const result = await client.requestCodeReview({ revisionId, autoMerge, maxIterations, confirm });
|
|
30003
|
+
const result = await client.requestCodeReview({ revisionId, autoMerge, maxIterations, confirm, requestingSessionId });
|
|
30000
30004
|
if (!result.success) {
|
|
30001
30005
|
return { content: [{ type: "text", text: `Failed to request code review (${result.error.code}): ${result.error.message}` }], isError: true };
|
|
30002
30006
|
}
|
|
@@ -30758,13 +30762,17 @@ function assertSnapshotShape(val, sourceHint) {
|
|
|
30758
30762
|
}
|
|
30759
30763
|
|
|
30760
30764
|
// ../../libs/harmonica-services/src/mcp/tools/subscription-tools.ts
|
|
30761
|
-
var ENTITY_TYPES = ["
|
|
30765
|
+
var ENTITY_TYPES = ["system", "beat", "revision"];
|
|
30766
|
+
var entityTypeField = external_exports.preprocess(
|
|
30767
|
+
(v) => v === "project" ? "system" : v,
|
|
30768
|
+
external_exports.enum(ENTITY_TYPES)
|
|
30769
|
+
);
|
|
30762
30770
|
function registerSubscriptionTools(server, ctx, client) {
|
|
30763
30771
|
server.tool(
|
|
30764
30772
|
"subscribe_to_entity",
|
|
30765
|
-
"Follow a
|
|
30773
|
+
"Follow a System, Beat, or Revision to receive notifications when it changes. You are auto-subscribed to things you own \u2014 use this to follow additional entities.",
|
|
30766
30774
|
{
|
|
30767
|
-
entityType:
|
|
30775
|
+
entityType: entityTypeField.describe("Type of entity to follow"),
|
|
30768
30776
|
entityId: external_exports.string().describe("The entity ID (system ID, beat ID, or revision ID)"),
|
|
30769
30777
|
systemId: external_exports.string().describe("The system ID (for access control)")
|
|
30770
30778
|
},
|
|
@@ -30786,9 +30794,9 @@ function registerSubscriptionTools(server, ctx, client) {
|
|
|
30786
30794
|
);
|
|
30787
30795
|
server.tool(
|
|
30788
30796
|
"unsubscribe_from_entity",
|
|
30789
|
-
"Stop following a
|
|
30797
|
+
"Stop following a System, Beat, or Revision. Use durable=true to prevent auto-resubscribe if you are later re-assigned.",
|
|
30790
30798
|
{
|
|
30791
|
-
entityType:
|
|
30799
|
+
entityType: entityTypeField.describe("Type of entity to unfollow"),
|
|
30792
30800
|
entityId: external_exports.string().describe("The entity ID"),
|
|
30793
30801
|
durable: external_exports.boolean().optional().default(false).describe("If true, prevents auto-resubscribe on reassignment")
|
|
30794
30802
|
},
|
|
@@ -32310,16 +32318,20 @@ ${JSON.stringify(task.result, null, 2)}
|
|
|
32310
32318
|
{
|
|
32311
32319
|
systemId: external_exports.string().min(1).describe("The system ID \u2014 the trusted scope the session is rooted at"),
|
|
32312
32320
|
message: external_exports.string().min(1).describe("Free-form first message describing what the session should do"),
|
|
32313
|
-
revisionId: external_exports.string().min(1).optional().describe("Optional Revision ID (rev-<uuid>). When provided, the Worker routes to the typed implementation session path (prepareRevisionImplementationSession), enabling file hint generation and richer session context. Omit for investigation, planning, or freeform sessions.")
|
|
32321
|
+
revisionId: external_exports.string().min(1).optional().describe("Optional Revision ID (rev-<uuid>). When provided, the Worker routes to the typed implementation session path (prepareRevisionImplementationSession), enabling file hint generation and richer session context. Omit for investigation, planning, or freeform sessions."),
|
|
32322
|
+
parentSessionId: external_exports.string().min(1).optional().describe("Your current Session ID (sess-<uuid>). Pass it when you are kicking off this session as part of your own work \u2014 the new session then nests under yours in the session tree and can report back to you. Omit for a standalone session.")
|
|
32314
32323
|
},
|
|
32315
|
-
async ({ systemId, message, revisionId }) => {
|
|
32324
|
+
async ({ systemId, message, revisionId, parentSessionId }) => {
|
|
32316
32325
|
try {
|
|
32317
32326
|
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
32318
32327
|
const task = await client.startSession(
|
|
32319
32328
|
systemId,
|
|
32320
32329
|
message,
|
|
32321
32330
|
{ name: ctx.user.name, email: ctx.user.email },
|
|
32322
|
-
revisionId?.trim()
|
|
32331
|
+
revisionId?.trim() || parentSessionId?.trim() ? {
|
|
32332
|
+
...revisionId?.trim() && { revisionId: revisionId.trim() },
|
|
32333
|
+
...parentSessionId?.trim() && { parentSessionId: parentSessionId.trim() }
|
|
32334
|
+
} : void 0
|
|
32323
32335
|
);
|
|
32324
32336
|
return {
|
|
32325
32337
|
content: [{
|
|
@@ -33911,10 +33923,17 @@ function createHttpClient(config2) {
|
|
|
33911
33923
|
// Agent sessions
|
|
33912
33924
|
startSession: async (systemId, message, triggeredBy, options) => {
|
|
33913
33925
|
const trimmedRevisionId = options?.revisionId?.trim();
|
|
33926
|
+
const trimmedParentSessionId = options?.parentSessionId?.trim();
|
|
33914
33927
|
const result = await request(
|
|
33915
33928
|
"POST",
|
|
33916
33929
|
`/api/sessions`,
|
|
33917
|
-
{
|
|
33930
|
+
{
|
|
33931
|
+
systemId,
|
|
33932
|
+
message,
|
|
33933
|
+
...triggeredBy && { triggeredBy },
|
|
33934
|
+
...trimmedRevisionId && { revisionId: trimmedRevisionId },
|
|
33935
|
+
...trimmedParentSessionId && { parentSessionId: trimmedParentSessionId }
|
|
33936
|
+
}
|
|
33918
33937
|
);
|
|
33919
33938
|
if (!result?.taskId) throw new Error("Start session enqueue failed: no taskId returned");
|
|
33920
33939
|
return { taskId: result.taskId, taskType: "generic_session", status: result.status ?? "pending", systemId, createdAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
@@ -35024,7 +35043,7 @@ function loadConfig() {
|
|
|
35024
35043
|
};
|
|
35025
35044
|
}
|
|
35026
35045
|
async function main() {
|
|
35027
|
-
console.error(`[harmonica-mcp] v${"4.
|
|
35046
|
+
console.error(`[harmonica-mcp] v${"4.3.0"} starting\u2026`);
|
|
35028
35047
|
const config2 = loadConfig();
|
|
35029
35048
|
const client = createHttpClient({
|
|
35030
35049
|
apiBaseUrl: config2.apiBaseUrl,
|