openkrak-mcp 1.0.10 → 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.
package/README.md CHANGED
@@ -1,26 +1,14 @@
1
1
  # openkrak-mcp
2
2
 
3
- **AI coding intelligence for any coding agent — delivered as an MCP server.**
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
- OpenKrak pre-computes your repository's structure and delivers a structured intelligence brief (Mahadata) before your LLM runs. Less hallucination, lower token cost, faster answers.
6
-
7
- ---
8
-
9
- ## The Problem
10
-
11
- Every time you ask your coding agent to modify code, the LLM starts blind — reading raw files, burning tokens, guessing dependencies.
12
-
13
- **Without OpenKrak:** LLM reads 50,000+ tokens of raw files. Slow. Expensive. Blind.
14
- **With OpenKrak:** LLM reads a pre-computed Mahadata brief. Precise. Cheap. Aware.
15
-
16
- For simple tasks, OpenKrak replaces 50+ file reads with a single tool call.
17
- For complex refactors, it cuts token usage 20-30% and eliminates blind exploration — the LLM knows exactly which files matter before it reads a single line.
5
+ **Supported:** OpenCode (TUI + Desktop). Claude Code, Codex, and Cursor support in development.
18
6
 
19
7
  ---
20
8
 
21
9
  ## How It Works
22
10
 
23
- OpenKrak runs the **Dorchester engine** — a 6-step static analysis pipeline:
11
+ OpenKrak runs the **Dorchester engine** — a six-step static analysis pipeline — on your repository before the language model executes any task.
24
12
 
25
13
  ```
26
14
  Repository
@@ -41,21 +29,10 @@ Blast Radius — Ripple effects of any change mapped before commit
41
29
  Execution Gate — Analysis validated and normalized
42
30
  │
43
31
  ▼
44
- Mahadata — Structured intelligence brief delivered to your coding agent
32
+ Mahadata — Structured brief delivered to the language model
45
33
  ```
46
34
 
47
- Your codebase never leaves your machine. All analysis runs locally.
48
-
49
- ---
50
-
51
- ## Supported Agents
52
-
53
- | Agent | Status |
54
- |-------|--------|
55
- | **OpenCode** | ✅ Supported |
56
- | Claude Code | 🔜 Coming soon |
57
- | Codex | 🔜 Coming soon |
58
- | Cursor | 🔜 Coming soon |
35
+ All analysis runs locally. Your codebase does not leave your machine.
59
36
 
60
37
  ---
61
38
 
@@ -65,13 +42,25 @@ Your codebase never leaves your machine. All analysis runs locally.
65
42
  npm install -g openkrak-mcp
66
43
  ```
67
44
 
45
+ Requires Node.js ≥ 18.
46
+
68
47
  ---
69
48
 
70
- ## Setup — OpenCode
49
+ ## Setup
50
+
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` |
71
60
 
72
- ### Step 1 — Edit config
61
+ ### Step 1 — Add OpenKrak to your config
73
62
 
74
- Open `~/.config/opencode/opencode.jsonc` and add the `mcp` block:
63
+ Open the config file and add the `mcp` block:
75
64
 
76
65
  ```jsonc
77
66
  {
@@ -80,91 +69,76 @@ Open `~/.config/opencode/opencode.jsonc` and add the `mcp` block:
80
69
  "openkrak": {
81
70
  "type": "local",
82
71
  "enabled": true,
83
- "command": ["openkrak-mcp"]
72
+ "command": ["npx", "openkrak-mcp"]
84
73
  }
85
74
  }
86
75
  }
87
76
  ```
88
77
 
89
- > **Windows path:** `C:\Users\<username>\.config\opencode\opencode.jsonc`
90
- > **Mac/Linux path:** `~/.config/opencode/opencode.jsonc`
91
-
92
78
  ### Step 2 — Restart OpenCode
93
79
 
94
- Close and reopen OpenCode. You should see **openkrak Connected** in the top-right MCP panel.
80
+ Close and reopen OpenCode (TUI or Desktop). Confirm **openkrak Connected** appears in the MCP panel.
95
81
 
