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.
Files changed (3) hide show
  1. package/dist/cli.js +357 -3
  2. package/dist/index.js +357 -3
  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();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harmony-mcp",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "MCP server for Harmony Kanban board - enables AI coding agents to manage your boards",
5
5
  "publishConfig": {
6
6
  "access": "public"