@datacore-one/mcp 1.1.0 → 1.1.1

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 CHANGED
@@ -237,7 +237,7 @@ function getConfig() {
237
237
  // package.json
238
238
  var package_default = {
239
239
  name: "@datacore-one/mcp",
240
- version: "1.1.0",
240
+ version: "1.1.1",
241
241
  description: "Datacore MCP server \u2014 The Software of You",
242
242
  type: "module",
243
243
  bin: {
@@ -933,7 +933,15 @@ async function handleInject(args2, paths) {
933
933
  const result = selectEngrams(ctx, personalEngrams, packs);
934
934
  const totalCount = result.directives.length + result.consider.length;
935
935
  if (totalCount === 0) {
936
- return { text: "", count: 0, tokens_used: 0 };
936
+ return {
937
+ text: "",
938
+ count: 0,
939
+ tokens_used: 0,
940
+ _hints: buildHints({
941
+ next: "No engrams matched this task. Use datacore.recall to search all sources, or datacore.learn to record new knowledge.",
942
+ related: ["datacore.recall", "datacore.learn"]
943
+ })
944
+ };
937
945
  }
938
946
  const lines = [];
939
947
  if (result.directives.length > 0) {
@@ -1383,6 +1391,10 @@ async function handleInstall(args2, packsDir) {
1383
1391
  const downloaded = await downloadPack(srcDir);
1384
1392
  if (downloaded.error) return { success: false, error: downloaded.error };
1385
1393
  srcDir = downloaded.path;
1394
+ } else if (!srcDir.includes("/") && !srcDir.includes("\\")) {
1395
+ const resolved = resolvePackId(srcDir, packsDir);
1396
+ if (resolved.error) return { success: false, error: resolved.error };
1397
+ srcDir = resolved.path;
1386
1398
  }
1387
1399
  const skillPath = path9.join(srcDir, "SKILL.md");
1388
1400
  if (!fs11.existsSync(skillPath)) {
@@ -1449,6 +1461,29 @@ function findPackRoot(dir) {
1449
1461
  }
1450
1462
  return null;
1451
1463
  }
1464
+ function resolvePackId(packId, packsDir) {
1465
+ const registryPack = packs_default.packs.find((p) => p.id === packId);
1466
+ if (!registryPack) {
1467
+ return { error: `Pack "${packId}" not found in registry. Use datacore.packs.discover to browse available packs.` };
1468
+ }
1469
+ if (registryPack.download_url) {
1470
+ return { error: `Pack "${packId}" must be installed via URL: ${registryPack.download_url}` };
1471
+ }
1472
+ const bundledDir = path9.join(
1473
+ path9.dirname(new URL(import.meta.url).pathname),
1474
+ "..",
1475
+ "packs",
1476
+ packId
1477
+ );
1478
+ if (fs11.existsSync(path9.join(bundledDir, "SKILL.md"))) {
1479
+ return { path: bundledDir };
1480
+ }
1481
+ const localDir = path9.join(packsDir, packId);
1482
+ if (fs11.existsSync(path9.join(localDir, "SKILL.md"))) {
1483
+ return { path: localDir };
1484
+ }
1485
+ return { error: `Pack "${packId}" is registered but not available locally. It may need to be downloaded manually.` };
1486
+ }
1452
1487
 
1453
1488
  // src/tools/export.ts
1454
1489
  import * as fs12 from "fs";
@@ -1496,6 +1531,12 @@ async function handleExport(args2, paths) {
1496
1531
  }
1497
1532
  };
1498
1533
  }
1534
+ if (fs12.existsSync(packDir)) {
1535
+ return {
1536
+ success: false,
1537
+ error: `Pack directory already exists at ${packDir}. Remove it first or use a different name.`
1538
+ };
1539
+ }
1499
1540
  fs12.mkdirSync(packDir, { recursive: true });
1500
1541
  const skillContent = `---
1501
1542
  name: "${args2.name}"
@@ -1524,6 +1565,7 @@ Exported ${selected.length} engrams.
1524
1565
  visibility: e.visibility,
1525
1566
  statement: e.statement,
1526
1567
  rationale: e.rationale,
1568
+ contraindications: e.contraindications,
1527
1569
  tags: e.tags,
1528
1570
  domain: e.domain,
1529
1571
  status: "active",
@@ -1797,9 +1839,10 @@ async function handleForget(args2, engramsPath) {
1797
1839
  }
1798
1840
  if (args2.search) {
1799
1841
  const searchLower = args2.search.toLowerCase();
1800
- const matches = engrams.filter((e) => e.status !== "retired").filter(
1842
+ const allMatches = engrams.filter((e) => e.status !== "retired").filter(
1801
1843
  (e) => e.statement.toLowerCase().includes(searchLower) || e.id.toLowerCase().includes(searchLower) || e.tags.some((t) => t.toLowerCase().includes(searchLower))
1802
- ).slice(0, 10);
1844
+ );
1845
+ const matches = allMatches.slice(0, 100);
1803
1846
  if (matches.length === 0) {
1804
1847
  return { success: false, error: `No active engrams matching "${args2.search}"` };
1805
1848
  }
@@ -1810,26 +1853,44 @@ async function handleForget(args2, engramsPath) {
1810
1853
  saveEngrams(engramsPath, engrams);
1811
1854
  return { success: true, retired: { id: engram.id, statement: engram.statement } };
1812
1855
  }
1856
+ const truncated = allMatches.length > 100;
1813
1857
  return {
1814
1858
  success: false,
1815
1859
  matches: matches.map((e) => ({ id: e.id, statement: e.statement })),
1816
- error: `Multiple matches found. Specify an exact ID to retire.`
1860
+ total_matches: allMatches.length,
1861
+ error: `${allMatches.length} matches found${truncated ? " (showing first 100)" : ""}. Specify an exact ID to retire.`
1817
1862
  };
1818
1863
  }
1819
1864
  return { success: false, error: "Provide either id or search parameter" };
1820
1865
  }
1821
1866
 
1822
1867
  // src/tools/feedback.ts
1823
- async function handleFeedback(args2, engramsPath) {
1868
+ import * as path13 from "path";
1869
+ function findEngram(engramId, engramsPath, packsPath) {
1870
+ const personal = loadEngrams(engramsPath);
1871
+ const found = personal.find((e) => e.id === engramId);
1872
+ if (found) return { engram: found, source: "personal", personalEngrams: personal };
1873
+ const packs = loadAllPacks(packsPath);
1874
+ for (const pack of packs) {
1875
+ const packEngram = pack.engrams.find((e) => e.id === engramId);
1876
+ if (packEngram) {
1877
+ const packId = pack.manifest["x-datacore"]?.id;
1878
+ const packEngramsPath = packId ? path13.join(packsPath, packId, "engrams.yaml") : void 0;
1879
+ return { engram: packEngram, source: "pack", packEngrams: pack.engrams, packEngramsPath };
1880
+ }
1881
+ }
1882
+ return null;
1883
+ }
1884
+ async function handleFeedback(args2, engramsPath, packsPath) {
1885
+ const pPath = packsPath ?? path13.join(path13.dirname(engramsPath), "packs");
1824
1886
  if (args2.signals && args2.signals.length > 0) {
1825
- return handleBatchFeedback(args2.signals, engramsPath);
1887
+ return handleBatchFeedback(args2.signals, engramsPath, pPath);
1826
1888
  }
1827
- return handleSingleFeedback(args2.engram_id, args2.signal, args2.comment, engramsPath);
1889
+ return handleSingleFeedback(args2.engram_id, args2.signal, args2.comment, engramsPath, pPath);
1828
1890
  }
1829
- async function handleSingleFeedback(engram_id, signal, comment, engramsPath) {
1830
- const engrams = loadEngrams(engramsPath);
1831
- const engram = engrams.find((e) => e.id === engram_id);
1832
- if (!engram) {
1891
+ async function handleSingleFeedback(engram_id, signal, comment, engramsPath, packsPath) {
1892
+ const found = findEngram(engram_id, engramsPath, packsPath);
1893
+ if (!found) {
1833
1894
  return {
1834
1895
  mode: "single",
1835
1896
  success: false,
@@ -1843,29 +1904,55 @@ async function handleSingleFeedback(engram_id, signal, comment, engramsPath) {
1843
1904
  };
1844
1905
  }
1845
1906
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1846
- if (!engram.feedback_signals) {
1847
- engram.feedback_signals = { positive: 0, negative: 0, neutral: 0 };
1907
+ if (!found.engram.feedback_signals) {
1908
+ found.engram.feedback_signals = { positive: 0, negative: 0, neutral: 0 };
1909
+ }
1910
+ found.engram.feedback_signals[signal] += 1;
1911
+ found.engram.activation.last_accessed = today;
1912
+ if (found.source === "personal" && found.personalEngrams) {
1913
+ atomicWriteYaml(engramsPath, { engrams: found.personalEngrams });
1914
+ } else if (found.source === "pack" && found.packEngrams && found.packEngramsPath) {
1915
+ atomicWriteYaml(found.packEngramsPath, { engrams: found.packEngrams });
1848
1916
  }
1849
- engram.feedback_signals[signal] += 1;
1850
- engram.activation.last_accessed = today;
1851
- atomicWriteYaml(engramsPath, { engrams });
1852
1917
  return {
1853
1918
  mode: "single",
1854
1919
  success: true,
1855
1920
  engram_id,
1856
1921
  signal,
1857
- feedback_signals: { ...engram.feedback_signals }
1922
+ source: found.source,
1923
+ feedback_signals: { ...found.engram.feedback_signals }
1858
1924
  };
1859
1925
  }
1860
- async function handleBatchFeedback(signals, engramsPath) {
1861
- const engrams = loadEngrams(engramsPath);
1926
+ async function handleBatchFeedback(signals, engramsPath, packsPath) {
1862
1927
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1863
1928
  const results = [];
1864
1929
  const summary = { positive: 0, negative: 0, neutral: 0 };
1865
- let changed = false;
1930
+ const personal = loadEngrams(engramsPath);
1931
+ const packs = loadAllPacks(packsPath);
1932
+ let personalDirty = false;
1933
+ const dirtyPackFiles = /* @__PURE__ */ new Map();
1866
1934
  for (const { engram_id, signal } of signals) {
1867
- const engram = engrams.find((e) => e.id === engram_id);
1868
- if (!engram) {
1935
+ let engram = personal.find((e) => e.id === engram_id);
1936
+ let source;
1937
+ if (engram) {
1938
+ source = "personal";
1939
+ } else {
1940
+ for (const pack of packs) {
1941
+ engram = pack.engrams.find((e) => e.id === engram_id);
1942
+ if (engram) {
1943
+ source = "pack";
1944
+ const packId = pack.manifest["x-datacore"]?.id;
1945
+ if (packId) {
1946
+ dirtyPackFiles.set(
1947
+ path13.join(packsPath, packId, "engrams.yaml"),
1948
+ pack.engrams
1949
+ );
1950
+ }
1951
+ break;
1952
+ }
1953
+ }
1954
+ }
1955
+ if (!engram || !source) {
1869
1956
  results.push({ engram_id, signal, success: false, error: `Engram ${engram_id} not found` });
1870
1957
  continue;
1871
1958
  }
@@ -1875,11 +1962,14 @@ async function handleBatchFeedback(signals, engramsPath) {
1875
1962
  engram.feedback_signals[signal] += 1;
1876
1963
  engram.activation.last_accessed = today;
1877
1964
  summary[signal]++;
1878
- changed = true;
1879
- results.push({ engram_id, signal, success: true });
1965
+ if (source === "personal") personalDirty = true;
1966
+ results.push({ engram_id, signal, success: true, source });
1880
1967
  }
1881
- if (changed) {
1882
- atomicWriteYaml(engramsPath, { engrams });
1968
+ if (personalDirty) {
1969
+ atomicWriteYaml(engramsPath, { engrams: personal });
1970
+ }
1971
+ for (const [filePath, engrams] of dirtyPackFiles) {
1972
+ atomicWriteYaml(filePath, { engrams });
1883
1973
  }
1884
1974
  return {
1885
1975
  mode: "batch",
@@ -1894,7 +1984,7 @@ async function handleBatchFeedback(signals, engramsPath) {
1894
1984
 
1895
1985
  // src/tools/session-start.ts
1896
1986
  import * as fs15 from "fs";
1897
- import * as path13 from "path";
1987
+ import * as path14 from "path";
1898
1988
  async function handleSessionStart(args2, storage2, bridge) {
1899
1989
  let engrams = null;
1900
1990
  if (args2.task) {
@@ -1907,7 +1997,7 @@ async function handleSessionStart(args2, storage2, bridge) {
1907
1997
  }
1908
1998
  }
1909
1999
  const { date: today } = localDate();
1910
- const journalFile = path13.join(storage2.journalPath, `${today}.md`);
2000
+ const journalFile = path14.join(storage2.journalPath, `${today}.md`);
1911
2001
  const journal_today = fs15.existsSync(journalFile) ? fs15.readFileSync(journalFile, "utf8") : null;
1912
2002
  const allEngrams = loadEngrams(storage2.engramsPath);
1913
2003
  const pending_candidates = allEngrams.filter((e) => e.status === "candidate").length;
@@ -2114,7 +2204,7 @@ import {
2114
2204
  ListResourceTemplatesRequestSchema
2115
2205
  } from "@modelcontextprotocol/sdk/types.js";
2116
2206
  import * as fs16 from "fs";
2117
- import * as path14 from "path";
2207
+ import * as path15 from "path";
2118
2208
  function registerResources(server, storage2) {
2119
2209
  server.setRequestHandler(ListResourcesRequestSchema, async () => ({
2120
2210
  resources: [
@@ -2195,7 +2285,7 @@ function registerResources(server, storage2) {
2195
2285
  const journalMatch = uri.match(/^datacore:\/\/journal\/(.+)$/);
2196
2286
  if (journalMatch) {
2197
2287
  const dateStr = journalMatch[1] === "today" ? localDate().date : journalMatch[1];
2198
- const filePath = path14.join(storage2.journalPath, `${dateStr}.md`);
2288
+ const filePath = path15.join(storage2.journalPath, `${dateStr}.md`);
2199
2289
  if (!fs16.existsSync(filePath)) {
2200
2290
  return { contents: [{ uri, mimeType: "text/markdown", text: `No journal entry for ${dateStr}` }] };
2201
2291
  }
@@ -2431,7 +2521,7 @@ function registerPrompts(server) {
2431
2521
  // src/datacortex.ts
2432
2522
  import { execFile } from "child_process";
2433
2523
  import * as fs17 from "fs";
2434
- import * as path15 from "path";
2524
+ import * as path16 from "path";
2435
2525
  var DatacortexBridge = class {
2436
2526
  pythonPath;
2437
2527
  scriptPath;
@@ -2441,8 +2531,8 @@ var DatacortexBridge = class {
2441
2531
  }
2442
2532
  findBridgeScript(datacorePath) {
2443
2533
  const candidates = [
2444
- path15.join(datacorePath, ".datacore", "modules", "datacortex", "lib", "bridge.py"),
2445
- path15.join(datacorePath, ".datacore", "modules", "datacortex", "bridge.py")
2534
+ path16.join(datacorePath, ".datacore", "modules", "datacortex", "lib", "bridge.py"),
2535
+ path16.join(datacorePath, ".datacore", "modules", "datacortex", "bridge.py")
2446
2536
  ];
2447
2537
  for (const candidate of candidates) {
2448
2538
  if (fs17.existsSync(candidate)) return candidate;
@@ -2579,7 +2669,7 @@ async function routeTool(name, args2) {
2579
2669
  result = await handleForget(validated, storage.engramsPath);
2580
2670
  break;
2581
2671
  case "datacore.feedback":
2582
- result = await handleFeedback(validated, storage.engramsPath);
2672
+ result = await handleFeedback(validated, storage.engramsPath, storage.packsPath);
2583
2673
  break;
2584
2674
  case "datacore.session.start":
2585
2675
  result = await handleSessionStart(validated, storage, datacortexBridge);