@n0zer0d4y/vulcan-file-ops 1.2.13 → 1.2.14

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/CHANGELOG.md CHANGED
@@ -8,33 +8,43 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
8
8
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
9
9
 
10
10
 
11
-
12
- ## [1.2.13] - 2026-04-23
13
-
14
- ### Fixed
15
-
16
- - Resolved the remaining MCP client tool discovery failure introduced after the SDK upgrade.
17
- - Tool schemas exposed through `tools/list` are now normalized for stricter MCP clients.
18
- - Removed client-hostile schema constructs from published tool input schemas, including `$schema`, `$ref`, `anyOf`, `oneOf`, and `allOf`.
19
- - Replaced the highest-risk wire schemas with explicit compatibility-first object schemas for `attach_image` and `make_directory`.
20
- - Preserved runtime backward compatibility while tightening the schemas advertised to clients.
21
- - Fixed residual MCP mode detection drift so stdio mode is triggered reliably in local and `npx` execution paths.
22
- - Added `zod` as a direct runtime dependency to avoid install-time fragility in clean environments and `npx` usage.
23
- - Synchronized package metadata so published registry metadata and local package metadata report the same release version.
24
- - Re-enabled and stabilized the previously skipped PDF-related Jest coverage.
25
- - Enabled the 10 skipped document tests for PDF read, HTML-to-PDF write, mixed document batches, and PDF round-trip paths.
26
- - Updated Jest PDF mocks so document tests exercise meaningful content paths instead of placeholder-only buffers.
27
- - Suppressed expected negative-path test diagnostics inside tests so successful runs no longer look like runtime failures.
28
- - Added a regression test to prevent incompatible tool schema shapes from reappearing in future releases.
29
-
30
- ### Changed
31
-
32
- - Documented the Codex-specific MCP configuration format in the README alongside the JSON-based client examples.
33
- - Updated `npx` examples to use `-y` explicitly for non-interactive client execution.
34
-
35
- ## [1.2.12] - 2026-02-21
36
-
37
- ### Fixed
11
+
12
+ ## [1.2.14] - 2026-05-16
13
+
14
+ ### Fixed
15
+
16
+ - **CRITICAL**: Fixed initialization deadlock with `claude-ai` v0.1.0 client (Claude Desktop web client, protocol `2025-11-25`).
17
+ - **Root Cause**: A custom `setRequestHandler(InitializeRequestSchema, ...)` was overriding the SDK's internal `_oninitialize` handler. This broke the SDK's state machine: `_clientCapabilities` and `_clientVersion` were never set, and protocol version negotiation was bypassed — the server echoed back the client's requested version verbatim rather than responding with the highest version it actually supports. The new client's stricter handshake exposed this latent defect.
18
+ - **Fix**: Removed the custom initialize handler and restored the SDK's built-in `_oninitialize`. The server now correctly negotiates `2025-06-18` when a client requests `2025-11-25`, which the client accepts per the MCP spec.
19
+ - **Instructions**: Server instructions (`generateServerDescription()`) are now injected into the SDK's `_instructions` field after directory initialization in `runServer()`, so they remain present in the initialize response without requiring a custom handler.
20
+ - Fixed `oninitialized` callback blocking the MCP handshake. The `listRoots()` call inside `oninitialized` was previously awaited, creating a potential deadlock (client won't respond to `roots/list` until after `initialized` is acknowledged, but the callback blocked acknowledgement). Changed to a detached fire-and-forget promise.
21
+
22
+ ## [1.2.13] - 2026-04-23
23
+
24
+ ### Fixed
25
+
26
+ - Resolved the remaining MCP client tool discovery failure introduced after the SDK upgrade.
27
+ - Tool schemas exposed through `tools/list` are now normalized for stricter MCP clients.
28
+ - Removed client-hostile schema constructs from published tool input schemas, including `$schema`, `$ref`, `anyOf`, `oneOf`, and `allOf`.
29
+ - Replaced the highest-risk wire schemas with explicit compatibility-first object schemas for `attach_image` and `make_directory`.
30
+ - Preserved runtime backward compatibility while tightening the schemas advertised to clients.
31
+ - Fixed residual MCP mode detection drift so stdio mode is triggered reliably in local and `npx` execution paths.
32
+ - Added `zod` as a direct runtime dependency to avoid install-time fragility in clean environments and `npx` usage.
33
+ - Synchronized package metadata so published registry metadata and local package metadata report the same release version.
34
+ - Re-enabled and stabilized the previously skipped PDF-related Jest coverage.
35
+ - Enabled the 10 skipped document tests for PDF read, HTML-to-PDF write, mixed document batches, and PDF round-trip paths.
36
+ - Updated Jest PDF mocks so document tests exercise meaningful content paths instead of placeholder-only buffers.
37
+ - Suppressed expected negative-path test diagnostics inside tests so successful runs no longer look like runtime failures.
38
+ - Added a regression test to prevent incompatible tool schema shapes from reappearing in future releases.
39
+
40
+ ### Changed
41
+
42
+ - Documented the Codex-specific MCP configuration format in the README alongside the JSON-based client examples.
43
+ - Updated `npx` examples to use `-y` explicitly for non-interactive client execution.
44
+
45
+ ## [1.2.12] - 2026-02-21
46
+
47
+ ### Fixed
38
48
 
39
49
  - **CRITICAL**: Fixed MCP server toggle failure and "no tools configured" error caused by Node.js version incompatibility and restrictive MCP detection.
40
50
  - **Node.js Compatibility**: Replaced `import ... with { type: "json" }` with manual `fs.readFileSync` for `package.json` to support Node.js versions earlier than 20.10.0 and 18.20.0 (including Node 14/16).
package/README.md CHANGED
@@ -124,10 +124,10 @@ This server can be used directly with npx (recommended) or installed globally/lo
124
124
 
125
125
  ### Basic Configuration
126
126
 
127
- Add to your MCP client configuration.
128
-
129
- For JSON-based clients such as Claude Desktop and Cursor, use their `mcpServers` JSON format.
130
- For Codex, use `C:\Users\<username>\.codex\config.toml` and the `mcp_servers` TOML table format shown below.
127
+ Add to your MCP client configuration.
128
+
129
+ For JSON-based clients such as Claude Desktop and Cursor, use their `mcpServers` JSON format.
130
+ For Codex, use `C:\Users\<username>\.codex\config.toml` and the `mcp_servers` TOML table format shown below.
131
131
 
132
132
  #### Option 1: Using npx (Recommended - No Installation Required)
133
133
 
@@ -135,22 +135,22 @@ For Codex, use `C:\Users\<username>\.codex\config.toml` and the `mcp_servers` TO
135
135
  {
136
136
  "mcpServers": {
137
137
  "vulcan-file-ops": {
138
- "command": "npx",
139
- "args": ["-y", "@n0zer0d4y/vulcan-file-ops"]
140
- }
141
- }
142
- }
143
- ```
144
-
145
- **Codex (`config.toml`)**
146
-
147
- ```toml
148
- [mcp_servers.vulcan_file_ops]
149
- command = "npx"
150
- args = ["-y", "@n0zer0d4y/vulcan-file-ops"]
151
- enabled = true
152
- startup_timeout_sec = 120.0
153
- ```
138
+ "command": "npx",
139
+ "args": ["-y", "@n0zer0d4y/vulcan-file-ops"]
140
+ }
141
+ }
142
+ }
143
+ ```
144
+
145
+ **Codex (`config.toml`)**
146
+
147
+ ```toml
148
+ [mcp_servers.vulcan_file_ops]
149
+ command = "npx"
150
+ args = ["-y", "@n0zer0d4y/vulcan-file-ops"]
151
+ enabled = true
152
+ startup_timeout_sec = 120.0
153
+ ```
154
154
 
155
155
  #### Option 2: Using Global Installation
156
156
 
@@ -180,7 +180,7 @@ After running `npm install @n0zer0d4y/vulcan-file-ops` in your project:
180
180
  }
