@vheins/local-memory-mcp 0.19.5 → 0.19.6

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.
@@ -1070,7 +1070,15 @@ var BaseEntity = class {
1070
1070
  status: r.status || "active",
1071
1071
  is_global: r.is_global === 1,
1072
1072
  tags: this.safeJSONParse(r.tags, []),
1073
- metadata: this.safeJSONParse(r.metadata, {})
1073
+ metadata: (() => {
1074
+ const meta = this.safeJSONParse(r.metadata, {});
1075
+ delete meta.structuredData;
1076
+ return meta;
1077
+ })(),
1078
+ structuredData: (() => {
1079
+ const meta = this.safeJSONParse(r.metadata, {});
1080
+ return meta.structuredData ?? void 0;
1081
+ })()
1074
1082
  };
1075
1083
  }
1076
1084
  rowToTask(row) {
@@ -1162,6 +1170,7 @@ var VALID_COLUMNS = /* @__PURE__ */ new Set([
1162
1170
  ]);
1163
1171
  var MemoryEntity = class extends BaseEntity {
1164
1172
  insert(entry) {
1173
+ const mergedMeta = this.mergeStructuredData(entry.metadata, entry.structuredData);
1165
1174
  this.run(
1166
1175
  `INSERT INTO memories (
1167
1176
  id, code, repo, owner, type, title, content, importance, folder, language,
@@ -1186,7 +1195,7 @@ var MemoryEntity = class extends BaseEntity {
1186
1195
  entry.status || "active",
1187
1196
  entry.is_global ? 1 : 0,
1188
1197
  entry.tags ? JSON.stringify(entry.tags) : null,
1189
- entry.metadata ? JSON.stringify(entry.metadata) : null,
1198
+ mergedMeta ? JSON.stringify(mergedMeta) : null,
1190
1199
  entry.agent || "unknown",
1191
1200
  entry.role || "unknown",
1192
1201
  entry.model || "unknown",
@@ -1194,6 +1203,9 @@ var MemoryEntity = class extends BaseEntity {
1194
1203
  ]
1195
1204
  );
1196
1205
  }
1206
+ mergeStructuredData(metadata, structuredData) {
1207
+ return { ...metadata, structuredData: structuredData ?? {} };
1208
+ }
1197
1209
  update(id, updates) {
1198
1210
  const fields = [];
1199
1211
  const values = [];
@@ -1219,6 +1231,12 @@ var MemoryEntity = class extends BaseEntity {
1219
1231
  fields.push("language = ?");
1220
1232
  values.push(scope.language);
1221
1233
  }
1234
+ } else if (k === "structuredData") {
1235
+ const existingRow = this.get("SELECT metadata FROM memories WHERE id = ?", [id]);
1236
+ const existingMeta = existingRow ? this.safeJSONParse(existingRow.metadata, {}) : {};
1237
+ const merged = { ...existingMeta, structuredData: val };
1238
+ fields.push("metadata = ?");
1239
+ values.push(JSON.stringify(merged));
1222
1240
  } else if (k === "tags" || k === "metadata") {
1223
1241
  fields.push(`${k} = ?`);
1224
1242
  values.push(JSON.stringify(val));
@@ -1322,6 +1340,7 @@ var MemoryEntity = class extends BaseEntity {
1322
1340
  return this.transaction(() => {
1323
1341
  let count = 0;
1324
1342
  for (const entry of entries) {
1343
+ const mergedMeta = this.mergeStructuredData(entry.metadata, entry.structuredData);
1325
1344
  this.run(
1326
1345
  `INSERT INTO memories (
1327
1346
  id, repo, owner, type, title, content, importance, folder, language,
@@ -1345,7 +1364,7 @@ var MemoryEntity = class extends BaseEntity {
1345
1364
  entry.status || "active",
1346
1365
  entry.is_global ? 1 : 0,
1347
1366
  entry.tags ? JSON.stringify(entry.tags) : null,
1348
- entry.metadata ? JSON.stringify(entry.metadata) : null,
1367
+ mergedMeta ? JSON.stringify(mergedMeta) : null,
1349
1368
  entry.agent || "unknown",
1350
1369
  entry.role || "unknown",
1351
1370
  entry.model || "unknown",
@@ -6457,6 +6476,28 @@ var SingleStandardSchema = z2.object({
6457
6476
  model: z2.string().optional()
6458
6477
  });
6459
6478
  var TaskStatusValues = TaskStatusSchema.options;
6479
+ function isPlainObject(v) {
6480
+ return typeof v === "object" && v !== null && !Array.isArray(v) && Object.getPrototypeOf(v) === Object.prototype;
6481
+ }
6482
+ function isJsonSerializable(val) {
6483
+ try {
6484
+ JSON.stringify(val);
6485
+ return true;
6486
+ } catch {
6487
+ return false;
6488
+ }
6489
+ }
6490
+ var StructuredDataValue = z2.lazy(
6491
+ () => z2.union([
6492
+ z2.string(),
6493
+ z2.number().refine((v) => Number.isFinite(v), "Number must be finite"),
6494
+ z2.boolean(),
6495
+ z2.null(),
6496
+ z2.array(StructuredDataValue),
6497
+ z2.record(z2.string(), StructuredDataValue).refine(isPlainObject, "Plain object required")
6498
+ ])
6499
+ );
6500
+ var StructuredDataSchema = z2.unknown().refine(isJsonSerializable, { message: "Value must be JSON-serializable" }).pipe(z2.record(z2.string(), StructuredDataValue));
6460
6501
 
6461
6502
  // src/mcp/tools/schemas/memory.ts
6462
6503
  import { z as z3 } from "zod";
@@ -6538,8 +6579,8 @@ var MemoryAcknowledgeSchema = z3.object({
6538
6579
  message: "Either memory_id or code must be provided"
6539
6580
  });
6540
6581
  var MemoryRecapSchema = z3.object({
6541
- owner: z3.string().min(1),
6542
- repo: z3.string().min(1).transform(normalizeRepo),
6582
+ owner: z3.string().min(1, "owner is required \u2014 provide it explicitly or configure MCP workspace roots"),
6583
+ repo: z3.string().min(1, "repo is required \u2014 provide it explicitly or configure MCP workspace roots").transform(normalizeRepo),
6543
6584
  limit: z3.number().min(1).max(50).default(20),
6544
6585
  offset: z3.number().min(0).default(0),
6545
6586
  structured: z3.boolean().default(false)
@@ -6729,8 +6770,8 @@ var TaskUpdateSchema = z4.object({
6729
6770
  message: "At least one field besides repo and id/ids must be provided for update"
6730
6771
  });
6731
6772
  var TaskListSchema = z4.object({
6732
- owner: z4.string().min(1),
6733
- repo: z4.string().min(1).transform(normalizeRepo),
6773
+ owner: z4.string().min(1, "owner is required \u2014 provide it explicitly or configure MCP workspace roots"),
6774
+ repo: z4.string().min(1, "repo is required \u2014 provide it explicitly or configure MCP workspace roots").transform(normalizeRepo),
6734
6775
  status: TaskStatusListSchema.default("backlog,pending,in_progress,blocked"),
6735
6776
  phase: z4.string().optional(),
6736
6777
  query: z4.string().optional(),
@@ -6759,7 +6800,9 @@ var TaskDeleteSchema = z4.object({
6759
6800
  structured: z4.boolean().default(false)
6760
6801
  }).refine(
6761
6802
  (data) => data.id !== void 0 || data.ids !== void 0 || data.task_code !== void 0 || data.task_codes !== void 0,
6762
- { message: "Either 'id', 'ids', 'task_code', or 'task_codes' must be provided for deletion" }
6803
+ {
6804
+ message: "Either 'id' (UUID), 'ids' (array of UUIDs), 'task_code' (string code like PERF-1), or 'task_codes' (array of string codes) must be provided. Note: 'ids' expects UUID format, not task codes \u2014 use 'task_code'/'task_codes' for string identifiers."
6805
+ }
6763
6806
  );
6764
6807
  var TaskGetSchema = z4.object({
6765
6808
  owner: z4.string().min(1),
@@ -6775,8 +6818,8 @@ var TaskGetSchema = z4.object({
6775
6818
  // src/mcp/tools/schemas/handoff.ts
6776
6819
  import { z as z5 } from "zod";
6777
6820
  var HandoffCreateSchema = z5.object({
6778
- owner: z5.string().min(1).optional().default(""),
6779
- repo: z5.string().min(1).transform(normalizeRepo),
6821
+ owner: z5.string().min(1, "owner is required \u2014 provide it explicitly or configure MCP workspace roots"),
6822
+ repo: z5.string().min(1, "repo is required \u2014 provide it explicitly or configure MCP workspace roots").transform(normalizeRepo),
6780
6823
  from_agent: z5.string().min(1),
6781
6824
  to_agent: z5.string().min(1).optional(),
6782
6825
  task_id: z5.string().uuid().optional(),
@@ -6799,8 +6842,8 @@ var HandoffUpdateSchema = z5.object({
6799
6842
  structured: z5.boolean().default(false)
6800
6843
  });
6801
6844
  var HandoffListSchema = z5.object({
6802
- owner: z5.string().min(1).optional().default(""),
6803
- repo: z5.string().min(1).transform(normalizeRepo),
6845
+ owner: z5.string().min(1, "owner is required \u2014 provide it explicitly or configure MCP workspace roots"),
6846
+ repo: z5.string().min(1, "repo is required \u2014 provide it explicitly or configure MCP workspace roots").transform(normalizeRepo),
6804
6847
  status: HandoffStatusSchema.optional(),
6805
6848
  from_agent: z5.string().min(1).optional(),
6806
6849
  to_agent: z5.string().min(1).optional(),
@@ -6809,8 +6852,8 @@ var HandoffListSchema = z5.object({
6809
6852
  structured: z5.boolean().default(false)
6810
6853
  });
6811
6854
  var TaskClaimSchema = z5.object({
6812
- owner: z5.string().min(1).optional().default(""),
6813
- repo: z5.string().min(1).transform(normalizeRepo),
6855
+ owner: z5.string().min(1, "owner is required \u2014 provide it explicitly or configure MCP workspace roots"),
6856
+ repo: z5.string().min(1, "repo is required \u2014 provide it explicitly or configure MCP workspace roots").transform(normalizeRepo),
6814
6857
  task_id: z5.string().uuid().optional(),
6815
6858
  task_code: z5.string().optional(),
6816
6859
  agent: z5.string().min(1),
@@ -6823,8 +6866,8 @@ var TaskClaimSchema = z5.object({
6823
6866
  message: "Provide either task_id or task_code, not both"
6824
6867
  });
6825
6868
  var ClaimListSchema = z5.object({
6826
- owner: z5.string().min(1).optional().default(""),
6827
- repo: z5.string().min(1).transform(normalizeRepo),
6869
+ owner: z5.string().optional().default(""),
6870
+ repo: z5.string().transform(normalizeRepo).optional().default(""),
6828
6871
  agent: z5.string().min(1).optional(),
6829
6872
  active_only: z5.boolean().default(true),
6830
6873
  limit: z5.number().min(1).max(100).default(20),
@@ -6832,8 +6875,8 @@ var ClaimListSchema = z5.object({
6832
6875
  structured: z5.boolean().default(false)
6833
6876
  });
6834
6877
  var ClaimReleaseSchema = z5.object({
6835
- owner: z5.string().min(1).optional().default(""),
6836
- repo: z5.string().min(1).transform(normalizeRepo),
6878
+ owner: z5.string().min(1, "owner is required \u2014 provide it explicitly or configure MCP workspace roots"),
6879
+ repo: z5.string().min(1, "repo is required \u2014 provide it explicitly or configure MCP workspace roots").transform(normalizeRepo),
6837
6880
  task_id: z5.string().uuid().optional(),
6838
6881
  task_code: z5.string().optional(),
6839
6882
  agent: z5.string().min(1).optional(),
@@ -7070,7 +7113,13 @@ async function handleHandoffCreate(args, storage) {
7070
7113
  });
7071
7114
  }
7072
7115
  async function handleHandoffList(args, storage) {
7073
- const validated = HandoffListSchema.parse(args);
7116
+ const parsed = HandoffListSchema.safeParse(args);
7117
+ if (!parsed.success) {
7118
+ const missing = parsed.error.issues.filter((i) => i.path.some((p) => p === "owner" || p === "repo")).map((i) => i.message).filter(Boolean);
7119
+ const msg = missing.length > 0 ? `Missing required fields: ${missing.join("; ")}. Pass owner/repo explicitly or configure MCP workspace roots so they can be auto-inferred.` : `Validation error: ${parsed.error.message}`;
7120
+ return { content: [{ type: "text", text: msg }], isError: true };
7121
+ }
7122
+ const validated = parsed.data;
7074
7123
  const { owner, repo, status, from_agent, to_agent, limit, offset, structured } = validated;
7075
7124
  const handoffs = storage.handoffs.listHandoffs({
7076
7125
  owner,
@@ -15,7 +15,7 @@ import {
15
15
  handleTaskClaim,
16
16
  listResources,
17
17
  logger
18
- } from "../chunk-ZSGQQS5F.js";
18
+ } from "../chunk-IT2PAPJ6.js";
19
19
 
20
20
  // src/dashboard/server.ts
21
21
  import express from "express";
@@ -61,7 +61,7 @@ import {
61
61
  parseRepoInput,
62
62
  rankCompletionValues,
63
63
  toContextSlug
64
- } from "../chunk-ZSGQQS5F.js";
64
+ } from "../chunk-IT2PAPJ6.js";
65
65
 
66
66
  // src/mcp/server.ts
67
67
  import { serveStdio } from "@modelcontextprotocol/server/stdio";
@@ -74,8 +74,8 @@ import path from "path";
74
74
  import { fileURLToPath } from "url";
75
75
  var __dirname = path.dirname(fileURLToPath(import.meta.url));
76
76
  var pkgVersion = "0.1.0";
77
- if ("0.19.5") {
78
- pkgVersion = "0.19.5";
77
+ if ("0.19.6") {
78
+ pkgVersion = "0.19.6";
79
79
  } else {
80
80
  let searchDir = __dirname;
81
81
  for (let i = 0; i < 5; i++) {
@@ -1118,7 +1118,13 @@ function extractAcceptedElicitationContent(result) {
1118
1118
 
1119
1119
  // src/mcp/tools/memory.recap.ts
1120
1120
  async function handleMemoryRecap(params, db2) {
1121
- const validated = MemoryRecapSchema.parse(params);
1121
+ const parsed = MemoryRecapSchema.safeParse(params);
1122
+ if (!parsed.success) {
1123
+ const missing = parsed.error.issues.filter((i) => i.path.some((p) => p === "owner" || p === "repo")).map((i) => i.message).filter(Boolean);
1124
+ const msg = missing.length > 0 ? `Missing required fields: ${missing.join("; ")}. Pass owner/repo explicitly or configure MCP workspace roots so they can be auto-inferred.` : `Validation error: ${parsed.error.message}`;
1125
+ return { content: [{ type: "text", text: msg }], isError: true };
1126
+ }
1127
+ const validated = parsed.data;
1122
1128
  logger.info("[Tool] memory.recap", { repo: validated.repo, limit: validated.limit, offset: validated.offset });
1123
1129
  const stats = db2.memories.getStats(validated.owner, validated.repo);
1124
1130
  const total = db2.memories.getTotalCount(validated.owner, validated.repo, false, ["task_archive"]);
@@ -1241,7 +1247,13 @@ function capitalize3(str) {
1241
1247
  return str.charAt(0).toUpperCase() + str.slice(1);
1242
1248
  }
1243
1249
  async function handleTaskList(args, storage) {
1244
- const validated = TaskListSchema.parse(args);
1250
+ const parsed = TaskListSchema.safeParse(args);
1251
+ if (!parsed.success) {
1252
+ const missing = parsed.error.issues.filter((i) => i.path.some((p) => p === "owner" || p === "repo")).map((i) => i.message).filter(Boolean);
1253
+ const msg = missing.length > 0 ? `Missing required fields: ${missing.join("; ")}. Pass owner/repo explicitly or configure MCP workspace roots so they can be auto-inferred.` : `Validation error: ${parsed.error.message}`;
1254
+ return { content: [{ type: "text", text: msg }], isError: true };
1255
+ }
1256
+ const validated = parsed.data;
1245
1257
  const { owner, repo, status, phase, query, limit, offset, structured: isStructuredRequest = false } = validated;
1246
1258
  let statuses = [];
1247
1259
  if (status !== "all") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vheins/local-memory-mcp",
3
- "version": "0.19.5",
3
+ "version": "0.19.6",
4
4
  "description": "MCP Local Memory Service for coding copilot agents",
5
5
  "mcpName": "io.github.vheins/local-memory-mcp",
6
6
  "type": "module",