harmony-mcp 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +357 -3
- package/dist/index.js +357 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -30366,6 +30366,62 @@ class HarmonyApiClient {
|
|
|
30366
30366
|
const query = params.toString() ? `?${params.toString()}` : "";
|
|
30367
30367
|
return this.request("GET", `/cards/${cardId}/agent-context${query}`);
|
|
30368
30368
|
}
|
|
30369
|
+
async createMemoryEntity(data) {
|
|
30370
|
+
return this.request("POST", "/memory/entities", data);
|
|
30371
|
+
}
|
|
30372
|
+
async listMemoryEntities(options) {
|
|
30373
|
+
const params = new URLSearchParams;
|
|
30374
|
+
params.set("workspace_id", options.workspace_id);
|
|
30375
|
+
if (options.project_id)
|
|
30376
|
+
params.set("project_id", options.project_id);
|
|
30377
|
+
if (options.type)
|
|
30378
|
+
params.set("type", options.type);
|
|
30379
|
+
if (options.scope)
|
|
30380
|
+
params.set("scope", options.scope);
|
|
30381
|
+
if (options.tags?.length)
|
|
30382
|
+
params.set("tags", options.tags.join(","));
|
|
30383
|
+
if (options.agent_identifier)
|
|
30384
|
+
params.set("agent_identifier", options.agent_identifier);
|
|
30385
|
+
if (options.min_confidence !== undefined)
|
|
30386
|
+
params.set("min_confidence", String(options.min_confidence));
|
|
30387
|
+
if (options.q)
|
|
30388
|
+
params.set("q", options.q);
|
|
30389
|
+
if (options.limit !== undefined)
|
|
30390
|
+
params.set("limit", String(options.limit));
|
|
30391
|
+
if (options.offset !== undefined)
|
|
30392
|
+
params.set("offset", String(options.offset));
|
|
30393
|
+
return this.request("GET", `/memory/entities?${params.toString()}`);
|
|
30394
|
+
}
|
|
30395
|
+
async getMemoryEntity(entityId) {
|
|
30396
|
+
return this.request("GET", `/memory/entities/${entityId}`);
|
|
30397
|
+
}
|
|
30398
|
+
async updateMemoryEntity(entityId, updates) {
|
|
30399
|
+
return this.request("PUT", `/memory/entities/${entityId}`, updates);
|
|
30400
|
+
}
|
|
30401
|
+
async deleteMemoryEntity(entityId) {
|
|
30402
|
+
return this.request("DELETE", `/memory/entities/${entityId}`);
|
|
30403
|
+
}
|
|
30404
|
+
async createMemoryRelation(data) {
|
|
30405
|
+
return this.request("POST", "/memory/relations", data);
|
|
30406
|
+
}
|
|
30407
|
+
async deleteMemoryRelation(relationId) {
|
|
30408
|
+
return this.request("DELETE", `/memory/relations/${relationId}`);
|
|
30409
|
+
}
|
|
30410
|
+
async getRelatedEntities(entityId) {
|
|
30411
|
+
return this.request("GET", `/memory/entities/${entityId}/related`);
|
|
30412
|
+
}
|
|
30413
|
+
async searchMemoryEntities(workspaceId, query, options) {
|
|
30414
|
+
const params = new URLSearchParams;
|
|
30415
|
+
params.set("workspace_id", workspaceId);
|
|
30416
|
+
params.set("q", query);
|
|
30417
|
+
if (options?.project_id)
|
|
30418
|
+
params.set("project_id", options.project_id);
|
|
30419
|
+
if (options?.type)
|
|
30420
|
+
params.set("type", options.type);
|
|
30421
|
+
if (options?.limit !== undefined)
|
|
30422
|
+
params.set("limit", String(options.limit));
|
|
30423
|
+
return this.request("GET", `/memory/search?${params.toString()}`);
|
|
30424
|
+
}
|
|
30369
30425
|
async processNLU(data) {
|
|
30370
30426
|
return this.request("POST", "/nlu", data);
|
|
30371
30427
|
}
|
|
@@ -30607,7 +30663,7 @@ ${lines.join(`
|
|
|
30607
30663
|
`)}`;
|
|
30608
30664
|
}
|
|
30609
30665
|
function generatePrompt(options) {
|
|
30610
|
-
const { card, column, variant, customConstraints } = options;
|
|
30666
|
+
const { card, column, variant, customConstraints, memories } = options;
|
|
30611
30667
|
const contextOpts = {
|
|
30612
30668
|
includeTitle: true,
|
|
30613
30669
|
includeDescription: true,
|
|
@@ -30670,6 +30726,17 @@ ${card.description}`);
|
|
|
30670
30726
|
roleFraming.outputSuggestions.forEach((s) => {
|
|
30671
30727
|
sections.push(`- ${s}`);
|
|
30672
30728
|
});
|
|
30729
|
+
if (memories && memories.length > 0) {
|
|
30730
|
+
sections.push(`
|
|
30731
|
+
## Relevant Memories`);
|
|
30732
|
+
sections.push(`*${memories.length} memories recalled from knowledge graph:*`);
|
|
30733
|
+
for (const memory of memories) {
|
|
30734
|
+
const tags = memory.tags.length > 0 ? ` [${memory.tags.join(", ")}]` : "";
|
|
30735
|
+
sections.push(`
|
|
30736
|
+
### ${memory.title} (${memory.type}, confidence: ${memory.confidence})${tags}`);
|
|
30737
|
+
sections.push(memory.content);
|
|
30738
|
+
}
|
|
30739
|
+
}
|
|
30673
30740
|
if (customConstraints) {
|
|
30674
30741
|
sections.push(`
|
|
30675
30742
|
## Additional Instructions
|
|
@@ -30690,7 +30757,8 @@ ${customConstraints}`);
|
|
|
30690
30757
|
labelCount: labels.length,
|
|
30691
30758
|
subtaskCount: subtasks.length,
|
|
30692
30759
|
completedSubtasks: subtasks.filter((s) => s.completed).length,
|
|
30693
|
-
linkedCardCount: links.length
|
|
30760
|
+
linkedCardCount: links.length,
|
|
30761
|
+
memoryCount: memories?.length || 0
|
|
30694
30762
|
},
|
|
30695
30763
|
tokenEstimate: estimateTokens(prompt)
|
|
30696
30764
|
};
|
|
@@ -31207,6 +31275,192 @@ var TOOLS = {
|
|
|
31207
31275
|
required: []
|
|
31208
31276
|
}
|
|
31209
31277
|
},
|
|
31278
|
+
harmony_remember: {
|
|
31279
|
+
description: "Store a memory entity (knowledge, pattern, decision, error/solution pair, etc.) for persistence across sessions. Accepts markdown with YAML frontmatter or structured fields.",
|
|
31280
|
+
inputSchema: {
|
|
31281
|
+
type: "object",
|
|
31282
|
+
properties: {
|
|
31283
|
+
title: { type: "string", description: "Memory title" },
|
|
31284
|
+
content: {
|
|
31285
|
+
type: "string",
|
|
31286
|
+
description: "Memory content (markdown body)"
|
|
31287
|
+
},
|
|
31288
|
+
type: {
|
|
31289
|
+
type: "string",
|
|
31290
|
+
enum: [
|
|
31291
|
+
"agent",
|
|
31292
|
+
"task",
|
|
31293
|
+
"decision",
|
|
31294
|
+
"context",
|
|
31295
|
+
"pattern",
|
|
31296
|
+
"error",
|
|
31297
|
+
"solution",
|
|
31298
|
+
"preference"
|
|
31299
|
+
],
|
|
31300
|
+
description: "Entity type (default: context)"
|
|
31301
|
+
},
|
|
31302
|
+
scope: {
|
|
31303
|
+
type: "string",
|
|
31304
|
+
enum: ["private", "project", "workspace", "global"],
|
|
31305
|
+
description: "Visibility scope (default: project). Private = only creator can see."
|
|
31306
|
+
},
|
|
31307
|
+
tags: {
|
|
31308
|
+
type: "array",
|
|
31309
|
+
items: { type: "string" },
|
|
31310
|
+
description: "Tags for categorization and filtering"
|
|
31311
|
+
},
|
|
31312
|
+
confidence: {
|
|
31313
|
+
type: "number",
|
|
31314
|
+
description: "Confidence score 0-1 (default: 1.0)"
|
|
31315
|
+
},
|
|
31316
|
+
metadata: {
|
|
31317
|
+
type: "object",
|
|
31318
|
+
description: "Additional structured metadata"
|
|
31319
|
+
},
|
|
31320
|
+
workspaceId: {
|
|
31321
|
+
type: "string",
|
|
31322
|
+
description: "Workspace ID (optional if context set)"
|
|
31323
|
+
},
|
|
31324
|
+
projectId: {
|
|
31325
|
+
type: "string",
|
|
31326
|
+
description: "Project ID (optional, required if scope is 'project')"
|
|
31327
|
+
}
|
|
31328
|
+
},
|
|
31329
|
+
required: ["title", "content"]
|
|
31330
|
+
}
|
|
31331
|
+
},
|
|
31332
|
+
harmony_recall: {
|
|
31333
|
+
description: "Retrieve memories by type, tags, scope, or text query. Returns matching knowledge entities.",
|
|
31334
|
+
inputSchema: {
|
|
31335
|
+
type: "object",
|
|
31336
|
+
properties: {
|
|
31337
|
+
type: {
|
|
31338
|
+
type: "string",
|
|
31339
|
+
enum: [
|
|
31340
|
+
"agent",
|
|
31341
|
+
"task",
|
|
31342
|
+
"decision",
|
|
31343
|
+
"context",
|
|
31344
|
+
"pattern",
|
|
31345
|
+
"error",
|
|
31346
|
+
"solution",
|
|
31347
|
+
"preference"
|
|
31348
|
+
],
|
|
31349
|
+
description: "Filter by entity type"
|
|
31350
|
+
},
|
|
31351
|
+
tags: {
|
|
31352
|
+
type: "array",
|
|
31353
|
+
items: { type: "string" },
|
|
31354
|
+
description: "Filter by tags (matches any)"
|
|
31355
|
+
},
|
|
31356
|
+
scope: {
|
|
31357
|
+
type: "string",
|
|
31358
|
+
enum: ["private", "project", "workspace", "global"],
|
|
31359
|
+
description: "Filter by scope"
|
|
31360
|
+
},
|
|
31361
|
+
query: {
|
|
31362
|
+
type: "string",
|
|
31363
|
+
description: "Text query to filter by title"
|
|
31364
|
+
},
|
|
31365
|
+
minConfidence: {
|
|
31366
|
+
type: "number",
|
|
31367
|
+
description: "Minimum confidence threshold (0-1)"
|
|
31368
|
+
},
|
|
31369
|
+
workspaceId: {
|
|
31370
|
+
type: "string",
|
|
31371
|
+
description: "Workspace ID (optional if context set)"
|
|
31372
|
+
},
|
|
31373
|
+
projectId: {
|
|
31374
|
+
type: "string",
|
|
31375
|
+
description: "Project ID (optional)"
|
|
31376
|
+
},
|
|
31377
|
+
limit: { type: "number", description: "Max results (default: 20)" }
|
|
31378
|
+
}
|
|
31379
|
+
}
|
|
31380
|
+
},
|
|
31381
|
+
harmony_forget: {
|
|
31382
|
+
description: "Archive or delete a memory entity by ID.",
|
|
31383
|
+
inputSchema: {
|
|
31384
|
+
type: "object",
|
|
31385
|
+
properties: {
|
|
31386
|
+
entityId: {
|
|
31387
|
+
type: "string",
|
|
31388
|
+
description: "Memory entity UUID to delete"
|
|
31389
|
+
}
|
|
31390
|
+
},
|
|
31391
|
+
required: ["entityId"]
|
|
31392
|
+
}
|
|
31393
|
+
},
|
|
31394
|
+
harmony_relate: {
|
|
31395
|
+
description: "Create a typed relationship between two memory entities. Relation types: learned_from, resolved_by, contradicts, supports, depends_on, part_of, caused_by.",
|
|
31396
|
+
inputSchema: {
|
|
31397
|
+
type: "object",
|
|
31398
|
+
properties: {
|
|
31399
|
+
sourceId: {
|
|
31400
|
+
type: "string",
|
|
31401
|
+
description: "Source entity UUID"
|
|
31402
|
+
},
|
|
31403
|
+
targetId: {
|
|
31404
|
+
type: "string",
|
|
31405
|
+
description: "Target entity UUID"
|
|
31406
|
+
},
|
|
31407
|
+
relationType: {
|
|
31408
|
+
type: "string",
|
|
31409
|
+
enum: [
|
|
31410
|
+
"learned_from",
|
|
31411
|
+
"resolved_by",
|
|
31412
|
+
"contradicts",
|
|
31413
|
+
"supports",
|
|
31414
|
+
"depends_on",
|
|
31415
|
+
"part_of",
|
|
31416
|
+
"caused_by"
|
|
31417
|
+
],
|
|
31418
|
+
description: "Type of relationship between entities"
|
|
31419
|
+
},
|
|
31420
|
+
confidence: {
|
|
31421
|
+
type: "number",
|
|
31422
|
+
description: "Relation confidence 0-1 (default: 1.0)"
|
|
31423
|
+
}
|
|
31424
|
+
},
|
|
31425
|
+
required: ["sourceId", "targetId", "relationType"]
|
|
31426
|
+
}
|
|
31427
|
+
},
|
|
31428
|
+
harmony_memory_search: {
|
|
31429
|
+
description: "Full-text search across the knowledge base. Returns entities matching the query, ranked by confidence.",
|
|
31430
|
+
inputSchema: {
|
|
31431
|
+
type: "object",
|
|
31432
|
+
properties: {
|
|
31433
|
+
query: {
|
|
31434
|
+
type: "string",
|
|
31435
|
+
description: "Search query (full-text search)"
|
|
31436
|
+
},
|
|
31437
|
+
type: {
|
|
31438
|
+
type: "string",
|
|
31439
|
+
enum: [
|
|
31440
|
+
"agent",
|
|
31441
|
+
"task",
|
|
31442
|
+
"decision",
|
|
31443
|
+
"context",
|
|
31444
|
+
"pattern",
|
|
31445
|
+
"error",
|
|
31446
|
+
"solution",
|
|
31447
|
+
"preference"
|
|
31448
|
+
],
|
|
31449
|
+
description: "Filter results by entity type"
|
|
31450
|
+
},
|
|
31451
|
+
workspaceId: {
|
|
31452
|
+
type: "string",
|
|
31453
|
+
description: "Workspace ID (optional if context set)"
|
|
31454
|
+
},
|
|
31455
|
+
projectId: {
|
|
31456
|
+
type: "string",
|
|
31457
|
+
description: "Project ID (optional)"
|
|
31458
|
+
},
|
|
31459
|
+
limit: { type: "number", description: "Max results (default: 20)" }
|
|
31460
|
+
},
|
|
31461
|
+
required: ["query"]
|
|
31462
|
+
}
|
|
31463
|
+
},
|
|
31210
31464
|
harmony_create_plan: {
|
|
31211
31465
|
description: "Create a new project plan. Use this to upload implementation plans created during planning. Returns a URL where the plan can be viewed and edited in Harmony.",
|
|
31212
31466
|
inputSchema: {
|
|
@@ -31716,12 +31970,36 @@ class HarmonyMCPServer {
|
|
|
31716
31970
|
if (args.includeDescription !== undefined) {
|
|
31717
31971
|
contextOptions.includeDescription = args.includeDescription === true || args.includeDescription === "true";
|
|
31718
31972
|
}
|
|
31973
|
+
let memories;
|
|
31974
|
+
try {
|
|
31975
|
+
const workspaceId = getActiveWorkspaceId();
|
|
31976
|
+
if (workspaceId && cardData.title) {
|
|
31977
|
+
const memoryResult = await client2.searchMemoryEntities(workspaceId, cardData.title, {
|
|
31978
|
+
project_id: getActiveProjectId() || undefined,
|
|
31979
|
+
limit: 5
|
|
31980
|
+
});
|
|
31981
|
+
if (memoryResult.entities?.length > 0) {
|
|
31982
|
+
memories = memoryResult.entities.map((e) => {
|
|
31983
|
+
const entity = e;
|
|
31984
|
+
return {
|
|
31985
|
+
id: entity.id,
|
|
31986
|
+
type: entity.type,
|
|
31987
|
+
title: entity.title,
|
|
31988
|
+
content: entity.content,
|
|
31989
|
+
confidence: entity.confidence,
|
|
31990
|
+
tags: entity.tags || []
|
|
31991
|
+
};
|
|
31992
|
+
});
|
|
31993
|
+
}
|
|
31994
|
+
}
|
|
31995
|
+
} catch {}
|
|
31719
31996
|
const result = generatePrompt({
|
|
31720
31997
|
card: cardData,
|
|
31721
31998
|
column: columnData,
|
|
31722
31999
|
variant,
|
|
31723
32000
|
contextOptions,
|
|
31724
|
-
customConstraints: args.customConstraints
|
|
32001
|
+
customConstraints: args.customConstraints,
|
|
32002
|
+
memories
|
|
31725
32003
|
});
|
|
31726
32004
|
return {
|
|
31727
32005
|
success: true,
|
|
@@ -31731,6 +32009,82 @@ class HarmonyMCPServer {
|
|
|
31731
32009
|
...result
|
|
31732
32010
|
};
|
|
31733
32011
|
}
|
|
32012
|
+
case "harmony_remember": {
|
|
32013
|
+
const title = exports_external.string().min(1).parse(args.title);
|
|
32014
|
+
const content = exports_external.string().min(1).parse(args.content);
|
|
32015
|
+
const workspaceId = args.workspaceId || getActiveWorkspaceId();
|
|
32016
|
+
if (!workspaceId) {
|
|
32017
|
+
throw new Error("No workspace specified. Use harmony_set_workspace_context or provide workspaceId.");
|
|
32018
|
+
}
|
|
32019
|
+
const result = await client2.createMemoryEntity({
|
|
32020
|
+
workspace_id: workspaceId,
|
|
32021
|
+
project_id: args.projectId || getActiveProjectId() || undefined,
|
|
32022
|
+
type: args.type || "context",
|
|
32023
|
+
scope: args.scope || "project",
|
|
32024
|
+
title,
|
|
32025
|
+
content,
|
|
32026
|
+
metadata: args.metadata,
|
|
32027
|
+
confidence: args.confidence,
|
|
32028
|
+
tags: args.tags,
|
|
32029
|
+
agent_identifier: "claude-code"
|
|
32030
|
+
});
|
|
32031
|
+
return { success: true, ...result };
|
|
32032
|
+
}
|
|
32033
|
+
case "harmony_recall": {
|
|
32034
|
+
const workspaceId = args.workspaceId || getActiveWorkspaceId();
|
|
32035
|
+
if (!workspaceId) {
|
|
32036
|
+
throw new Error("No workspace specified. Use harmony_set_workspace_context or provide workspaceId.");
|
|
32037
|
+
}
|
|
32038
|
+
const result = await client2.listMemoryEntities({
|
|
32039
|
+
workspace_id: workspaceId,
|
|
32040
|
+
project_id: args.projectId || getActiveProjectId() || undefined,
|
|
32041
|
+
type: args.type,
|
|
32042
|
+
scope: args.scope,
|
|
32043
|
+
tags: args.tags,
|
|
32044
|
+
min_confidence: args.minConfidence,
|
|
32045
|
+
q: args.query,
|
|
32046
|
+
limit: args.limit
|
|
32047
|
+
});
|
|
32048
|
+
return { success: true, ...result };
|
|
32049
|
+
}
|
|
32050
|
+
case "harmony_forget": {
|
|
32051
|
+
const entityId = exports_external.string().uuid().parse(args.entityId);
|
|
32052
|
+
await client2.deleteMemoryEntity(entityId);
|
|
32053
|
+
return { success: true };
|
|
32054
|
+
}
|
|
32055
|
+
case "harmony_relate": {
|
|
32056
|
+
const sourceId = exports_external.string().uuid().parse(args.sourceId);
|
|
32057
|
+
const targetId = exports_external.string().uuid().parse(args.targetId);
|
|
32058
|
+
const relationType = exports_external.enum([
|
|
32059
|
+
"learned_from",
|
|
32060
|
+
"resolved_by",
|
|
32061
|
+
"contradicts",
|
|
32062
|
+
"supports",
|
|
32063
|
+
"depends_on",
|
|
32064
|
+
"part_of",
|
|
32065
|
+
"caused_by"
|
|
32066
|
+
]).parse(args.relationType);
|
|
32067
|
+
const result = await client2.createMemoryRelation({
|
|
32068
|
+
source_id: sourceId,
|
|
32069
|
+
target_id: targetId,
|
|
32070
|
+
relation_type: relationType,
|
|
32071
|
+
confidence: args.confidence
|
|
32072
|
+
});
|
|
32073
|
+
return { success: true, ...result };
|
|
32074
|
+
}
|
|
32075
|
+
case "harmony_memory_search": {
|
|
32076
|
+
const query = exports_external.string().min(1).parse(args.query);
|
|
32077
|
+
const workspaceId = args.workspaceId || getActiveWorkspaceId();
|
|
32078
|
+
if (!workspaceId) {
|
|
32079
|
+
throw new Error("No workspace specified. Use harmony_set_workspace_context or provide workspaceId.");
|
|
32080
|
+
}
|
|
32081
|
+
const result = await client2.searchMemoryEntities(workspaceId, query, {
|
|
32082
|
+
project_id: args.projectId || getActiveProjectId() || undefined,
|
|
32083
|
+
type: args.type,
|
|
32084
|
+
limit: args.limit
|
|
32085
|
+
});
|
|
32086
|
+
return { success: true, ...result };
|
|
32087
|
+
}
|
|
31734
32088
|
case "harmony_create_plan": {
|
|
31735
32089
|
const title = exports_external.string().min(1).parse(args.title);
|
|
31736
32090
|
const projectId = args.projectId || getProjectId();
|
package/dist/index.js
CHANGED
|
@@ -28126,6 +28126,62 @@ class HarmonyApiClient {
|
|
|
28126
28126
|
const query = params.toString() ? `?${params.toString()}` : "";
|
|
28127
28127
|
return this.request("GET", `/cards/${cardId}/agent-context${query}`);
|
|
28128
28128
|
}
|
|
28129
|
+
async createMemoryEntity(data) {
|
|
28130
|
+
return this.request("POST", "/memory/entities", data);
|
|
28131
|
+
}
|
|
28132
|
+
async listMemoryEntities(options) {
|
|
28133
|
+
const params = new URLSearchParams;
|
|
28134
|
+
params.set("workspace_id", options.workspace_id);
|
|
28135
|
+
if (options.project_id)
|
|
28136
|
+
params.set("project_id", options.project_id);
|
|
28137
|
+
if (options.type)
|
|
28138
|
+
params.set("type", options.type);
|
|
28139
|
+
if (options.scope)
|
|
28140
|
+
params.set("scope", options.scope);
|
|
28141
|
+
if (options.tags?.length)
|
|
28142
|
+
params.set("tags", options.tags.join(","));
|
|
28143
|
+
if (options.agent_identifier)
|
|
28144
|
+
params.set("agent_identifier", options.agent_identifier);
|
|
28145
|
+
if (options.min_confidence !== undefined)
|
|
28146
|
+
params.set("min_confidence", String(options.min_confidence));
|
|
28147
|
+
if (options.q)
|
|
28148
|
+
params.set("q", options.q);
|
|
28149
|
+
if (options.limit !== undefined)
|
|
28150
|
+
params.set("limit", String(options.limit));
|
|
28151
|
+
if (options.offset !== undefined)
|
|
28152
|
+
params.set("offset", String(options.offset));
|
|
28153
|
+
return this.request("GET", `/memory/entities?${params.toString()}`);
|
|
28154
|
+
}
|
|
28155
|
+
async getMemoryEntity(entityId) {
|
|
28156
|
+
return this.request("GET", `/memory/entities/${entityId}`);
|
|
28157
|
+
}
|
|
28158
|
+
async updateMemoryEntity(entityId, updates) {
|
|
28159
|
+
return this.request("PUT", `/memory/entities/${entityId}`, updates);
|
|
28160
|
+
}
|
|
28161
|
+
async deleteMemoryEntity(entityId) {
|
|
28162
|
+
return this.request("DELETE", `/memory/entities/${entityId}`);
|
|
28163
|
+
}
|
|
28164
|
+
async createMemoryRelation(data) {
|
|
28165
|
+
return this.request("POST", "/memory/relations", data);
|
|
28166
|
+
}
|
|
28167
|
+
async deleteMemoryRelation(relationId) {
|
|
28168
|
+
return this.request("DELETE", `/memory/relations/${relationId}`);
|
|
28169
|
+
}
|
|
28170
|
+
async getRelatedEntities(entityId) {
|
|
28171
|
+
return this.request("GET", `/memory/entities/${entityId}/related`);
|
|
28172
|
+
}
|
|
28173
|
+
async searchMemoryEntities(workspaceId, query, options) {
|
|
28174
|
+
const params = new URLSearchParams;
|
|
28175
|
+
params.set("workspace_id", workspaceId);
|
|
28176
|
+
params.set("q", query);
|
|
28177
|
+
if (options?.project_id)
|
|
28178
|
+
params.set("project_id", options.project_id);
|
|
28179
|
+
if (options?.type)
|
|
28180
|
+
params.set("type", options.type);
|
|
28181
|
+
if (options?.limit !== undefined)
|
|
28182
|
+
params.set("limit", String(options.limit));
|
|
28183
|
+
return this.request("GET", `/memory/search?${params.toString()}`);
|
|
28184
|
+
}
|
|
28129
28185
|
async processNLU(data) {
|
|
28130
28186
|
return this.request("POST", "/nlu", data);
|
|
28131
28187
|
}
|
|
@@ -28367,7 +28423,7 @@ ${lines.join(`
|
|
|
28367
28423
|
`)}`;
|
|
28368
28424
|
}
|
|
28369
28425
|
function generatePrompt(options) {
|
|
28370
|
-
const { card, column, variant, customConstraints } = options;
|
|
28426
|
+
const { card, column, variant, customConstraints, memories } = options;
|
|
28371
28427
|
const contextOpts = {
|
|
28372
28428
|
includeTitle: true,
|
|
28373
28429
|
includeDescription: true,
|
|
@@ -28430,6 +28486,17 @@ ${card.description}`);
|
|
|
28430
28486
|
roleFraming.outputSuggestions.forEach((s) => {
|
|
28431
28487
|
sections.push(`- ${s}`);
|
|
28432
28488
|
});
|
|
28489
|
+
if (memories && memories.length > 0) {
|
|
28490
|
+
sections.push(`
|
|
28491
|
+
## Relevant Memories`);
|
|
28492
|
+
sections.push(`*${memories.length} memories recalled from knowledge graph:*`);
|
|
28493
|
+
for (const memory of memories) {
|
|
28494
|
+
const tags = memory.tags.length > 0 ? ` [${memory.tags.join(", ")}]` : "";
|
|
28495
|
+
sections.push(`
|
|
28496
|
+
### ${memory.title} (${memory.type}, confidence: ${memory.confidence})${tags}`);
|
|
28497
|
+
sections.push(memory.content);
|
|
28498
|
+
}
|
|
28499
|
+
}
|
|
28433
28500
|
if (customConstraints) {
|
|
28434
28501
|
sections.push(`
|
|
28435
28502
|
## Additional Instructions
|
|
@@ -28450,7 +28517,8 @@ ${customConstraints}`);
|
|
|
28450
28517
|
labelCount: labels.length,
|
|
28451
28518
|
subtaskCount: subtasks.length,
|
|
28452
28519
|
completedSubtasks: subtasks.filter((s) => s.completed).length,
|
|
28453
|
-
linkedCardCount: links.length
|
|
28520
|
+
linkedCardCount: links.length,
|
|
28521
|
+
memoryCount: memories?.length || 0
|
|
28454
28522
|
},
|
|
28455
28523
|
tokenEstimate: estimateTokens(prompt)
|
|
28456
28524
|
};
|
|
@@ -28967,6 +29035,192 @@ var TOOLS = {
|
|
|
28967
29035
|
required: []
|
|
28968
29036
|
}
|
|
28969
29037
|
},
|
|
29038
|
+
harmony_remember: {
|
|
29039
|
+
description: "Store a memory entity (knowledge, pattern, decision, error/solution pair, etc.) for persistence across sessions. Accepts markdown with YAML frontmatter or structured fields.",
|
|
29040
|
+
inputSchema: {
|
|
29041
|
+
type: "object",
|
|
29042
|
+
properties: {
|
|
29043
|
+
title: { type: "string", description: "Memory title" },
|
|
29044
|
+
content: {
|
|
29045
|
+
type: "string",
|
|
29046
|
+
description: "Memory content (markdown body)"
|
|
29047
|
+
},
|
|
29048
|
+
type: {
|
|
29049
|
+
type: "string",
|
|
29050
|
+
enum: [
|
|
29051
|
+
"agent",
|
|
29052
|
+
"task",
|
|
29053
|
+
"decision",
|
|
29054
|
+
"context",
|
|
29055
|
+
"pattern",
|
|
29056
|
+
"error",
|
|
29057
|
+
"solution",
|
|
29058
|
+
"preference"
|
|
29059
|
+
],
|
|
29060
|
+
description: "Entity type (default: context)"
|
|
29061
|
+
},
|
|
29062
|
+
scope: {
|
|
29063
|
+
type: "string",
|
|
29064
|
+
enum: ["private", "project", "workspace", "global"],
|
|
29065
|
+
description: "Visibility scope (default: project). Private = only creator can see."
|
|
29066
|
+
},
|
|
29067
|
+
tags: {
|
|
29068
|
+
type: "array",
|
|
29069
|
+
items: { type: "string" },
|
|
29070
|
+
description: "Tags for categorization and filtering"
|
|
29071
|
+
},
|
|
29072
|
+
confidence: {
|
|
29073
|
+
type: "number",
|
|
29074
|
+
description: "Confidence score 0-1 (default: 1.0)"
|
|
29075
|
+
},
|
|
29076
|
+
metadata: {
|
|
29077
|
+
type: "object",
|
|
29078
|
+
description: "Additional structured metadata"
|
|
29079
|
+
},
|
|
29080
|
+
workspaceId: {
|
|
29081
|
+
type: "string",
|
|
29082
|
+
description: "Workspace ID (optional if context set)"
|
|
29083
|
+
},
|
|
29084
|
+
projectId: {
|
|
29085
|
+
type: "string",
|
|
29086
|
+
description: "Project ID (optional, required if scope is 'project')"
|
|
29087
|
+
}
|
|
29088
|
+
},
|
|
29089
|
+
required: ["title", "content"]
|
|
29090
|
+
}
|
|
29091
|
+
},
|
|
29092
|
+
harmony_recall: {
|
|
29093
|
+
description: "Retrieve memories by type, tags, scope, or text query. Returns matching knowledge entities.",
|
|
29094
|
+
inputSchema: {
|
|
29095
|
+
type: "object",
|
|
29096
|
+
properties: {
|
|
29097
|
+
type: {
|
|
29098
|
+
type: "string",
|
|
29099
|
+
enum: [
|
|
29100
|
+
"agent",
|
|
29101
|
+
"task",
|
|
29102
|
+
"decision",
|
|
29103
|
+
"context",
|
|
29104
|
+
"pattern",
|
|
29105
|
+
"error",
|
|
29106
|
+
"solution",
|
|
29107
|
+
"preference"
|
|
29108
|
+
],
|
|
29109
|
+
description: "Filter by entity type"
|
|
29110
|
+
},
|
|
29111
|
+
tags: {
|
|
29112
|
+
type: "array",
|
|
29113
|
+
items: { type: "string" },
|
|
29114
|
+
description: "Filter by tags (matches any)"
|
|
29115
|
+
},
|
|
29116
|
+
scope: {
|
|
29117
|
+
type: "string",
|
|
29118
|
+
enum: ["private", "project", "workspace", "global"],
|
|
29119
|
+
description: "Filter by scope"
|
|
29120
|
+
},
|
|
29121
|
+
query: {
|
|
29122
|
+
type: "string",
|
|
29123
|
+
description: "Text query to filter by title"
|
|
29124
|
+
},
|
|
29125
|
+
minConfidence: {
|
|
29126
|
+
type: "number",
|
|
29127
|
+
description: "Minimum confidence threshold (0-1)"
|
|
29128
|
+
},
|
|
29129
|
+
workspaceId: {
|
|
29130
|
+
type: "string",
|
|
29131
|
+
description: "Workspace ID (optional if context set)"
|
|
29132
|
+
},
|
|
29133
|
+
projectId: {
|
|
29134
|
+
type: "string",
|
|
29135
|
+
description: "Project ID (optional)"
|
|
29136
|
+
},
|
|
29137
|
+
limit: { type: "number", description: "Max results (default: 20)" }
|
|
29138
|
+
}
|
|
29139
|
+
}
|
|
29140
|
+
},
|
|
29141
|
+
harmony_forget: {
|
|
29142
|
+
description: "Archive or delete a memory entity by ID.",
|
|
29143
|
+
inputSchema: {
|
|
29144
|
+
type: "object",
|
|
29145
|
+
properties: {
|
|
29146
|
+
entityId: {
|
|
29147
|
+
type: "string",
|
|
29148
|
+
description: "Memory entity UUID to delete"
|
|
29149
|
+
}
|
|
29150
|
+
},
|
|
29151
|
+
required: ["entityId"]
|
|
29152
|
+
}
|
|
29153
|
+
},
|
|
29154
|
+
harmony_relate: {
|
|
29155
|
+
description: "Create a typed relationship between two memory entities. Relation types: learned_from, resolved_by, contradicts, supports, depends_on, part_of, caused_by.",
|
|
29156
|
+
inputSchema: {
|
|
29157
|
+
type: "object",
|
|
29158
|
+
properties: {
|
|
29159
|
+
sourceId: {
|
|
29160
|
+
type: "string",
|
|
29161
|
+
description: "Source entity UUID"
|
|
29162
|
+
},
|
|
29163
|
+
targetId: {
|
|
29164
|
+
type: "string",
|
|
29165
|
+
description: "Target entity UUID"
|
|
29166
|
+
},
|
|
29167
|
+
relationType: {
|
|
29168
|
+
type: "string",
|
|
29169
|
+
enum: [
|
|
29170
|
+
"learned_from",
|
|
29171
|
+
"resolved_by",
|
|
29172
|
+
"contradicts",
|
|
29173
|
+
"supports",
|
|
29174
|
+
"depends_on",
|
|
29175
|
+
"part_of",
|
|
29176
|
+
"caused_by"
|
|
29177
|
+
],
|
|
29178
|
+
description: "Type of relationship between entities"
|
|
29179
|
+
},
|
|
29180
|
+
confidence: {
|
|
29181
|
+
type: "number",
|
|
29182
|
+
description: "Relation confidence 0-1 (default: 1.0)"
|
|
29183
|
+
}
|
|
29184
|
+
},
|
|
29185
|
+
required: ["sourceId", "targetId", "relationType"]
|
|
29186
|
+
}
|
|
29187
|
+
},
|
|
29188
|
+
harmony_memory_search: {
|
|
29189
|
+
description: "Full-text search across the knowledge base. Returns entities matching the query, ranked by confidence.",
|
|
29190
|
+
inputSchema: {
|
|
29191
|
+
type: "object",
|
|
29192
|
+
properties: {
|
|
29193
|
+
query: {
|
|
29194
|
+
type: "string",
|
|
29195
|
+
description: "Search query (full-text search)"
|
|
29196
|
+
},
|
|
29197
|
+
type: {
|
|
29198
|
+
type: "string",
|
|
29199
|
+
enum: [
|
|
29200
|
+
"agent",
|
|
29201
|
+
"task",
|
|
29202
|
+
"decision",
|
|
29203
|
+
"context",
|
|
29204
|
+
"pattern",
|
|
29205
|
+
"error",
|
|
29206
|
+
"solution",
|
|
29207
|
+
"preference"
|
|
29208
|
+
],
|
|
29209
|
+
description: "Filter results by entity type"
|
|
29210
|
+
},
|
|
29211
|
+
workspaceId: {
|
|
29212
|
+
type: "string",
|
|
29213
|
+
description: "Workspace ID (optional if context set)"
|
|
29214
|
+
},
|
|
29215
|
+
projectId: {
|
|
29216
|
+
type: "string",
|
|
29217
|
+
description: "Project ID (optional)"
|
|
29218
|
+
},
|
|
29219
|
+
limit: { type: "number", description: "Max results (default: 20)" }
|
|
29220
|
+
},
|
|
29221
|
+
required: ["query"]
|
|
29222
|
+
}
|
|
29223
|
+
},
|
|
28970
29224
|
harmony_create_plan: {
|
|
28971
29225
|
description: "Create a new project plan. Use this to upload implementation plans created during planning. Returns a URL where the plan can be viewed and edited in Harmony.",
|
|
28972
29226
|
inputSchema: {
|
|
@@ -29476,12 +29730,36 @@ class HarmonyMCPServer {
|
|
|
29476
29730
|
if (args.includeDescription !== undefined) {
|
|
29477
29731
|
contextOptions.includeDescription = args.includeDescription === true || args.includeDescription === "true";
|
|
29478
29732
|
}
|
|
29733
|
+
let memories;
|
|
29734
|
+
try {
|
|
29735
|
+
const workspaceId = getActiveWorkspaceId();
|
|
29736
|
+
if (workspaceId && cardData.title) {
|
|
29737
|
+
const memoryResult = await client2.searchMemoryEntities(workspaceId, cardData.title, {
|
|
29738
|
+
project_id: getActiveProjectId() || undefined,
|
|
29739
|
+
limit: 5
|
|
29740
|
+
});
|
|
29741
|
+
if (memoryResult.entities?.length > 0) {
|
|
29742
|
+
memories = memoryResult.entities.map((e) => {
|
|
29743
|
+
const entity = e;
|
|
29744
|
+
return {
|
|
29745
|
+
id: entity.id,
|
|
29746
|
+
type: entity.type,
|
|
29747
|
+
title: entity.title,
|
|
29748
|
+
content: entity.content,
|
|
29749
|
+
confidence: entity.confidence,
|
|
29750
|
+
tags: entity.tags || []
|
|
29751
|
+
};
|
|
29752
|
+
});
|
|
29753
|
+
}
|
|
29754
|
+
}
|
|
29755
|
+
} catch {}
|
|
29479
29756
|
const result = generatePrompt({
|
|
29480
29757
|
card: cardData,
|
|
29481
29758
|
column: columnData,
|
|
29482
29759
|
variant,
|
|
29483
29760
|
contextOptions,
|
|
29484
|
-
customConstraints: args.customConstraints
|
|
29761
|
+
customConstraints: args.customConstraints,
|
|
29762
|
+
memories
|
|
29485
29763
|
});
|
|
29486
29764
|
return {
|
|
29487
29765
|
success: true,
|
|
@@ -29491,6 +29769,82 @@ class HarmonyMCPServer {
|
|
|
29491
29769
|
...result
|
|
29492
29770
|
};
|
|
29493
29771
|
}
|
|
29772
|
+
case "harmony_remember": {
|
|
29773
|
+
const title = exports_external.string().min(1).parse(args.title);
|
|
29774
|
+
const content = exports_external.string().min(1).parse(args.content);
|
|
29775
|
+
const workspaceId = args.workspaceId || getActiveWorkspaceId();
|
|
29776
|
+
if (!workspaceId) {
|
|
29777
|
+
throw new Error("No workspace specified. Use harmony_set_workspace_context or provide workspaceId.");
|
|
29778
|
+
}
|
|
29779
|
+
const result = await client2.createMemoryEntity({
|
|
29780
|
+
workspace_id: workspaceId,
|
|
29781
|
+
project_id: args.projectId || getActiveProjectId() || undefined,
|
|
29782
|
+
type: args.type || "context",
|
|
29783
|
+
scope: args.scope || "project",
|
|
29784
|
+
title,
|
|
29785
|
+
content,
|
|
29786
|
+
metadata: args.metadata,
|
|
29787
|
+
confidence: args.confidence,
|
|
29788
|
+
tags: args.tags,
|
|
29789
|
+
agent_identifier: "claude-code"
|
|
29790
|
+
});
|
|
29791
|
+
return { success: true, ...result };
|
|
29792
|
+
}
|
|
29793
|
+
case "harmony_recall": {
|
|
29794
|
+
const workspaceId = args.workspaceId || getActiveWorkspaceId();
|
|
29795
|
+
if (!workspaceId) {
|
|
29796
|
+
throw new Error("No workspace specified. Use harmony_set_workspace_context or provide workspaceId.");
|
|
29797
|
+
}
|
|
29798
|
+
const result = await client2.listMemoryEntities({
|
|
29799
|
+
workspace_id: workspaceId,
|
|
29800
|
+
project_id: args.projectId || getActiveProjectId() || undefined,
|
|
29801
|
+
type: args.type,
|
|
29802
|
+
scope: args.scope,
|
|
29803
|
+
tags: args.tags,
|
|
29804
|
+
min_confidence: args.minConfidence,
|
|
29805
|
+
q: args.query,
|
|
29806
|
+
limit: args.limit
|
|
29807
|
+
});
|
|
29808
|
+
return { success: true, ...result };
|
|
29809
|
+
}
|
|
29810
|
+
case "harmony_forget": {
|
|
29811
|
+
const entityId = exports_external.string().uuid().parse(args.entityId);
|
|
29812
|
+
await client2.deleteMemoryEntity(entityId);
|
|
29813
|
+
return { success: true };
|
|
29814
|
+
}
|
|
29815
|
+
case "harmony_relate": {
|
|
29816
|
+
const sourceId = exports_external.string().uuid().parse(args.sourceId);
|
|
29817
|
+
const targetId = exports_external.string().uuid().parse(args.targetId);
|
|
29818
|
+
const relationType = exports_external.enum([
|
|
29819
|
+
"learned_from",
|
|
29820
|
+
"resolved_by",
|
|
29821
|
+
"contradicts",
|
|
29822
|
+
"supports",
|
|
29823
|
+
"depends_on",
|
|
29824
|
+
"part_of",
|
|
29825
|
+
"caused_by"
|
|
29826
|
+
]).parse(args.relationType);
|
|
29827
|
+
const result = await client2.createMemoryRelation({
|
|
29828
|
+
source_id: sourceId,
|
|
29829
|
+
target_id: targetId,
|
|
29830
|
+
relation_type: relationType,
|
|
29831
|
+
confidence: args.confidence
|
|
29832
|
+
});
|
|
29833
|
+
return { success: true, ...result };
|
|
29834
|
+
}
|
|
29835
|
+
case "harmony_memory_search": {
|
|
29836
|
+
const query = exports_external.string().min(1).parse(args.query);
|
|
29837
|
+
const workspaceId = args.workspaceId || getActiveWorkspaceId();
|
|
29838
|
+
if (!workspaceId) {
|
|
29839
|
+
throw new Error("No workspace specified. Use harmony_set_workspace_context or provide workspaceId.");
|
|
29840
|
+
}
|
|
29841
|
+
const result = await client2.searchMemoryEntities(workspaceId, query, {
|
|
29842
|
+
project_id: args.projectId || getActiveProjectId() || undefined,
|
|
29843
|
+
type: args.type,
|
|
29844
|
+
limit: args.limit
|
|
29845
|
+
});
|
|
29846
|
+
return { success: true, ...result };
|
|
29847
|
+
}
|
|
29494
29848
|
case "harmony_create_plan": {
|
|
29495
29849
|
const title = exports_external.string().min(1).parse(args.title);
|
|
29496
29850
|
const projectId = args.projectId || getProjectId();
|