181
181
  ```
182
182
 
183
- #### Option 4: Local Repository Execution (For Developers)
183
+ #### Option 4: Local Repository Execution (For Developers)
184
184
 
185
185
  If you've cloned this repository and want to run from source:
186
186
 
@@ -191,39 +191,39 @@ npm install
191
191
  npm run build
192
192
  ```
193
193
 
194
- Then configure your MCP client:
195
-
196
- ```json
197
- {
198
- "mcpServers": {
199
- "vulcan-file-ops": {
200
- "command": "node",
201
- "args": [
202
- "/absolute/path/to/vulcan-file-ops/dist/cli.js",
203
- "--approved-folders",
204
- "/path/to/your/allowed/directories"
205
- ]
206
- }
207
- }
208
- }
209
- ```
210
-
211
- **Codex (`config.toml`)**
212
-
213
- ```toml
214
- [mcp_servers.vulcan_file_ops]
215
- command = "node"
216
- args = [
217
- 'C:\absolute\path\to\vulcan-file-ops\dist\cli.js',
218
- "--approved-folders",
219
- 'C:\path\to\your\allowed\directories'
220
- ]
221
- cwd = 'C:\absolute\path\to\vulcan-file-ops'
222
- enabled = true
223
- startup_timeout_sec = 120.0
224
- ```
225
-
226
- **Note:** For local repository execution, prefer `node dist/cli.js` with an absolute path. This works reliably in Codex and avoids PATH ambiguity.
194
+ Then configure your MCP client:
195
+
196
+ ```json
197
+ {
198
+ "mcpServers": {
199
+ "vulcan-file-ops": {
200
+ "command": "node",
201
+ "args": [
202
+ "/absolute/path/to/vulcan-file-ops/dist/cli.js",
203
+ "--approved-folders",
204
+ "/path/to/your/allowed/directories"
205
+ ]
206
+ }
207
+ }
208
+ }
209
+ ```
210
+
211
+ **Codex (`config.toml`)**
212
+
213
+ ```toml
214
+ [mcp_servers.vulcan_file_ops]
215
+ command = "node"
216
+ args = [
217
+ 'C:\absolute\path\to\vulcan-file-ops\dist\cli.js',
218
+ "--approved-folders",
219
+ 'C:\path\to\your\allowed\directories'
220
+ ]
221
+ cwd = 'C:\absolute\path\to\vulcan-file-ops'
222
+ enabled = true
223
+ startup_timeout_sec = 120.0
224
+ ```
225
+
226
+ **Note:** For local repository execution, prefer `node dist/cli.js` with an absolute path. This works reliably in Codex and avoids PATH ambiguity.
227
227
 
