openkrak-mcp 1.0.11 → 1.0.12

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/README.md +55 -26
  2. package/dist/index.js +37 -14
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  MCP server for developer tooling. Performs static analysis on a software repository via the Dorchester engine and delivers a structured context brief to the language model before any file is accessed.
4
4
 
5
- **Current integration:** OpenCode. Claude Code, Codex, and Cursor support in development.
5
+ **Supported:** OpenCode (TUI + Desktop). Claude Code, Codex, and Cursor support in development.
6
6
 
7
7
  ---
8
8
 
@@ -46,9 +46,21 @@ Requires Node.js ≥ 18.
46
46
 
47
47
  ---
48
48
 
49
- ## Setup — OpenCode
49
+ ## Setup
50
50
 
51
- **Step 1.** Open `~/.config/opencode/opencode.jsonc` and add the `mcp` block:
51
+ OpenKrak works with both **OpenCode TUI** and **OpenCode Desktop**. The config file and setup steps are identical for both.
52
+
53
+ ### Config file location
54
+
55
+ | Platform | Path |
56
+ |----------|------|
57
+ | Windows | `C:\Users\<username>\.config\opencode\opencode.jsonc` |
58
+ | macOS | `~/.config/opencode/opencode.jsonc` |
59
+ | Linux | `~/.config/opencode/opencode.jsonc` |
60
+
61
+ ### Step 1 — Add OpenKrak to your config
62
+
63
+ Open the config file and add the `mcp` block:
52
64
 
53
65
  ```jsonc
54
66
  {
@@ -63,45 +75,62 @@ Requires Node.js ≥ 18.
63
75
  }
64
76
  ```
65
77
 
66
- > Windows: `C:\Users\<username>\.config\opencode\opencode.jsonc`
67
- > macOS / Linux: `~/.config/opencode/opencode.jsonc`
78
+ ### Step 2 — Restart OpenCode
68
79
 
69
- **Step 2.** Restart OpenCode. Confirm **openkrak Connected** appears in the MCP panel.
80
+ Close and reopen OpenCode (TUI or Desktop). Confirm **openkrak Connected** appears in the MCP panel.
70
81
 
71
- **Step 3.** Open any repository and run a coding task. OpenKrak runs automatically before the language model accesses any file.
82
+ > **OpenCode Desktop:** MCP status is shown in the bottom status bar. Green dot = connected.
83
+ > **OpenCode TUI:** MCP status is shown in the top-right panel.
84
+
85
+ ### Step 3 — Run your first analysis
86
+
87
+ Open any repository in OpenCode and send a message:
72
88
 
73
- To invoke explicitly:
74
89
  ```
75
- Use analyze_repo on /path/to/your/repo with objective "refactor the auth module"
90
+ analyze_repo on /absolute/path/to/your/repo
76
91
  ```
77
92
 
93
+ Or just start a coding task normally — OpenKrak runs automatically before the model reads any file.
94
+
78
95
  ---
79
96
 
80
- ## Enabling and Disabling
97
+ ## Tools
81
98
 
82
- Set `"enabled"` in your config and restart OpenCode:
99
+ | Tool | When to use |
100
+ |------|-------------|
101
+ | `analyze_repo` | Full pipeline. Call before any coding task on a new repo. Returns dependency graph, hotspot rankings, blast radius, and threat matrix. |
102
+ | `get_mahadata` | Compact repo brief — structure, entry points, constraints, risk score. Use when you need repo-wide context without a full re-analysis. |
103
+ | `get_hotspots` | Ranked list of high-risk files by complexity, coupling, and change frequency. Use before reviewing or refactoring. |
104
+ | `blast_radius` | Impact map for a specific file. Which files, modules, and APIs are affected by a change. Use before modifying a critical file. |
105
+
106
+ ### Example prompts
83
107
 
84
- ```jsonc
85
- "enabled": true // on
86
- "enabled": false // off
108
+ ```
109
+ analyze_repo on /path/to/repo with objective "refactor the auth module"
110
+ ```
111
+ ```
112
+ Run get_hotspots on /path/to/repo — which files should I avoid touching?
113
+ ```
114
+ ```
115
+ blast_radius on /path/to/repo for file src/api/routes/user.ts
87
116
  ```
88
117
 
89
118
  ---
90
119
 
91
- ## Tools
120
+ ## Enable / Disable
92
121
 
93
- | Tool | Description |
94
- |------|-------------|
95
- | `analyze_repo` | Full Dorchester pipeline. Returns dependency graph, hotspot rankings, blast radius, and threat matrix. Call before any coding task. |
96
- | `get_mahadata` | Compact repository intelligence brief. Structure, entry points, constraints, risk score. |
97
- | `get_hotspots` | Ranked list of high-risk files by complexity, coupling, and change frequency. |
98
- | `blast_radius` | Impact map for a specific file change. Which files, modules, and APIs are affected. |
122
+ Set `"enabled"` in your config and restart OpenCode:
123
+
124
+ ```jsonc
125
+ "enabled": true // on
126
+ "enabled": false // off
127
+ ```
99
128
 
100
129
  ---
101
130
 
102
- ## License Tiers
131
+ ## Pro License
103
132
 
104
- Free tier is active by default — no account or configuration required.
133
+ Free tier is active by default — no account required.
105
134
 
106
135
  | Plan | Price | Queries |
107
136
  |------|-------|---------|
@@ -109,7 +138,7 @@ Free tier is active by default — no account or configuration required.
109
138
  | Pro Monthly | $8 / month | Unlimited |
110
139
  | Pro Annual | $67.20 / year | Unlimited |
111
140
 
112
- To activate a Pro license, add your key to the MCP config:
141
+ To activate Pro, add your key to the config:
113
142
 
114
143
  ```jsonc
