dexe-mcp 0.1.1 → 0.1.3

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/.mcp.example.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
+ "_comment": "Mac/Linux: use `dexe-mcp` directly. Windows: replace with { command: 'cmd', args: ['/c', 'dexe-mcp'] }. See README.md for the full install matrix.",
2
3
  "mcpServers": {
3
4
  "dexe": {
4
- "command": "npx",
5
- "args": ["-y", "dexe-mcp"]
5
+ "command": "dexe-mcp"
6
6
  }
7
7
  }
8
8
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.3
4
+
5
+ ### Docs
6
+ - **Windows install section rewritten** to lead with the absolute-path recipe (`node <abs path to dist/index.js>`) instead of `cmd /c dexe-mcp`. End-to-end testing against Claude Code on Windows showed the `cmd /c` wrapper, while standalone functional, did not reliably complete the MCP handshake when spawned by Claude Code — the absolute-path recipe has zero shim resolution and is known-working.
7
+ - **New prereq step**: verify `npm --version` actually runs in your shell *before* attempting `npm install -g dexe-mcp`. Users with a stripped `node.exe`-only install (common on Windows) will hit a silent `npm i -g` no-op otherwise, with no visible error.
8
+ - Added a "Verify the install" section showing how to smoke-test `dexe-mcp` over stdio without involving Claude Code, so users can distinguish "MCP server broken" from "client registration broken".
9
+
10
+ No code changes — 0.1.3 is a docs-only patch on top of 0.1.2's behavior.
11
+
12
+ ## 0.1.2
13
+
14
+ ### Fixed
15
+ - **Server no longer hangs / fails on first launch.** The heavy `git clone` + `npm install` bootstrap is now lazy — it runs only when a build tool (`dexe_compile`, `dexe_test`, `dexe_coverage`, `dexe_lint`) is first invoked, not inside MCP `initialize()`. Previously the MCP handshake would block for minutes or time out, and crash outright on hosts where `npm` / `git` were not on the spawned process's PATH.
16
+ - **PATH-independent spawning of `npm` and `hardhat`.** The runner now invokes `node <npm-cli.js>` and `node <protocol>/node_modules/hardhat/internal/cli/cli.js` directly via `process.execPath`, so it works on Windows installs where `npm.cmd` / `npx.cmd` aren't on the MCP client's spawn PATH (common with nvm-windows and with stripped `node.exe`-only installs).
17
+ - **Actionable error messages** when `git` is not installed, when `DEXE_PROTOCOL_PATH` points at a non-Hardhat directory, or when the user-managed checkout is missing `node_modules`.
18
+ - Concurrent build-tool calls now coalesce into a single bootstrap instead of racing `git clone` / `npm install`.
19
+
20
+ ### Changed
21
+ - `loadConfig()` no longer hard-fails when the DeXe-Protocol checkout is missing or incomplete at startup — it logs a soft warning to stderr and defers preparation to the first build-tool invocation.
22
+ - `src/bootstrap.ts` split into `resolveProtocolPath()` (cheap, startup-safe) and `ensureBuildReady()` (lazy, idempotent).
23
+ - New `src/runtime.ts` with portable `npmCommand()` / `hardhatCommand()` / `hasGit()` helpers.
24
+
25
+ ### Docs
26
+ - README now has an OS-specific install matrix (Mac/Linux vs. Windows) and a "dev / local checkout" recipe. Troubleshooting section updated for the new lazy-bootstrap behavior and the `process.execPath` npm resolution.
27
+
3
28
  ## 0.1.1
4
29
 
5
30
  ### Added
