@danielblomma/cortex-mcp 2.0.4 → 2.0.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.
package/bin/cortex.mjs CHANGED
@@ -22,17 +22,20 @@ const PACKAGE_ROOT = path.resolve(__dirname, "..");
22
22
  const SCAFFOLD_ROOT = path.join(PACKAGE_ROOT, "scaffold");
23
23
  const PACKAGE_JSON_PATH = path.join(PACKAGE_ROOT, "package.json");
24
24
 
25
+ // v2.0.5: project layout moved mcp/ under .context/mcp/, and the
26
+ // gitignore policy flipped to "ignore everything in .context/, whitelist
27
+ // only the three editable config files". Generated artifacts (db,
28
+ // embeddings, cache, hooks, mcp/, govern.local.json) never land in git.
29
+ const MCP_PROJECT_REL = path.join(".context", "mcp");
30
+
25
31
  const GITIGNORE_LINES = [
26
32
  "",
27
33
  "# Cortex local storage",
28
- ".context/db/",
29
- ".context/embeddings/",
30
- ".context/cache/",
31
- ".context/hooks/",
32
- ".npm-cache/",
33
- "mcp/.npm-cache/",
34
- "mcp/dist/",
35
- "mcp/node_modules/"
34
+ ".context/",
35
+ "!.context/config.yaml",
36
+ "!.context/rules.yaml",
37
+ "!.context/ontology.cypher",
38
+ ".npm-cache/"
36
39
  ];
37
40
 