115
144
  {
@@ -127,7 +156,7 @@ To activate a Pro license, add your key to the MCP config:
127
156
  }
128
157
  ```
129
158
 
130
- License keys are available at [openkrak-web.vercel.app](https://openkrak-web.vercel.app). Delivered instantly via email after purchase. No subscription, no auto-renewal.
159
+ License keys: [openkrak-web.vercel.app](https://openkrak-web.vercel.app). Delivered via email after purchase. No subscription, no auto-renewal.
131
160
 
132
161
  ---
133
162
 
@@ -135,7 +164,7 @@ License keys are available at [openkrak-web.vercel.app](https://openkrak-web.ver
135
164
 
136
165
  - Static analysis only. No AI inference in the pipeline.
137
166
  - Anonymous usage telemetry is collected (query count, tool name, error events). No source code or file contents are transmitted.
138
- - License validation requires a network call to verify your key against the license server.
167
+ - License validation requires a network call to the license server on each tool invocation.
139
168
 
140
169
  ---
141
170
 
package/dist/index.js CHANGED
@@ -241794,7 +241794,7 @@ function inferLanguage(filePath) {
241794
241794
  if (filePath.endsWith(".js") || filePath.endsWith(".jsx")) return "javascript";
241795
241795
  return "unknown";
241796
241796
  }
241797
- function extractRawEdges(filePath, ast, fileNodeId) {
241797
+ function extractRawEdges(filePath, ast, fileNodeId, tsconfigPaths2) {
241798
241798
  const edges = [];
241799
241799
  const symbolRanges = [];
241800
241800
  (0, import_typescript_estree3.simpleTraverse)(ast, {
@@ -241845,8 +241845,7 @@ function extractRawEdges(filePath, ast, fileNodeId) {
241845
241845
  if (node.type === "ImportDeclaration") {
241846
241846
  const importPath = node.source.value;
241847
241847
  const line = node.loc?.start.line ?? null;
241848
- const isBarrel = isBarrelPath(importPath);
241849
- const resolvedTarget = resolveImportTarget(filePath, importPath);
241848
+ const resolvedTarget = resolveImportTarget(filePath, importPath, tsconfigPaths2);
241850
241849
  edges.push({
241851
241850
  from: importFromNodeId,
241852
241851
  to: resolvedTarget,
@@ -241875,7 +241874,7 @@ function extractRawEdges(filePath, ast, fileNodeId) {
241875
241874
  const sourceLiteral = node.source.type === "Literal" ? node.source.value : "<dynamic>";
241876
241875
  edges.push({
241877
241876
  from: fileNodeId,
241878
- to: resolveImportTarget(filePath, sourceLiteral),
241877
+ to: resolveImportTarget(filePath, sourceLiteral, tsconfigPaths2),
241879
241878
  kind: "dynamic_import",
241880
241879
  file: filePath,
241881
241880
  line,
@@ -241889,7 +241888,6 @@ function extractRawEdges(filePath, ast, fileNodeId) {
241889
241888
  edges.push({
241890
241889
  from: fileNodeId,
241891
241890
  to: superName,
241892
- // resolved to node_id in assembly
241893
241891
  kind: "extend",
241894
241892
  file: filePath,
241895
241893
  line: node.loc.start.line,
@@ -241954,7 +241952,7 @@ function extractRawEdges(filePath, ast, fileNodeId) {
241954
241952
  });
241955
241953
  return edges;
241956
241954
  }
241957
- function extractBarrelReExports(filePath, ast) {
241955
+ function extractBarrelReExports(filePath, ast, tsconfigPaths2) {
241958
241956
  const reExports = [];
241959
241957
  (0, import_typescript_estree3.simpleTraverse)(ast, {
241960
241958
  enter(node) {
@@ -241962,7 +241960,7 @@ function extractBarrelReExports(filePath, ast) {
241962
241960
  if (!node.source) return;
241963
241961
  const sourcePath = node.source.value;
241964
241962
  if (!sourcePath.startsWith(".")) return;
241965
- const resolvedSource = resolveImportTarget(filePath, sourcePath);
241963
+ const resolvedSource = resolveImportTarget(filePath, sourcePath, tsconfigPaths2);
241966
241964
  if (node.type === "ExportAllDeclaration") {
241967
241965
  reExports.push({
241968
241966
  barrelFile: filePath,
@@ -241985,7 +241983,7 @@ function extractBarrelReExports(filePath, ast) {
241985
241983
  });
241986
241984
  return reExports;
241987
241985
  }
241988
- function resolveImportTarget(fromFile, importPath) {
241986
+ function resolveImportTarget(fromFile, importPath, tsconfigPaths2) {
241989
241987
  if (importPath.startsWith(".")) {
241990
241988
  const dir = import_path3.default.dirname(fromFile);
241991
241989
  const resolved = import_path3.default.join(dir, importPath).replace(/\\/g, "/");
@@ -241995,11 +241993,29 @@ function resolveImportTarget(fromFile, importPath) {
241995
241993
  }
241996
241994
  return normalized;
241997
241995
  }
241996
+ if (tsconfigPaths2) {
241997
+ for (const [prefix, target] of Object.entries(tsconfigPaths2)) {
241998
+ if (importPath.startsWith(prefix)) {
241999
+ const rest = importPath.slice(prefix.length);
242000
+ const resolved = (target + rest).replace(/\\/g, "/");
242001
+ const normalized = resolved.replace(/\.js$/, ".ts");
242002
+ if (!import_path3.default.extname(normalized)) {
242003
+ return normalized + ".ts";
242004
+ }
242005
+ return normalized;
242006
+ }
242007
+ }
242008
+ }
242009
+ if (importPath.startsWith("@/")) {
242010
+ const stripped = importPath.slice(2);
242011
+ const normalized = stripped.replace(/\.js$/, ".ts");
242012
+ if (!import_path3.default.extname(normalized)) {
242013
+ return normalized + ".ts";
242014
+ }
242015
+ return normalized;
242016
+ }
241998
242017
  return importPath;
241999
242018
  }
242000
- function isBarrelPath(importPath) {
242001
- return importPath.endsWith("/index") || importPath.endsWith("/index.ts") || importPath.endsWith("/index.js") || importPath === "index";
242002
- }
242003
242019
  function assembleGraph(allNodes, rawEdges, barrelReExports = []) {
242004
242020
  for (const node of allNodes) {
242005
242021
  node.id = node.id.replace(/\\/g, "/");
@@ -242511,7 +242527,14 @@ function inferModule(filePath) {
242511
242527
  return parts.length >= 2 ? parts[0] : null;
242512
242528
  }
242513
242529
  function isEntryPoint(filePath) {
242514
- return /\/(index|main|app|server|cli)\.(ts|js)x?$/.test(filePath);
242530
+ const normalized = filePath.replace(/\\/g, "/");
242531
+ if (/\/(index|main|server|cli)\.(ts|js)x?$/.test(normalized)) return true;
242532
+ if (/^app\/.*page\.(ts|js)x?$/.test(normalized)) return true;
242533
+ if (/^app\/layout\.(ts|js)x?$/.test(normalized)) return true;
242534
+ if (/^app\/.*route\.(ts|js)x?$/.test(normalized)) return true;
242535
+ if (/^pages\//.test(normalized) && /\.(ts|js)x?$/.test(normalized)) return true;
242536
+ if (/^src\/(main|index|App)\.(ts|js)x?$/.test(normalized)) return true;
242537
+ return false;
242515
242538
  }
242516
242539
  function walkAst(node, onEnter, onLeave) {
242517
242540
  if (!node || typeof node !== "object" || !("type" in node)) return;
@@ -242622,9 +242645,9 @@ async function runDeepStrike(store, opts) {
242622
242645
  for (const s of symbols) s.content_hash = currentHash;
242623
242646
  allNodes.push(...symbols);
242624
242647
  const fileNodeId = symbols.find((n) => n.kind === "file")?.id ?? `${relPath}::file::0`;
242625
- const rawEdges = extractRawEdges(relPath, ast, fileNodeId);
242648
+ const rawEdges = extractRawEdges(relPath, ast, fileNodeId, tsconfigPaths);
242626
242649
  allRawEdges.push(...rawEdges);
242627
- const barrelReExports = extractBarrelReExports(relPath, ast);
242650
+ const barrelReExports = extractBarrelReExports(relPath, ast, tsconfigPaths);
242628
242651
  allBarrelReExports.push(...barrelReExports);
242629
242652
  const secFindings = detectSecurityPatterns(relPath, content);
242630
242653
  allFindings.push(...secFindings);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openkrak-mcp",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "description": "OpenKrak MCP Server - AI coding intelligence via Dorchester engine",
5
5
  "mcpName": "io.github.FrnzJulianBergmann/openkrak",
6
6
  "type": "commonjs",