96
- ### Step 3 — Use it
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.
97
84
 
98
- Just open a repo and ask your agent anything. OpenKrak automatically runs before the LLM touches your files.
85
+ ### Step 3 — Run your first analysis
99
86
 
100
- Or call it explicitly:
87
+ Open any repository in OpenCode and send a message:
101
88
 
102
89
  ```
103
- Use analyze_repo on /path/to/your/repo with objective "refactor the auth module"
90
+ analyze_repo on /absolute/path/to/your/repo
104
91
  ```
105
92
 
93
+ Or just start a coding task normally — OpenKrak runs automatically before the model reads any file.
94
+
106
95
  ---
107
96
 
108
- ## Turning OpenKrak On / Off
97
+ ## Tools
109
98
 
110
- Change `"enabled"` in your config:
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. |
111
105
 
112
- ```jsonc
113
- // ON
114
- "enabled": true
106
+ ### Example prompts
115
107
 
116
- // OFF
117
- "enabled": false
118
108
  ```
119
-
120
- Then restart OpenCode. That's it.
121
-
122
- **Quick toggle scripts (optional):**
123
-
124
- Save these two files anywhere on your machine.
125
-
126
- `mcp-on.ps1` (Windows PowerShell):
127
- ```powershell
128
- $config = Get-Content "$env:USERPROFILE\.config\opencode\opencode.jsonc" | ConvertFrom-Json -AsHashtable
129
- $config.mcp.openkrak.enabled = $true
130
- $config | ConvertTo-Json -Depth 10 | Set-Content "$env:USERPROFILE\.config\opencode\opencode.jsonc"
131
- Write-Host "OpenKrak: ON"
109
+ analyze_repo on /path/to/repo with objective "refactor the auth module"
132
110
  ```
133
-
134
- `mcp-off.ps1` (Windows PowerShell):
135
- ```powershell
136
- $config = Get-Content "$env:USERPROFILE\.config\opencode\opencode.jsonc" | ConvertFrom-Json -AsHashtable
137
- $config.mcp.openkrak.enabled = $false
138
- $config | ConvertTo-Json -Depth 10 | Set-Content "$env:USERPROFILE\.config\opencode\opencode.jsonc"
139
- Write-Host "OpenKrak: OFF"
140
111
  ```
141
-
142
- Run with:
143
- ```powershell
144
- powershell -File mcp-on.ps1
145
- powershell -File mcp-off.ps1
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
146
116
  ```
147
117
 
148
118
  ---
149
119
 
150
- ## Tools
120
+ ## Enable / Disable
151
121
 
152
- Once connected, your coding agent has access to 4 tools:
122
+ Set `"enabled"` in your config and restart OpenCode:
153
123
 
154
- | Tool | When to use |
155
- |------|-------------|
156
- | `analyze_repo` | Before any coding task — runs full Dorchester pipeline, returns dependency graph, hotspots, blast radius, threat matrix |
157
- | `get_mahadata` | Quick 500-token intelligence brief — repo structure, entry points, constraints, risk score |
158
- | `get_hotspots` | Which files are most dangerous to touch — ranked by complexity, coupling, change frequency |
159
- | `blast_radius` | Ripple effect of modifying a specific file — which files, modules, APIs will be affected |
124
+ ```jsonc
125
+ "enabled": true // on
126
+ "enabled": false // off
127
+ ```
160
128
 
161
129
  ---
162
130
 
163
- ## Pro License (optional)
131
+ ## Pro License
164
132
 
165
- Free tier gives you **15 calls per 24 hours** — no account needed.
133
+ Free tier is active by default — no account required.
166
134
 