228
228
  ### Advanced Configuration
229
229
 
@@ -237,12 +237,12 @@ Pre-configure specific directories for immediate access on server start:
237
237
  {
238
238
  "mcpServers": {
239
239
  "vulcan-file-ops": {
240
- "command": "npx",
241
- "args": [
242
- "-y",
243
- "@n0zer0d4y/vulcan-file-ops",
244
- "--approved-folders",
245
- "/Users/username/projects",
240
+ "command": "npx",
241
+ "args": [
242
+ "-y",
243
+ "@n0zer0d4y/vulcan-file-ops",
244
+ "--approved-folders",
245
+ "/Users/username/projects",
246
246
  "/Users/username/documents"
247
247
  ]
248
248
  }
@@ -256,12 +256,12 @@ Pre-configure specific directories for immediate access on server start:
256
256
  {
257
257
  "mcpServers": {
258
258
  "vulcan-file-ops": {
259
- "command": "npx",
260
- "args": [
261
- "-y",
262
- "@n0zer0d4y/vulcan-file-ops",
263
- "--approved-folders",
264
- "C:/Users/username/projects",
259
+ "command": "npx",
260
+ "args": [
261
+ "-y",
262
+ "@n0zer0d4y/vulcan-file-ops",
263
+ "--approved-folders",
264
+ "C:/Users/username/projects",
265
265
  "C:/Users/username/documents"
266
266
  ]
267
267
  }
@@ -269,7 +269,7 @@ Pre-configure specific directories for immediate access on server start:
269
269
  }
270
270
  ```
271
271
 
272
- **Alternative: Local Repository Execution**
272
+ **Alternative: Local Repository Execution**
273
273
 
274
274
  For users running from a cloned repository (after `npm run build`):
275
275
 
@@ -277,32 +277,32 @@ For users running from a cloned repository (after `npm run build`):
277
277
  {
278
278
  "mcpServers": {
279
279
  "vulcan-file-ops": {
280
- "command": "vulcan-file-ops",
281
- "args": [
282
- "--approved-folders",
283
- "/Users/username/projects",
284
- "/Users/username/documents"
280
+ "command": "vulcan-file-ops",
281
+ "args": [
282
+ "--approved-folders",
283
+ "/Users/username/projects",
284
+ "/Users/username/documents"
285
285
  ]
286
286
  }
287
287
  }
288
288
  }
289
- ```
290
-
291
- **Codex with Approved Folders (`config.toml`)**
292
-
293
- ```toml
294
- [mcp_servers.vulcan_file_ops]
295
- command = "node"
296
- args = [
297
- 'C:\absolute\path\to\vulcan-file-ops\dist\cli.js',
298
- "--approved-folders",
299
- 'C:\Users\username\projects',
300
- 'C:\Users\username\documents'
301
- ]
302
- cwd = 'C:\absolute\path\to\vulcan-file-ops'
303
- enabled = true
304
- startup_timeout_sec = 120.0
305
- ```
289
+ ```
290
+
291
+ **Codex with Approved Folders (`config.toml`)**
292
+
293
+ ```toml
294
+ [mcp_servers.vulcan_file_ops]
295
+ command = "node"
296
+ args = [
297
+ 'C:\absolute\path\to\vulcan-file-ops\dist\cli.js',
298
+ "--approved-folders",
299
+ 'C:\Users\username\projects',
300
+ 'C:\Users\username\documents'
301
+ ]
302
+ cwd = 'C:\absolute\path\to\vulcan-file-ops'
303
+ enabled = true
304
+ startup_timeout_sec = 120.0
305
+ ```
306
306
 
307
307
  **Path Format Note:**
308
308
 
@@ -16,7 +16,7 @@ if (_isMCP) {
16
16
  }
17
17
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
18
18
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
19
- import { CallToolRequestSchema, ListToolsRequestSchema, InitializeRequestSchema, PingRequestSchema, RootsListChangedNotificationSchema, } from "@modelcontextprotocol/sdk/types.js";
19
+ import { CallToolRequestSchema, ListToolsRequestSchema, PingRequestSchema, RootsListChangedNotificationSchema, } from "@modelcontextprotocol/sdk/types.js";
20
20
  import fs from "fs/promises";
21
21
  import { readFileSync } from "fs";
22
22
  import path from "path";
@@ -399,26 +399,11 @@ const server = new Server({
399
399
  // receive "Method not found" errors, and fail to enable the toggle
400
400
  },
401
401
  });
402
- // Initialize handler - required for MCP protocol
403
- server.setRequestHandler(InitializeRequestSchema, async (request) => {
404
- const clientCapabilities = request.params.capabilities;
405
- return {
406
- // CRITICAL: Return the protocol version the CLIENT requested, not LATEST
407
- // Claude Desktop only supports 2025-06-18 and will disconnect if we return 2025-11-25
408
- protocolVersion: request.params.protocolVersion,
409
- capabilities: {
410
- tools: {
411
- listChanged: true,
412
- },
413
- // CRITICAL: Do NOT declare resources or prompts - we don't implement them
414
- },
415
- serverInfo: {
416
- name: "vulcan-file-ops",
417
- version: VERSION,
418
- },
419
- instructions: generateServerDescription(),
420
- };
421
- });
402
+ // The SDK's built-in initialize handler (_oninitialize) is left in place.
403
+ // Overriding it via setRequestHandler breaks the SDK's internal state machine:
404
+ // _clientCapabilities and _clientVersion never get set, and protocol version
405
+ // negotiation is bypassed (should respond with max supported ≤ client's requested).
406
+ // Instructions are injected at runtime in runServer() after directories initialize.
422
407
  // Ping handler - for health checks
423
408
  server.setRequestHandler(PingRequestSchema, async () => {
424
409
  return {};
@@ -623,18 +608,19 @@ server.setNotificationHandler(RootsListChangedNotificationSchema, async () => {
623
608
  }
624
609
  });
625
610
  // Handles post-initialization setup, specifically checking for and fetching MCP roots.
626
- server.oninitialized = async () => {
611
+ // listRoots() is fired detached (no await) so it doesn't block the initialize handshake.
612
+ // Blocking here deadlocks: the client won't respond to roots/list until after initialize
613
+ // completes, but initialize won't complete until this callback returns.
614
+ server.oninitialized = () => {
627
615
  const clientCapabilities = server.getClientCapabilities();
628
616
  if (clientCapabilities?.roots) {
629
- try {
630
- const response = await server.listRoots();
617
+ server.listRoots().then(async (response) => {
631
618
  if (response && "roots" in response) {
632
619
  await updateAllowedDirectoriesFromRoots(response.roots);
633
620
  }
634
- }
635
- catch (error) {
621
+ }).catch(() => {
636
622
  // Silently handle errors - dynamic access will work via register_directory tool
637
- }
623
+ });
638
624
  }
639
625
  };
640
626
  // Start server
@@ -658,6 +644,10 @@ export async function runServer() {
658
644
  }
659
645
  // In MCP mode, silently continue - server can work without approved folders
660
646
  }
647
+ // Inject instructions now that directories are known. The SDK's built-in
648
+ // _oninitialize reads this._instructions when building the initialize response.
649
+ server._instructions =
650
+ generateServerDescription();
661
651
  const transport = new StdioServerTransport();
662
652
  await server.connect(transport);
663
653
  // Minimal logging to avoid issues with MCP clients
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@n0zer0d4y/vulcan-file-ops",
3
- "version": "1.2.13",
3
+ "version": "1.2.14",
4
4
  "mcpName": "io.github.n0zer0d4y/vulcan-file-ops",
5
5
  "description": "MCP server for AI assistants: read, write, edit, and manage files securely on local filesystem.",
6
6
  "license": "MIT",