package/README.md CHANGED
@@ -6,41 +6,142 @@ MCP server for Claude Code / Antigravity that wraps the [DeXe Protocol](https://
6
6
 
7
7
  ## Prerequisites
8
8
 
9
- - **Node.js >= 20**
10
- - **Git** (the server auto-clones DeXe-Protocol on first run)
9
+ - **Node.js >= 20** with a working `npm`. Verify before continuing:
11
10
 
12
- ## Quick start
11
+ ```bash
12
+ node --version # should print v20.x or higher
13
+ npm --version # MUST print a version, not "command not found"
14
+ ```
13
15
 
14
- Add this to your project's `.mcp.json` (or your MCP client config):
16
+ If `npm --version` fails, you have a stripped Node install (a bare `node.exe` without the rest of the toolchain — common on Windows when `C:\Program Files\nodejs\node.exe` was placed manually). Install Node from <https://nodejs.org> or via [nvm](https://github.com/nvm-sh/nvm) / [nvm-windows](https://github.com/coreybutler/nvm-windows) and retry. Without npm, `npm install -g dexe-mcp` silently does nothing.
17
+
18
+ - **Git** — only needed on first run, to clone DeXe-Protocol. If you already have a local checkout, point `DEXE_PROTOCOL_PATH` at it and git is optional.
19
+
20
+ ## Install
21
+
22
+ ### 1. Install the package globally
23
+
24
+ ```bash
25
+ npm install -g dexe-mcp
26
+ ```
27
+
28
+ Verify the install landed by asking npm where it put it:
29
+
30
+ ```bash
31
+ npm root -g
32
+ # Mac/Linux: /usr/local/lib/node_modules (or ~/.nvm/versions/node/vXX.X.X/lib/node_modules)
33
+ # Windows: C:\Users\<you>\AppData\Roaming\nvm\<version>\node_modules
34
+ # (or C:\Users\<you>\AppData\Roaming\npm\node_modules for non-nvm)
35
+ ```
36
+
37
+ Note the output — you'll need it for the Windows install step below. The package lives at `<npm-root>/dexe-mcp/dist/index.js`.
38
+
39
+ ### 2. Register the MCP server
40
+
41
+ #### Mac / Linux
42
+
43
+ Bare command works because Unix `exec` resolves PATH directly:
44
+
45
+ ```bash
46
+ claude mcp add dexe -- dexe-mcp
47
+ ```
48
+
49
+ Or in JSON (`.mcp.json`, `claude_desktop_config.json`, etc.):
15
50
 
16
51
  ```json
17
52
  {
18
53
  "mcpServers": {
19
54
  "dexe": {
20
- "command": "npx",
21
- "args": ["-y", "dexe-mcp"]
55
+ "command": "dexe-mcp"
22
56
  }
23
57
  }
24
58
  }
25
59
  ```
26
60
 
27
- Restart your MCP client. On first launch, `dexe-mcp` will automatically:
61
+ #### Windows recommended: absolute path to `node` + `dist/index.js`
28
62
 
29
- 1. Clone `dexe-network/DeXe-Protocol` to a local cache directory (~200 MB, shallow clone)
30
- 2. Run `npm install` in the checkout
63
+ On Windows, `dexe-mcp` is installed as a `.cmd` shim that many MCP clients (including Claude Code as of this writing) fail to spawn cleanly over stdio. The **absolute-path** form bypasses shim resolution entirely and is the known-good recipe:
31
64
 
32
- Subsequent launches are instant. No manual setup needed.
65
+ ```bash
66
+ claude mcp add dexe -- "C:\Program Files\nodejs\node.exe" "C:\Users\<you>\AppData\Roaming\nvm\<version>\node_modules\dexe-mcp\dist\index.js"
67
+ ```
68
+
69
+ Substitute `<you>` and `<version>` (or use whatever `npm root -g` printed above). In JSON:
70
+
71
+ ```json
72
+ {
73
+ "mcpServers": {
74
+ "dexe": {
75
+ "command": "C:/Program Files/nodejs/node.exe",
76
+ "args": ["C:/Users/<you>/AppData/Roaming/nvm/<version>/node_modules/dexe-mcp/dist/index.js"]
77
+ }
78
+ }
79
+ }
80
+ ```
33
81
 
34
- ### Advanced: custom checkout path
82
+ This works because:
83
+ - No PATH dependency — every argument is an absolute path
84
+ - No `.cmd` / `.ps1` shim in the chain, so `CreateProcess` semantics don't trip over missing extensions
85
+ - `dexe-mcp` internally invokes `npm`/`hardhat` via `process.execPath`, so it uses whichever Node you pointed at and does not need npm on the spawned process PATH
35
86
 
36
- If you already have a DeXe-Protocol checkout or want to control its location:
87
+ <details>
88
+ <summary>Alternative: <code>cmd /c dexe-mcp</code> (not recommended — often unreliable with Claude Code)</summary>
37
89
 
38
90
  ```json
39
91
  {
40
92
  "mcpServers": {
41
93
  "dexe": {
42
- "command": "npx",
43
- "args": ["-y", "dexe-mcp"],
94
+ "command": "cmd",
95
+ "args": ["/c", "dexe-mcp"]
96
+ }
97
+ }
98
+ }
99
+ ```
100
+
101
+ Use only if the absolute-path form is inconvenient. End-to-end testing showed this can pass a direct stdio check but fail to complete the MCP handshake when spawned by Claude Code.
102
+ </details>
103
+
104
+ ### 3. Verify the install (optional but recommended)
105
+
106
+ Before wiring the server into your MCP client, confirm the binary can actually speak MCP over stdio. On any OS:
107
+
108
+ ```bash
109
+ # Send a minimal initialize request, expect a capabilities JSON back.
110
+ echo "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"t\",\"version\":\"1\"}}}" | dexe-mcp
111
+ ```
112
+
113
+ On Windows if the above hangs, try instead:
114
+
115
+ ```bash
116
+ echo {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"1"}}} | node "C:\Users\<you>\AppData\Roaming\nvm\<version>\node_modules\dexe-mcp\dist\index.js"
117
+ ```
118
+
119
+ A healthy response starts with a single stderr line (`[dexe-mcp] connected on stdio. …`) and a stdout JSON blob containing `"serverInfo":{"name":"dexe-mcp"}`. If you see that, the server is fine and any "failed to connect" from your MCP client is purely a client-side spawn/config problem, not a bug in dexe-mcp.
120
+
121
+ ### 4. Restart your MCP client
122
+
123
+ On the first build-tool call (e.g. `dexe_compile`), `dexe-mcp` will automatically:
124
+
125
+ 1. Shallow-clone `dexe-network/DeXe-Protocol` into a platform cache directory (~200 MB)
126
+ 2. Run `npm install` in that checkout (a few minutes, one time)
127
+
128
+ The MCP server itself starts instantly — the heavy work is deferred until you actually need it. Cache locations:
129
+
130
+ | OS | Path |
131
+ |----|------|
132
+ | Windows | `%LOCALAPPDATA%\dexe-mcp\DeXe-Protocol` |
133
+ | macOS | `~/Library/Caches/dexe-mcp/DeXe-Protocol` |
134
+ | Linux | `$XDG_CACHE_HOME/dexe-mcp/DeXe-Protocol` (or `~/.cache/dexe-mcp/DeXe-Protocol`) |
135
+
136
+ ### Advanced: existing DeXe-Protocol checkout
137
+
138
+ If you already have a DeXe-Protocol clone you want to reuse (and have run `npm install` there at least once), set `DEXE_PROTOCOL_PATH`:
139
+
140
+ ```json
141
+ {
142
+ "mcpServers": {
143
+ "dexe": {
144
+ "command": "dexe-mcp",
44
145
  "env": {
45
146
  "DEXE_PROTOCOL_PATH": "/absolute/path/to/your/DeXe-Protocol"
46
147
  }
@@ -49,9 +150,36 @@ If you already have a DeXe-Protocol checkout or want to control its location:
49
150
  }
50
151
  ```
51
152
 
153
+ With this set, dexe-mcp will **not** clone or install anything — it trusts the path you gave it. On Windows, wrap `command` with `cmd /c` as above.
154
+
155
+ ### Dev mode (working on dexe-mcp itself)
156
+
157
+ Clone this repo, build, and point the MCP command at the local `dist/index.js`:
158
+
159
+ ```bash
160
+ git clone https://github.com/edward-arinin-web-dev/dexe-mcp.git
161
+ cd dexe-mcp
162
+ npm install
163
+ npm run build
164
+ ```
165
+
166
+ ```json
167
+ {
168
+ "mcpServers": {
169
+ "dexe": {
170
+ "command": "node",
171
+ "args": ["/absolute/path/to/dexe-mcp/dist/index.js"],
172
+ "env": {
173
+ "DEXE_PROTOCOL_PATH": "/absolute/path/to/DeXe-Protocol"
174
+ }
175
+ }
176
+ }
177
+ }
178
+ ```
179
+
52
180
  ## First run
53
181
 
54
- Before introspection tools work, run `dexe_compile` once per session to populate `DeXe-Protocol/artifacts/`. You will get a clear "artifacts not found" error otherwise.
182
+ Before introspection tools work, run `dexe_compile` once per session to populate `DeXe-Protocol/artifacts/`. You will get a clear "artifacts not found" error otherwise. On a brand-new install the first `dexe_compile` also triggers the clone + `npm install` steps described above.
55
183
 
56
184
  ## Tool catalog
57
185
 
@@ -89,19 +217,44 @@ Before introspection tools work, run `dexe_compile` once per session to populate
89
217
 
90
218
  | Variable | Required | Purpose |
91
219
  |----------|----------|---------|
92
- | `DEXE_PROTOCOL_PATH` | no | Override the auto-managed DeXe-Protocol checkout path |
220
+ | `DEXE_PROTOCOL_PATH` | no | Use an existing DeXe-Protocol checkout; disables auto clone/install |
93
221
  | `DEXE_RPC_URL` | no | JSON-RPC endpoint for `dexe_decode_proposal` and `dexe_read_gov_state` |
94
222
  | `DEXE_FORK_BLOCK` | no | Pin the fork to a specific block (Phase B) |
95
223
 
96
224
  ## Troubleshooting
97
225
 
226
+ ### "`git` is not on PATH"
227
+
228
+ Install git from <https://git-scm.com/downloads> and restart your MCP client. Alternatively, clone DeXe-Protocol manually and set `DEXE_PROTOCOL_PATH` to skip the clone step entirely.
229
+
230
+ ### "`npm install` failed inside DeXe-Protocol"
231
+
232
+ Usually means your Node install lacks a bundled `npm` (e.g. a stripped `node.exe` dropped on PATH without the rest of the install). Reinstall Node from <https://nodejs.org> or via nvm / nvm-windows and retry. dexe-mcp invokes npm via `process.execPath` so it uses whichever Node is running it — it does not need `npm` on the spawn PATH.
233
+
234
+ ### "Failed to connect" in Claude Code (Windows)
235
+
236
+ Run the direct stdio test from the "Verify the install" section first. If that prints a clean `serverInfo` response, the server is fine and the problem is in how your client is spawning it.
237
+
238
+ The fix is almost always to switch to the **absolute-path** registration:
239
+
240
+ ```bash
241
+ claude mcp remove dexe
242
+ claude mcp add dexe -- "C:\Program Files\nodejs\node.exe" "C:\Users\<you>\AppData\Roaming\nvm\<version>\node_modules\dexe-mcp\dist\index.js"
243
+ ```
244
+
245
+ Bare `dexe-mcp` and `cmd /c dexe-mcp` both rely on shim resolution that Claude Code's `CreateProcess`-based spawn does not always handle. The absolute-path form has zero shim resolution.
246
+
247
+ ### `npm install -g dexe-mcp` reported success but `dexe-mcp` is nowhere to be found
248
+
249
+ You're almost certainly on a stripped Node install whose `npm` silently no-ops. Check with `npm --version` — if it fails, install Node properly (see Prerequisites). If it prints a version, check `npm root -g` and look inside that directory; the package should be at `<npm-root>/dexe-mcp`.
250
+
98
251
  ### "Hardhat artifacts not found — run dexe_compile first"
99
252
 
100
253
  Introspection tools require compiled artifacts. Run `dexe_compile` once after the initial setup to populate them.
101
254
 
102
- ### "Failed to clone DeXe-Protocol"
255
+ ### "DEXE_PROTOCOL_PATH=… is missing node_modules"
103
256
 
104
- Make sure `git` is installed and available on your PATH, and that you have internet access. The server clones from `https://github.com/dexe-network/DeXe-Protocol.git`.
257
+ You pointed `DEXE_PROTOCOL_PATH` at a checkout that hasn't been installed yet. `cd` into it and run `npm install` once, then retry.
105
258
 
106
259
  ### "DEXE_RPC_URL is not set"
107
260
 
@@ -1,12 +1,30 @@
1
1
  /**
2
- * Ensures a DeXe-Protocol checkout is available, returning its absolute path.
2
+ * Cheap, synchronous resolution of where the DeXe-Protocol checkout *should*
3
+ * live. **Does not** clone or install anything — safe to call at MCP startup.
3
4
  *
4
5
  * Priority:
5
6
  * 1. `DEXE_PROTOCOL_PATH` env var (power-user override)
6
- * 2. Auto-managed clone in the platform cache directory
7
+ * 2. Auto-managed path inside the platform cache directory
7
8
  *
8
- * On first run the clone + npm install may take a few minutes.
9
- * Progress is logged to stderr (stdout is the MCP protocol channel).
9
+ * The returned path may not exist yet on disk. Call `ensureBuildReady()`
10
+ * before invoking tools that require hardhat.
10
11
  */
11
- export declare function ensureProtocolCheckout(): Promise<string>;
12
+ export declare function resolveProtocolPath(): string;
13
+ /**
14
+ * True if `protocolPath` looks like a hardhat project with installed deps.
15
+ * Used by build/test tools to short-circuit the lazy bootstrap.
16
+ */
17
+ export declare function isBuildReady(protocolPath: string): boolean;
18
+ /**
19
+ * Lazy, expensive bootstrap: ensures a DeXe-Protocol checkout exists at
20
+ * `protocolPath` and that its npm dependencies are installed. Idempotent.
21
+ *
22
+ * Only called from build/test tools. MCP startup must **not** await this.
23
+ *
24
+ * Skipped entirely when `DEXE_PROTOCOL_PATH` points at a user-managed
25
+ * checkout — we trust the user to keep it in shape.
26
+ *
27
+ * Throws with an actionable message if `git` or `npm` are unavailable.
28
+ */
29
+ export declare function ensureBuildReady(protocolPath: string): Promise<void>;
12
30
  //# sourceMappingURL=bootstrap.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAsCA;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC,CAgD9D"}
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAqCA;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAO1D;AAMD;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuF1E"}
package/dist/bootstrap.js CHANGED
@@ -1,7 +1,10 @@
1
1
  import { existsSync, mkdirSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { homedir, platform } from "node:os";
4
- import { execSync } from "node:child_process";
4
+ import { execFile } from "node:child_process";
5
+ import { promisify } from "node:util";
6
+ import { hasGit, npmCommand } from "./runtime.js";
7
+ const execFileAsync = promisify(execFile);
5
8
  const REPO_URL = "https://github.com/dexe-network/DeXe-Protocol.git";
6
9
  const CACHE_DIR_NAME = "dexe-mcp";
7
10
  const CHECKOUT_DIR = "DeXe-Protocol";
@@ -21,63 +24,119 @@ function getCacheDir() {
21
24
  if (os === "darwin") {
22
25
  return join(homedir(), "Library", "Caches", CACHE_DIR_NAME);
23
26
  }
24
- // Linux / others — respect XDG_CACHE_HOME
25
27
  const base = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
26
28
  return join(base, CACHE_DIR_NAME);
27
29
  }
28
30
  function log(msg) {
29
31
  process.stderr.write(`[dexe-mcp] ${msg}\n`);
30
32
  }
31
- function runSync(cmd, cwd) {
32
- execSync(cmd, { cwd, stdio: ["ignore", "pipe", "pipe"] });
33
- }
34
33
  /**
35
- * Ensures a DeXe-Protocol checkout is available, returning its absolute path.
34
+ * Cheap, synchronous resolution of where the DeXe-Protocol checkout *should*
35
+ * live. **Does not** clone or install anything — safe to call at MCP startup.
36
36
  *
37
37
  * Priority:
38
38
  * 1. `DEXE_PROTOCOL_PATH` env var (power-user override)
39
- * 2. Auto-managed clone in the platform cache directory
39
+ * 2. Auto-managed path inside the platform cache directory
40
40
  *
41
- * On first run the clone + npm install may take a few minutes.
42
- * Progress is logged to stderr (stdout is the MCP protocol channel).
41
+ * The returned path may not exist yet on disk. Call `ensureBuildReady()`
42
+ * before invoking tools that require hardhat.
43
43
  */
44
- export async function ensureProtocolCheckout() {
45
- // ---- explicit override ----
44
+ export function resolveProtocolPath() {
46
45
  const explicit = process.env.DEXE_PROTOCOL_PATH?.trim();
47
46
  if (explicit)
48
47
  return explicit;
49
- // ---- auto-managed clone ----
50
- const cacheDir = getCacheDir();
51
- const protocolPath = join(cacheDir, CHECKOUT_DIR);
52
- if (!existsSync(cacheDir)) {
53
- mkdirSync(cacheDir, { recursive: true });
54
- }
55
- const gitDir = join(protocolPath, ".git");
56
- if (!existsSync(gitDir)) {
57
- log(`Cloning DeXe-Protocol (shallow, ~200 MB) into ${protocolPath} …`);
58
- log("This only happens once. Subsequent launches will be instant.");
59
- try {
60
- runSync(`git clone --depth 1 ${REPO_URL} "${CHECKOUT_DIR}"`, cacheDir);
61
- }
62
- catch (err) {
63
- const msg = err instanceof Error ? err.message : String(err);
64
- throw new Error(`Failed to clone DeXe-Protocol. Make sure git is installed and you have internet access.\n${msg}`);
65
- }
66
- log("Clone complete.");
67
- }
68
- // Ensure npm dependencies are installed
69
- const nodeModules = join(protocolPath, "node_modules");
70
- if (!existsSync(nodeModules)) {
71
- log("Installing DeXe-Protocol npm dependencies (first run only) …");
48
+ return join(getCacheDir(), CHECKOUT_DIR);
49
+ }
50
+ /**
51
+ * True if `protocolPath` looks like a hardhat project with installed deps.
52
+ * Used by build/test tools to short-circuit the lazy bootstrap.
53
+ */
54
+ export function isBuildReady(protocolPath) {
55
+ if (!existsSync(protocolPath))
56
+ return false;
57
+ const hasConfig = existsSync(join(protocolPath, "hardhat.config.js")) ||
58
+ existsSync(join(protocolPath, "hardhat.config.ts"));
59
+ const hasNodeModules = existsSync(join(protocolPath, "node_modules"));
60
+ return hasConfig && hasNodeModules;
61
+ }
62
+ // Promise-coalescing: if two tools call ensureBuildReady() concurrently,
63
+ // they should share a single clone+install, not race.
64
+ let inflightEnsure = null;
65
+ /**
66
+ * Lazy, expensive bootstrap: ensures a DeXe-Protocol checkout exists at
67
+ * `protocolPath` and that its npm dependencies are installed. Idempotent.
68
+ *
69
+ * Only called from build/test tools. MCP startup must **not** await this.
70
+ *
71
+ * Skipped entirely when `DEXE_PROTOCOL_PATH` points at a user-managed
72
+ * checkout — we trust the user to keep it in shape.
73
+ *
74
+ * Throws with an actionable message if `git` or `npm` are unavailable.
75
+ */
76
+ export async function ensureBuildReady(protocolPath) {
77
+ if (isBuildReady(protocolPath))
78
+ return;
79
+ if (inflightEnsure)
80
+ return inflightEnsure;
81
+ inflightEnsure = (async () => {
72
82
  try {
73
- runSync("npm install", protocolPath);
83
+ const explicit = process.env.DEXE_PROTOCOL_PATH?.trim();
84
+ if (explicit) {
85
+ // User-managed checkout: don't touch it. Give a clear diagnosis.
86
+ if (!existsSync(protocolPath)) {
87
+ throw new Error(`DEXE_PROTOCOL_PATH points at ${protocolPath}, but that directory does not exist.`);
88
+ }
89
+ if (!existsSync(join(protocolPath, "hardhat.config.js")) &&
90
+ !existsSync(join(protocolPath, "hardhat.config.ts"))) {
91
+ throw new Error(`DEXE_PROTOCOL_PATH=${protocolPath} is not a Hardhat project (no hardhat.config.{js,ts}).`);
92
+ }
93
+ if (!existsSync(join(protocolPath, "node_modules"))) {
94
+ throw new Error(`DEXE_PROTOCOL_PATH=${protocolPath} is missing node_modules. Run \`npm install\` there once and retry.`);
95
+ }
96
+ return;
97
+ }
98
+ // Auto-managed cache path: we own it, we can clone + install into it.
99
+ const cacheDir = getCacheDir();
100
+ if (!existsSync(cacheDir))
101
+ mkdirSync(cacheDir, { recursive: true });
102
+ if (!existsSync(join(protocolPath, ".git"))) {
103
+ if (!(await hasGit())) {
104
+ throw new Error("`git` is not on PATH. Install git (https://git-scm.com/downloads) and retry — dexe-mcp needs it to fetch the DeXe-Protocol sources on first run.");
105
+ }
106
+ log(`Cloning DeXe-Protocol (shallow, ~200 MB) into ${protocolPath} …`);
107
+ log("This only happens once. Subsequent calls will be instant.");
108
+ try {
109
+ await execFileAsync("git", ["clone", "--depth", "1", REPO_URL, CHECKOUT_DIR], { cwd: cacheDir, windowsHide: true });
110
+ }
111
+ catch (err) {
112
+ const msg = err instanceof Error ? err.message : String(err);
113
+ throw new Error(`Failed to clone DeXe-Protocol. Check internet access and git credentials.\n${msg}`);
114
+ }
115
+ log("Clone complete.");
116
+ }
117
+ if (!existsSync(join(protocolPath, "node_modules"))) {
118
+ log("Installing DeXe-Protocol npm dependencies (first run only) — this takes a few minutes …");
119
+ const npm = npmCommand();
120
+ try {
121
+ await execFileAsync(npm.command, [...npm.prefixArgs, "install", "--no-audit", "--no-fund"], {
122
+ cwd: protocolPath,
123
+ windowsHide: true,
124
+ maxBuffer: 64 * 1024 * 1024,
125
+ });
126
+ }
127
+ catch (err) {
128
+ const msg = err instanceof Error ? err.message : String(err);
129
+ throw new Error(`\`npm install\` failed inside ${protocolPath}.\n` +
130
+ `If your Node install lacks a bundled npm (e.g. a stripped node.exe), ` +
131
+ `install Node from https://nodejs.org or via nvm and retry.\n${msg}`);
132
+ }
133
+ log("Dependencies installed.");
134
+ }
74
135
  }
75
- catch (err) {
76
- const msg = err instanceof Error ? err.message : String(err);
77
- throw new Error(`npm install failed in DeXe-Protocol checkout.\n${msg}`);
136
+ finally {
137
+ inflightEnsure = null;
78
138
  }
79
- log("Dependencies installed.");
80
- }
81
- return protocolPath;
139
+ })();
140
+ return inflightEnsure;
82
141
  }
83
142
  //# sourceMappingURL=bootstrap.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,QAAQ,GAAG,mDAAmD,CAAC;AACrE,MAAM,cAAc,GAAG,UAAU,CAAC;AAClC,MAAM,YAAY,GAAG,eAAe,CAAC;AAErC;;;;;;GAMG;AACH,SAAS,WAAW;IAClB,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IACtB,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAC7E,OAAO,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;IAC9D,CAAC;IACD,0CAA0C;IAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;IACrE,OAAO,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,GAAG,CAAC,GAAW;IACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,OAAO,CAAC,GAAW,EAAE,GAAW;IACvC,QAAQ,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC1C,8BAA8B;IAC9B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC;IACxD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAElD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAE1C,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,GAAG,CAAC,iDAAiD,YAAY,IAAI,CAAC,CAAC;QACvE,GAAG,CAAC,8DAA8D,CAAC,CAAC;QACpE,IAAI,CAAC;YACH,OAAO,CACL,uBAAuB,QAAQ,KAAK,YAAY,GAAG,EACnD,QAAQ,CACT,CAAC;QACJ,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,MAAM,IAAI,KAAK,CACb,4FAA4F,GAAG,EAAE,CAClG,CAAC;QACJ,CAAC;QACD,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACzB,CAAC;IAED,wCAAwC;IACxC,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IACvD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,GAAG,CAAC,8DAA8D,CAAC,CAAC;QACpE,IAAI,CAAC;YACH,OAAO,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,MAAM,IAAI,KAAK,CACb,kDAAkD,GAAG,EAAE,CACxD,CAAC;QACJ,CAAC;QACD,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export interface DexeConfig {
2
- /** Absolute, normalized path to the DeXe-Protocol checkout. */
2
+ /** Absolute, normalized path to the DeXe-Protocol checkout (may not exist yet). */
3
3
  protocolPath: string;
4
4
  /** Optional JSON-RPC endpoint for on-chain gov tools. */
5
5
  rpcUrl?: string;
@@ -7,13 +7,10 @@ export interface DexeConfig {
7
7
  forkBlock?: number;
8
8
  }
9
9
  /**
10
- * Validates environment and returns a frozen config.
11
- *
12
- * If `DEXE_PROTOCOL_PATH` is set, uses it directly (power-user override).
13
- * Otherwise, auto-clones DeXe-Protocol into a platform cache directory.
14
- *
15
- * Exported primarily for the MCP entrypoint; tests can construct their own
16
- * config objects directly.
10
+ * Reads environment and returns a frozen config. **Fast and side-effect-free**
11
+ * — safe to await during MCP `initialize`. Does not clone, install, or shell
12
+ * out. The protocol checkout may not exist yet; `ensureBuildReady` handles
13
+ * that lazily from inside build/test tools.
17
14
  */
18
15
  export declare function loadConfig(): Promise<DexeConfig>;
19
16
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CA4BtD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CA4BtD"}
package/dist/config.js CHANGED
@@ -1,25 +1,22 @@
1
- import { existsSync, statSync } from "node:fs";
2
- import { resolve, join } from "node:path";
3
- import { ensureProtocolCheckout } from "./bootstrap.js";
1
+ import { existsSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { resolveProtocolPath, isBuildReady } from "./bootstrap.js";
4
4
  /**
5
- * Validates environment and returns a frozen config.
6
- *
7
- * If `DEXE_PROTOCOL_PATH` is set, uses it directly (power-user override).
8
- * Otherwise, auto-clones DeXe-Protocol into a platform cache directory.
9
- *
10
- * Exported primarily for the MCP entrypoint; tests can construct their own
11
- * config objects directly.
5
+ * Reads environment and returns a frozen config. **Fast and side-effect-free**
6
+ * — safe to await during MCP `initialize`. Does not clone, install, or shell
7
+ * out. The protocol checkout may not exist yet; `ensureBuildReady` handles
8
+ * that lazily from inside build/test tools.
12
9
  */
13
10
  export async function loadConfig() {
14
- const raw = await ensureProtocolCheckout();
15
- const protocolPath = resolve(raw);
16
- if (!existsSync(protocolPath) || !statSync(protocolPath).isDirectory()) {
17
- fatal(`DeXe-Protocol path does not exist or is not a directory: ${protocolPath}`);
11
+ const protocolPath = resolve(resolveProtocolPath());
12
+ // Soft warning only — don't block startup. The lazy bootstrap will either
13
+ // create the checkout (auto-managed path) or surface a clear error when a
14
+ // build tool is actually invoked (DEXE_PROTOCOL_PATH override).
15
+ if (!existsSync(protocolPath)) {
16
+ process.stderr.write(`[dexe-mcp] DeXe-Protocol checkout not found at ${protocolPath} — will be prepared on first dexe_compile call.\n`);
18
17
  }
19
- const hardhatConfig = join(protocolPath, "hardhat.config.js");
20
- const hardhatConfigTs = join(protocolPath, "hardhat.config.ts");
21
- if (!existsSync(hardhatConfig) && !existsSync(hardhatConfigTs)) {
22
- fatal(`DeXe-Protocol path is not a Hardhat project — no hardhat.config.{js,ts} found at ${protocolPath}`);
18
+ else if (!isBuildReady(protocolPath)) {
19
+ process.stderr.write(`[dexe-mcp] DeXe-Protocol checkout at ${protocolPath} is incomplete (missing node_modules or hardhat.config) — will be prepared on first dexe_compile call.\n`);
23
20
  }
24
21
  const rpcUrl = process.env.DEXE_RPC_URL?.trim() || undefined;
25
22
  let forkBlock;
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAWxD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,GAAG,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAElC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACvE,KAAK,CAAC,4DAA4D,YAAY,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,mBAAmB,CAAC,CAAC;IAC9D,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,mBAAmB,CAAC,CAAC;IAChE,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAC/D,KAAK,CACH,oFAAoF,YAAY,EAAE,CACnG,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAE7D,IAAI,SAA6B,CAAC;IAClC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,KAAK,CAAC,wDAAwD,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC;QAC/F,CAAC;QACD,SAAS,GAAG,CAAC,CAAC;IAChB,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,KAAK,CAAC,GAAW;IACxB,oDAAoD;IACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAWnE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,YAAY,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAEpD,0EAA0E;IAC1E,0EAA0E;IAC1E,gEAAgE;IAChE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,kDAAkD,YAAY,mDAAmD,CAClH,CAAC;IACJ,CAAC;SAAM,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,CAAC;QACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wCAAwC,YAAY,0GAA0G,CAC/J,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAE7D,IAAI,SAA6B,CAAC;IAClC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,KAAK,CAAC,wDAAwD,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC;QAC/F,CAAC;QACD,SAAS,GAAG,CAAC,CAAC;IAChB,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,KAAK,CAAC,GAAW;IACxB,oDAAoD;IACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
package/dist/hardhat.d.ts CHANGED
@@ -17,9 +17,19 @@ export interface RunResult {
17
17
  export declare class HardhatRunner {
18
18
  private readonly config;
19
19
  constructor(config: DexeConfig);
20
- /** Run `npm run <script>` in the protocol directory. */
20
+ /**
21
+ * Run `npm run <script>` in the protocol directory.
22
+ *
23
+ * Uses `node <npm-cli.js>` under the hood so this works regardless of
24
+ * whether `npm` is on the MCP's spawn PATH.
25
+ */
21
26
  runNpmScript(script: string, extraArgs?: string[]): Promise<RunResult>;
22
- /** Run `npx hardhat <subcommand> <args...>` in the protocol directory. */
27
+ /**
28
+ * Run `hardhat <subcommand> <args...>` in the protocol directory.
29
+ *
30
+ * Uses `node <protocol>/node_modules/hardhat/internal/cli/cli.js` so this
31
+ * doesn't require `npx` on PATH.
32
+ */
23
33
  runHardhat(subcommand: string, args?: string[]): Promise<RunResult>;
24
34
  private run;
25
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"hardhat.d.ts","sourceRoot":"","sources":["../src/hardhat.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,sDAAsD;AACtD,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAiBD,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,UAAU;IAE/C,wDAAwD;IACxD,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAQ1E,0EAA0E;IAC1E,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAIvE,OAAO,CAAC,GAAG;CAuDZ"}
1
+ {"version":3,"file":"hardhat.d.ts","sourceRoot":"","sources":["../src/hardhat.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAI9C,sDAAsD;AACtD,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAiBD,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,UAAU;IAE/C;;;;;OAKG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAQhF;;;;;OAKG;IACG,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAW7E,OAAO,CAAC,GAAG;CAuDZ"}
package/dist/hardhat.js CHANGED
@@ -3,6 +3,8 @@ import pLimit from "p-limit";
3
3
  import { writeFileSync, mkdtempSync } from "node:fs";
4
4
  import { tmpdir } from "node:os";
5
5
  import { join } from "node:path";
6
+ import { ensureBuildReady } from "./bootstrap.js";
7
+ import { hardhatCommand, npmCommand } from "./runtime.js";
6
8
  const HARDHAT_TIMEOUT_MS = 10 * 60 * 1000;
7
9
  const STDOUT_TAIL_LINES = 200;
8
10
  const STDERR_TAIL_LINES = 100;
@@ -21,17 +23,33 @@ export class HardhatRunner {
21
23
  constructor(config) {
22
24
  this.config = config;
23
25
  }
24
- /** Run `npm run <script>` in the protocol directory. */
25
- runNpmScript(script, extraArgs = []) {
26
- const args = ["run", script];
27
- if (extraArgs.length > 0) {
26
+ /**
27
+ * Run `npm run <script>` in the protocol directory.
28
+ *
29
+ * Uses `node <npm-cli.js>` under the hood so this works regardless of
30
+ * whether `npm` is on the MCP's spawn PATH.
31
+ */
32
+ async runNpmScript(script, extraArgs = []) {
33
+ await ensureBuildReady(this.config.protocolPath);
34
+ const npm = npmCommand();
35
+ const args = [...npm.prefixArgs, "run", script];
36
+ if (extraArgs.length > 0)
28
37
  args.push("--", ...extraArgs);
29
- }
30
- return this.run("npm", args, `npm-run-${script}`);
38
+ return this.run(npm.command, args, `npm-run-${script}`);
31
39
  }
32
- /** Run `npx hardhat <subcommand> <args...>` in the protocol directory. */
33
- runHardhat(subcommand, args = []) {
34
- return this.run("npx", ["hardhat", subcommand, ...args], `hardhat-${subcommand}`);
40
+ /**
41
+ * Run `hardhat <subcommand> <args...>` in the protocol directory.
42
+ *
43
+ * Uses `node <protocol>/node_modules/hardhat/internal/cli/cli.js` so this
44
+ * doesn't require `npx` on PATH.
45
+ */
46
+ async runHardhat(subcommand, args = []) {
47
+ await ensureBuildReady(this.config.protocolPath);
48
+ const hh = hardhatCommand(this.config.protocolPath);
49
+ if (!hh) {
50
+ throw new Error(`Hardhat is not installed inside ${this.config.protocolPath}. This should have been fixed by ensureBuildReady — did npm install fail?`);
51
+ }
52
+ return this.run(hh.command, [...hh.prefixArgs, subcommand, ...args], `hardhat-${subcommand}`);
35
53
  }
36
54
  run(command, args, label) {
37
55
  return limit(async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"hardhat.js","sourceRoot":"","sources":["../src/hardhat.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hardhat.js","sourceRoot":"","sources":["../src/hardhat.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { loadConfig } from "./config.js";
5
5
  import { registerAll } from "./tools/index.js";
6
6
  async function main() {
7
7
  const config = await loadConfig();
8
- const server = new McpServer({ name: "dexe-mcp", version: "0.1.1" }, {
8
+ const server = new McpServer({ name: "dexe-mcp", version: "0.1.3" }, {
9
9
  instructions: "Tools for the DeXe Protocol governance-DAO codebase. Before calling any dexe_get_* / dexe_list_contracts / dexe_find_selector tool, ensure artifacts exist by calling dexe_compile once per session. dexe_decode_proposal and dexe_read_gov_state require DEXE_RPC_URL to be set.",
10
10
  });
11
11
  registerAll(server, config);
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Portable runtime helpers for spawning `npm`, `npx`, `hardhat`, and `git`
3
+ * without depending on the MCP process's PATH.
4
+ *
5
+ * Claude Code (and other MCP clients) spawn servers with a minimal PATH.
6
+ * On Windows in particular, `npm`/`npx` are `.cmd` shims that `CreateProcess`
7
+ * won't find unless they're on that PATH. We side-step the whole problem by
8
+ * invoking JS entry points (`npm-cli.js`, `hardhat/internal/cli/cli.js`)
9
+ * directly through `process.execPath`.
10
+ */
11
+ /**
12
+ * Locate the `npm-cli.js` that ships with the currently-running Node.
13
+ *
14
+ * Layouts we handle:
15
+ * - Windows (official installer / nvm-windows):
16
+ * <execDir>\node_modules\npm\bin\npm-cli.js
17
+ * - Unix (nvm, homebrew, official installer):
18
+ * <execDir>/../lib/node_modules/npm/bin/npm-cli.js
19
+ *
20
+ * Returns `null` if nothing is found — caller should fall back to `npm` on PATH.
21
+ */
22
+ export declare function resolveNpmCli(): string | null;
23
+ /**
24
+ * Locate Hardhat's CLI entry point inside a protocol checkout.
25
+ * Returns `null` if `node_modules` isn't installed yet.
26
+ */
27
+ export declare function resolveHardhatCli(protocolPath: string): string | null;
28
+ export declare function hasGit(): Promise<boolean>;
29
+ /**
30
+ * Describe the PATH-independent command we'd use to run `npm` / `npx`.
31
+ * Returns the `[command, prefixArgs]` tuple so callers can append script args.
32
+ *
33
+ * If `npm-cli.js` is found, we return `(process.execPath, [cliPath])`.
34
+ * Otherwise we fall back to `("npm", [])` which requires PATH — and may fail
35
+ * on machines where npm isn't on the spawn PATH, but that's strictly better
36
+ * than crashing at startup.
37
+ */
38
+ export declare function npmCommand(): {
39
+ command: string;
40
+ prefixArgs: string[];
41
+ };
42
+ /**
43
+ * Describe the command we'd use to run Hardhat against a given protocol path.
44
+ *
45
+ * Prefers `node <protocolPath>/node_modules/hardhat/internal/cli/cli.js` which
46
+ * has zero PATH dependency. Falls back to `npx hardhat` (requires PATH).
47
+ *
48
+ * Returns `null` if the protocol's `node_modules` isn't installed — caller
49
+ * should trigger `ensureBuildReady` first.
50
+ */
51
+ export declare function hardhatCommand(protocolPath: string): {
52
+ command: string;
53
+ prefixArgs: string[];
54
+ } | null;
55
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAa7C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGrE;AAID,wBAAgB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAQzC;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAItE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,GACnB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAIlD"}
@@ -0,0 +1,90 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { platform } from "node:os";
4
+ import { execFile } from "node:child_process";
5
+ /**
6
+ * Portable runtime helpers for spawning `npm`, `npx`, `hardhat`, and `git`
7
+ * without depending on the MCP process's PATH.
8
+ *
9
+ * Claude Code (and other MCP clients) spawn servers with a minimal PATH.
10
+ * On Windows in particular, `npm`/`npx` are `.cmd` shims that `CreateProcess`
11
+ * won't find unless they're on that PATH. We side-step the whole problem by
12
+ * invoking JS entry points (`npm-cli.js`, `hardhat/internal/cli/cli.js`)
13
+ * directly through `process.execPath`.
14
+ */
15
+ /**
16
+ * Locate the `npm-cli.js` that ships with the currently-running Node.
17
+ *
18
+ * Layouts we handle:
19
+ * - Windows (official installer / nvm-windows):
20
+ * <execDir>\node_modules\npm\bin\npm-cli.js
21
+ * - Unix (nvm, homebrew, official installer):
22
+ * <execDir>/../lib/node_modules/npm/bin/npm-cli.js
23
+ *
24
+ * Returns `null` if nothing is found — caller should fall back to `npm` on PATH.
25
+ */
26
+ export function resolveNpmCli() {
27
+ const execDir = dirname(process.execPath);
28
+ const candidates = platform() === "win32"
29
+ ? [join(execDir, "node_modules", "npm", "bin", "npm-cli.js")]
30
+ : [
31
+ join(execDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
32
+ join(execDir, "..", "libexec", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
33
+ ];
34
+ for (const c of candidates) {
35
+ if (existsSync(c))
36
+ return c;
37
+ }
38
+ return null;
39
+ }
40
+ /**
41
+ * Locate Hardhat's CLI entry point inside a protocol checkout.
42
+ * Returns `null` if `node_modules` isn't installed yet.
43
+ */
44
+ export function resolveHardhatCli(protocolPath) {
45
+ const p = join(protocolPath, "node_modules", "hardhat", "internal", "cli", "cli.js");
46
+ return existsSync(p) ? p : null;
47
+ }
48
+ /** Detect whether `git` is available on PATH. Cached per-process. */
49
+ let gitAvailable = null;
50
+ export function hasGit() {
51
+ if (gitAvailable !== null)
52
+ return Promise.resolve(gitAvailable);
53
+ return new Promise((resolvePromise) => {
54
+ execFile("git", ["--version"], { windowsHide: true }, (err) => {
55
+ gitAvailable = !err;
56
+ resolvePromise(gitAvailable);
57
+ });
58
+ });
59
+ }
60
+ /**
61
+ * Describe the PATH-independent command we'd use to run `npm` / `npx`.
62
+ * Returns the `[command, prefixArgs]` tuple so callers can append script args.
63
+ *
64
+ * If `npm-cli.js` is found, we return `(process.execPath, [cliPath])`.
65
+ * Otherwise we fall back to `("npm", [])` which requires PATH — and may fail
66
+ * on machines where npm isn't on the spawn PATH, but that's strictly better
67
+ * than crashing at startup.
68
+ */
69
+ export function npmCommand() {
70
+ const cli = resolveNpmCli();
71
+ if (cli)
72
+ return { command: process.execPath, prefixArgs: [cli] };
73
+ return { command: platform() === "win32" ? "npm.cmd" : "npm", prefixArgs: [] };
74
+ }
75
+ /**
76
+ * Describe the command we'd use to run Hardhat against a given protocol path.
77
+ *
78
+ * Prefers `node <protocolPath>/node_modules/hardhat/internal/cli/cli.js` which
79
+ * has zero PATH dependency. Falls back to `npx hardhat` (requires PATH).
80
+ *
81
+ * Returns `null` if the protocol's `node_modules` isn't installed — caller
82
+ * should trigger `ensureBuildReady` first.
83
+ */
84
+ export function hardhatCommand(protocolPath) {
85
+ const cli = resolveHardhatCli(protocolPath);
86
+ if (cli)
87
+ return { command: process.execPath, prefixArgs: [cli] };
88
+ return null;
89
+ }
90
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C;;;;;;;;;GASG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,UAAU,GACd,QAAQ,EAAE,KAAK,OAAO;QACpB,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;QAC7D,CAAC,CAAC;YACE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC;YACtE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC;SAClF,CAAC;IACR,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,YAAoB;IACpD,MAAM,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrF,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAClC,CAAC;AAED,qEAAqE;AACrE,IAAI,YAAY,GAAmB,IAAI,CAAC;AACxC,MAAM,UAAU,MAAM;IACpB,IAAI,YAAY,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAChE,OAAO,IAAI,OAAO,CAAC,CAAC,cAAc,EAAE,EAAE;QACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE;YAC5D,YAAY,GAAG,CAAC,GAAG,CAAC;YACpB,cAAc,CAAC,YAAY,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAC5B,IAAI,GAAG;QAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;IACjE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;AACjF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,YAAoB;IAEpB,MAAM,GAAG,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAC5C,IAAI,GAAG;QAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;IACjE,OAAO,IAAI,CAAC;AACd,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dexe-mcp",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "MCP server wrapping DeXe Protocol for Claude Code dev tooling (build/test, contract introspection, governance-domain tools)",
5
5
  "type": "module",
6
6
  "license": "MIT",