167
- For unlimited calls, get a Pro key at **[openkrak.dev](https://openkrak.dev)**:
135
+ | Plan | Price | Queries |
136
+ |------|-------|---------|
137
+ | Free | $0 | 15 per 24-hour rolling window |
138
+ | Pro Monthly | $8 / month | Unlimited |
139
+ | Pro Annual | $67.20 / year | Unlimited |
140
+
141
+ To activate Pro, add your key to the config:
168
142
 
169
143
  ```jsonc
170
144
  {
@@ -173,7 +147,7 @@ For unlimited calls, get a Pro key at **[openkrak.dev](https://openkrak.dev)**:
173
147
  "openkrak": {
174
148
  "type": "local",
175
149
  "enabled": true,
176
- "command": ["openkrak-mcp"],
150
+ "command": ["npx", "openkrak-mcp"],
177
151
  "env": {
178
152
  "OPENKRAK_KEY": "your-license-key"
179
153
  }
@@ -182,32 +156,22 @@ For unlimited calls, get a Pro key at **[openkrak.dev](https://openkrak.dev)**:
182
156
  }
183
157
  ```
184
158
 
185
- | Plan | Price | Limit |
186
- |------|-------|-------|
187
- | Free | $0 | 15 calls / 24h rolling |
188
- | Pro Monthly | $8/month | Unlimited |
189
- | Pro Annual | $67.20/year | Unlimited |
159
+ License keys: [openkrak-web.vercel.app](https://openkrak-web.vercel.app). Delivered via email after purchase. No subscription, no auto-renewal.
190
160
 
191
161
  ---
192
162
 
193
- ## Privacy
163
+ ## Notes
194
164
 
195
- - Your codebase **never leaves your machine**
196
- - Analysis runs 100% locally via the Dorchester engine
197
- - Only license validation calls hit the network (to verify your key)
198
- - No telemetry, no file uploads
165
+ - Static analysis only. No AI inference in the pipeline.
166
+ - Anonymous usage telemetry is collected (query count, tool name, error events). No source code or file contents are transmitted.
167
+ - License validation requires a network call to the license server on each tool invocation.
199
168
 
200
169
  ---
201
170
 
202
- ## Tech
171
+ ## Repository
203
172
 
204
- - **Protocol:** MCP (Model Context Protocol) — open standard by Anthropic
205
- - **Analysis:** Static, deterministic — not AI/probabilistic
206
- - **Runtime:** Node.js ≥ 18
207
- - **License:** MIT
173
+ [github.com/FrnzJulianBergmann/openkrak](https://github.com/FrnzJulianBergmann/openkrak)
208
174
 
209
175
  ---
210
176
 
211
- ## License
212
-
213
- MIT — © 2026 Faiz Hamizan
177
+ MIT License — © 2026 Faiz Hamizan / Challanger Absolute Advance
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,7 +1,8 @@
1
1
  {
2
2
  "name": "openkrak-mcp",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "OpenKrak MCP Server - AI coding intelligence via Dorchester engine",
5
+ "mcpName": "io.github.FrnzJulianBergmann/openkrak",
5
6
  "type": "commonjs",
6
7
  "bin": {
7
8
  "openkrak-mcp": "dist/index.js"
@@ -9,7 +10,8 @@
9
10
  "main": "./dist/index.js",
10
11
  "files": [
11
12
  "dist",
12
- "README.md"
13
+ "README.md",
14
+ "server.json"
13
15
  ],
14
16
  "scripts": {
15
17
  "build": "tsup",
package/server.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.FrnzJulianBergmann/openkrak",
4
+ "title": "OpenKrak",
5
+ "description": "MCP server that performs static analysis on a repository via the Dorchester engine — dependency graph construction, complexity scoring, blast radius mapping — and delivers a structured context brief to the language model before any file is read.",
6
+ "version": "1.0.10",
7
+ "repository": {
8
+ "url": "https://github.com/FrnzJulianBergmann/openkrak",
9
+ "source": "github"
10
+ },
11
+ "websiteUrl": "https://openkrak-web.vercel.app",
12
+ "packages": [
13
+ {
14
+ "registryType": "npm",
15
+ "registryBaseUrl": "https://registry.npmjs.org",
16
+ "identifier": "openkrak-mcp",
17
+ "version": "1.0.10",
18
+ "transport": {
19
+ "type": "stdio"
20
+ }
21
+ }
22
+ ]
23
+ }