38
41
  function printBanner(title) {
@@ -86,6 +89,13 @@ function printHelp() {
86
89
  console.log(helpRow("hooks [install|uninstall|status] [--project]", "Claude Code hooks"));
87
90
  console.log(helpRow("telemetry test", "Smoke-test the push pipeline"));
88
91
 
92
+ console.log(helpSection("HARNESS"));
93
+ console.log(helpRow("stage start --task-id <id> --description \"...\"", "Start a workflow run for a task"));
94
+ console.log(helpRow("stage status --task-id <id>", "Print run state JSON"));
95
+ console.log(helpRow("stage envelope --task-id <id> [--stage <name>]", "Compose stage prompt envelope"));
96
+ console.log(helpRow("stage advance --task-id <id> --stage <name> --body-file <path>", "Write artifact, advance run"));
97
+ console.log(helpRow("stage run --task-id <id> -- <command>", "Exec a command with CORTEX_ACTIVE_TASK_ID set"));
98
+
89
99
  console.log(helpSection("MISC"));
90
100
  console.log(helpRow("mcp", "Run the MCP stdio server for the current project"));
91
101
  console.log(helpRow("version", "Print CLI version"));
@@ -199,7 +209,6 @@ const INIT_SKIP_DIRECTORIES = new Set([
199
209
  ".cache",
200
210
  ".context",
201
211
  "scripts",
202
- "mcp",
203
212
  ".githooks",
204
213
  "bin",
205
214
  "obj"
@@ -439,11 +448,26 @@ function mergeGitignore(targetDir) {
439
448
  fs.writeFileSync(gitignorePath, merged, "utf8");
440
449
  }
441
450
 
451
+ function migrateLegacyMcpLocation(targetDir) {
452
+ const legacyMcp = path.join(targetDir, "mcp");
453
+ const newMcp = path.join(targetDir, MCP_PROJECT_REL);
454
+ if (!fs.existsSync(legacyMcp)) return;
455
+ if (fs.existsSync(newMcp)) return;
456
+ fs.mkdirSync(path.join(targetDir, ".context"), { recursive: true });
457
+ fs.renameSync(legacyMcp, newMcp);
458
+ console.log(
459
+ "[cortex] migrated legacy mcp/ → .context/mcp/ to keep project root clean. " +
460
+ "Re-run 'cortex connect' if Claude/Codex MCP registrations need to be refreshed.",
461
+ );
462
+ }
463
+
442
464
  function installScaffold(targetDir, force) {
465
+ migrateLegacyMcpLocation(targetDir);
466
+
443
467
  const copyMap = [
444
468
  [path.join(SCAFFOLD_ROOT, ".context"), path.join(targetDir, ".context")],
445
469
  [path.join(SCAFFOLD_ROOT, "scripts"), path.join(targetDir, "scripts")],
446
- [path.join(SCAFFOLD_ROOT, "mcp"), path.join(targetDir, "mcp")],
470
+ [path.join(SCAFFOLD_ROOT, "mcp"), path.join(targetDir, MCP_PROJECT_REL)],
447
471
  [path.join(SCAFFOLD_ROOT, ".githooks"), path.join(targetDir, ".githooks")]
448
472
  ];
449
473
 
@@ -633,7 +657,7 @@ async function connectClaude(targetDir) {
633
657
  }
634
658
 
635
659
  const serverName = "cortex";
636
- const projectServerEntry = path.join("mcp", "dist", "server.js");
660
+ const projectServerEntry = path.join(MCP_PROJECT_REL, "dist", "server.js");
637
661
  await runCommandResult("claude", ["mcp", "remove", "-s", "project", serverName], targetDir, "ignore");
638
662
  await runCommand(
639
663
  "claude",
@@ -646,7 +670,7 @@ async function connectClaude(targetDir) {
646
670
 
647
671
  async function connectMcpClients(targetDir, options = {}) {
648
672
  const { skipBuild = false } = options;
649
- const mcpDir = path.join(targetDir, "mcp");
673
+ const mcpDir = path.join(targetDir, MCP_PROJECT_REL);
650
674
  const packageJson = path.join(mcpDir, "package.json");
651
675
  const nodeModules = path.join(mcpDir, "node_modules");
652
676
  const serverEntry = path.join(mcpDir, "dist", "server.js");
@@ -662,7 +686,7 @@ async function connectMcpClients(targetDir, options = {}) {
662
686
  console.log(`[cortex] MCP build failed, continuing with existing dist output: ${toErrorMessage(error)}`);
663
687
  }
664
688
  } else if (!skipBuild) {
665
- console.log("[cortex] mcp/node_modules not found, skipping build (run cortex bootstrap first)");
689
+ console.log("[cortex] .context/mcp/node_modules not found, skipping build (run cortex bootstrap first)");
666
690
  }
667
691
 
668
692
  if (!fs.existsSync(serverEntry)) {
@@ -716,7 +740,7 @@ async function maybeInstallGitHooks(targetDir) {
716
740
  }
717
741
 
718
742
  function ensureProjectInitialized(targetDir) {
719
- const mcpPackageJson = path.join(targetDir, "mcp", "package.json");
743
+ const mcpPackageJson = path.join(targetDir, MCP_PROJECT_REL, "package.json");
720
744
  if (!fs.existsSync(mcpPackageJson)) {
721
745
  throw new Error(`Missing ${mcpPackageJson}. Run 'cortex init --bootstrap' first.`);
722
746
  }
@@ -731,7 +755,9 @@ function isTruthyEnv(value) {
731
755
  }
732
756
 
733
757
  function canAutoInitialize(targetDir) {
734
- const scaffoldPaths = [".context", "scripts", "mcp", ".githooks"].map((entry) => path.join(targetDir, entry));
758
+ // Legacy mcp/ at root no longer counted — pre-v2.0.5 projects are migrated
759
+ // by installScaffold rather than blocking auto-init.
760
+ const scaffoldPaths = [".context", "scripts", ".githooks"].map((entry) => path.join(targetDir, entry));
735
761
  return scaffoldPaths.every((entryPath) => !fs.existsSync(entryPath));
736
762
  }
737
763
 
@@ -744,7 +770,12 @@ function isScaffoldOutOfDate(targetDir) {
744
770
  if (!fs.existsSync(doctorScript)) {
745
771
  return true;
746
772
  }
747
- const mcpPackage = path.join(targetDir, "mcp", "package.json");
773
+ // Treat legacy mcp/ at project root as out-of-date so existing installs
774
+ // get migrated into .context/mcp/ on the next bootstrap.
775
+ if (fs.existsSync(path.join(targetDir, "mcp", "package.json"))) {
776
+ return true;
777
+ }
778
+ const mcpPackage = path.join(targetDir, MCP_PROJECT_REL, "package.json");
748
779
  if (!fs.existsSync(mcpPackage)) {
749
780
  return true;
750
781
  }
@@ -780,7 +811,8 @@ async function maybeMigrateScaffold(targetDir, command) {
780
811
 
781
812
  console.error(
782
813
  `[cortex] scaffold in ${targetDir} is out of date ` +
783
- `(missing scripts/doctor.sh, mcp/package.json, or doctor subcommand in context.sh).`
814
+ `(missing scripts/doctor.sh, .context/mcp/package.json, doctor subcommand in context.sh, ` +
815
+ `or carries a legacy mcp/ directory at the project root).`
784
816
  );
785
817
 
786
818
  let proceed = autoYes;
@@ -808,8 +840,8 @@ async function maybeMigrateScaffold(targetDir, command) {
808
840
  }
809
841
 
810
842
  async function ensureProjectInitializedForMcp(targetDir) {
811
- const mcpPackageJson = path.join(targetDir, "mcp", "package.json");
812
- const serverEntry = path.join(targetDir, "mcp", "dist", "server.js");
843
+ const mcpPackageJson = path.join(targetDir, MCP_PROJECT_REL, "package.json");
844
+ const serverEntry = path.join(targetDir, MCP_PROJECT_REL, "dist", "server.js");
813
845
 
814
846
  if (fs.existsSync(mcpPackageJson) && fs.existsSync(serverEntry)) {
815
847
  return;
@@ -947,7 +979,7 @@ async function run() {
947
979
  process.env.CORTEX_PROJECT_ROOT = target;
948
980
  await ensureProjectInitializedForMcp(target);
949
981
  ensureProjectInitialized(target);
950
- const serverEntry = path.join(target, "mcp", "dist", "server.js");
982
+ const serverEntry = path.join(target, MCP_PROJECT_REL, "dist", "server.js");
951
983
  if (!fs.existsSync(serverEntry)) {
952
984
  throw new Error(`Missing ${serverEntry}. Run 'cortex bootstrap' in ${target} first.`);
953
985
  }
@@ -980,6 +1012,10 @@ async function run() {
980
1012
  return runRunCommand(rest);
981
1013
  }
982
1014
 
1015
+ if (command === "stage") {
1016
+ return runStageCommandShim(rest);
1017
+ }
1018
+
983
1019
  const passthrough = new Set([
984
1020
  "bootstrap",
985
1021
  "update",
@@ -1038,12 +1074,12 @@ function isPidAlive(pid) {
1038
1074
  }
1039
1075
 
1040
1076
  function resolveProjectMcpDist() {
1041
- // v2.0.0: daemon/hooks/cli are built into the project's mcp/dist/
1042
- // (via 'cortex bootstrap'). PACKAGE_ROOT/scaffold/mcp/ is the source
1043
- // tree the scaffold is copied from. The actual built code lives in
1044
- // each project's <cwd>/mcp/dist/ after bootstrap.
1077
+ // v2.0.5: project layout was moved from <cwd>/mcp/ to <cwd>/.context/mcp/.
1078
+ // PACKAGE_ROOT/scaffold/mcp/ is still the source tree the scaffold is
1079
+ // copied from; the actual built code lives in each project's
1080
+ // <cwd>/.context/mcp/dist/ after bootstrap.
1045
1081
  const target = process.env.CORTEX_PROJECT_ROOT?.trim() || process.cwd();
1046
- return path.join(target, "mcp", "dist");
1082
+ return path.join(target, MCP_PROJECT_REL, "dist");
1047
1083
  }
1048
1084
 
1049
1085
  function resolveDaemonEntry() {
@@ -1502,6 +1538,19 @@ async function runRunCommand(args) {
1502
1538
  process.exit(exitCode);
1503
1539
  }
1504
1540
 
1541
+ async function runStageCommandShim(args) {
1542
+ const target = process.env.CORTEX_PROJECT_ROOT?.trim() || process.cwd();
1543
+ process.env.CORTEX_PROJECT_ROOT = path.resolve(target);
1544
+ const entry = resolveCliEntry("stage");
1545
+ if (!fs.existsSync(entry)) {
1546
+ throw new Error(
1547
+ `Build the project's MCP first (missing ${entry}). Run 'cortex bootstrap' in the project root.`,
1548
+ );
1549
+ }
1550
+ const mod = await import(pathToFileURL(entry).href);
1551
+ await mod.runStageCommand(args);
1552
+ }
1553
+
1505
1554
  async function runTelemetryCommand(args) {
1506
1555
  const sub = args[0] || "help";
1507
1556
  if (sub === "test") {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@danielblomma/cortex-mcp",
3
3
  "mcpName": "io.github.DanielBlomma/cortex",
4
- "version": "2.0.4",
4
+ "version": "2.0.6",
5
5
  "description": "Local, repo-scoped context platform for coding assistants. Semantic search, graph relationships, and architectural rule context.",
6
6
  "type": "module",
7
7
  "author": "Daniel Blomma",
@@ -10,6 +10,9 @@
10
10
  "dependencies": {
11
11
  "@huggingface/transformers": "^4.1.0",
12
12
  "@modelcontextprotocol/sdk": "^1.27.1",
13
+ "@types/js-yaml": "^4.0.9",
14
+ "js-yaml": "^4.1.1",
15
+ "minimatch": "^10.2.5",
13
16
  "ryugraph": "^25.9.1",
14
17
  "zod": "^3.24.1"
15
18
  },
@@ -842,12 +845,17 @@
842
845
  "dev": true,
843
846
  "license": "MIT"
844
847
  },
848
+ "node_modules/@types/js-yaml": {
849
+ "version": "4.0.9",
850
+ "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz",
851
+ "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==",
852
+ "license": "MIT"
853
+ },
845
854
  "node_modules/@types/node": {
846
855
  "version": "22.19.13",
847
856
  "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.13.tgz",
848
857
  "integrity": "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw==",
849
858
  "license": "MIT",
850
- "peer": true,
851
859
  "dependencies": {
852
860
  "undici-types": "~6.21.0"
853
861
  }
@@ -989,6 +997,21 @@
989
997
  "dev": true,
990
998
  "license": "MIT"
991
999
  },
1000
+ "node_modules/argparse": {
1001
+ "version": "2.0.1",
1002
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
1003
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
1004
+ "license": "Python-2.0"
1005
+ },
1006
+ "node_modules/balanced-match": {
1007
+ "version": "4.0.4",
1008
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
1009
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
1010
+ "license": "MIT",
1011
+ "engines": {
1012
+ "node": "18 || 20 || >=22"
1013
+ }
1014
+ },
992
1015
  "node_modules/body-parser": {
993
1016
  "version": "2.2.2",
994
1017
  "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
@@ -1020,6 +1043,18 @@
1020
1043
  "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
1021
1044
  "license": "MIT"
1022
1045
  },
1046
+ "node_modules/brace-expansion": {
1047
+ "version": "5.0.5",
1048
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
1049
+ "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
1050
+ "license": "MIT",
1051
+ "dependencies": {
1052
+ "balanced-match": "^4.0.2"
1053
+ },
1054
+ "engines": {
1055
+ "node": "18 || 20 || >=22"
1056
+ }
1057
+ },
1023
1058
  "node_modules/bytes": {
1024
1059
  "version": "3.1.2",
1025
1060
  "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -1760,7 +1795,6 @@
1760
1795
  "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.14.tgz",
1761
1796
  "integrity": "sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==",
1762
1797
  "license": "MIT",
1763
- "peer": true,
1764
1798
  "engines": {
1765
1799
  "node": ">=16.9.0"
1766
1800
  }
@@ -1861,6 +1895,18 @@
1861
1895
  "url": "https://github.com/sponsors/panva"
1862
1896
  }
1863
1897
  },
1898
+ "node_modules/js-yaml": {
1899
+ "version": "4.1.1",
1900
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
1901
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
1902
+ "license": "MIT",
1903
+ "dependencies": {
1904
+ "argparse": "^2.0.1"
1905
+ },
1906
+ "bin": {
1907
+ "js-yaml": "bin/js-yaml.js"
1908
+ }
1909
+ },
1864
1910
  "node_modules/json-schema-traverse": {
1865
1911
  "version": "1.0.0",
1866
1912
  "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
@@ -1940,6 +1986,21 @@
1940
1986
  "url": "https://github.com/sponsors/sindresorhus"
1941
1987
  }
1942
1988
  },
1989
+ "node_modules/minimatch": {
1990
+ "version": "10.2.5",
1991
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
1992
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
1993
+ "license": "BlueOak-1.0.0",
1994
+ "dependencies": {
1995
+ "brace-expansion": "^5.0.5"
1996
+ },
1997
+ "engines": {
1998
+ "node": "18 || 20 || >=22"
1999
+ },
2000
+ "funding": {
2001
+ "url": "https://github.com/sponsors/isaacs"
2002
+ }
2003
+ },
1943
2004
  "node_modules/minimist": {
1944
2005
  "version": "1.2.8",
1945
2006
  "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
@@ -2611,7 +2672,6 @@
2611
2672
  "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
2612
2673
  "dev": true,
2613
2674
  "license": "Apache-2.0",
2614
- "peer": true,
2615
2675
  "bin": {
2616
2676
  "tsc": "bin/tsc",
2617
2677
  "tsserver": "bin/tsserver"
@@ -2764,7 +2824,6 @@
2764
2824
  "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
2765
2825
  "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
2766
2826
  "license": "MIT",
2767
- "peer": true,
2768
2827
  "funding": {
2769
2828
  "url": "https://github.com/sponsors/colinhacks"
2770
2829
  }
@@ -12,8 +12,11 @@
12
12
  "test": "npm run build --silent && node --test tests/*.test.mjs"
13
13
  },
14
14
  "dependencies": {
15
- "@modelcontextprotocol/sdk": "^1.27.1",
16
15
  "@huggingface/transformers": "^4.1.0",
16
+ "@modelcontextprotocol/sdk": "^1.27.1",
17
+ "@types/js-yaml": "^4.0.9",
18
+ "js-yaml": "^4.1.1",
19
+ "minimatch": "^10.2.5",
17
20
  "ryugraph": "^25.9.1",
18
21
  "zod": "^3.24.1"
19
22
  },