@n0zer0d4y/vulcan-file-ops 1.2.4 → 1.2.5
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/dist/cli.js +7 -2
- package/dist/server/index.js +38 -27
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
// CRITICAL: Detect MCP mode and suppress console output BEFORE any imports
|
|
3
3
|
// MCP servers use stdin/stdout for JSON-RPC via stdio transport
|
|
4
4
|
// Detection: stdin/stdout are NOT TTY (piped/redirected) = MCP mode
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
//
|
|
6
|
+
// EXCEPTION: --help and --version flags should always output to console
|
|
7
|
+
// even when stdin/stdout are piped (e.g., in scripts or CI environments)
|
|
8
|
+
const isHelpOrVersion = process.argv.some((arg) => arg === "--help" || arg === "-h" || arg === "--version" || arg === "-v");
|
|
9
|
+
const isMCP = !isHelpOrVersion &&
|
|
10
|
+
((!process.stdin.isTTY && !process.stdout.isTTY) ||
|
|
11
|
+
process.argv.some((arg) => arg.includes("mcp") || arg.includes("stdio")));
|
|
7
12
|
if (isMCP) {
|
|
8
13
|
// Suppress all console methods (but NOT stdout/stderr streams - MCP SDK needs those)
|
|
9
14
|
const noop = () => { };
|
package/dist/server/index.js
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
// CRITICAL: Suppress console output IMMEDIATELY, before any imports
|
|
3
|
+
// This MUST be the first executable code due to ES Module execution order.
|
|
4
|
+
// With static imports, child modules are evaluated BEFORE the importing
|
|
5
|
+
// module's top-level code runs. By placing suppression here at the very top
|
|
6
|
+
// of the main server module, we ensure no console output can corrupt the
|
|
7
|
+
// MCP JSON-RPC protocol stream on stdout.
|
|
8
|
+
// See: RCA-Claude-Desktop-MCP-Toggle-Failure-2026-01-31.md
|
|
9
|
+
// Check for CLI info flags BEFORE suppression - these should always work
|
|
10
|
+
const _isHelpOrVersion = process.argv.some((arg) => arg === "--help" || arg === "-h" || arg === "--version" || arg === "-v");
|
|
11
|
+
const _mcpMode = !_isHelpOrVersion &&
|
|
12
|
+
((!process.stdin.isTTY && !process.stdout.isTTY) ||
|
|
13
|
+
process.argv.some((arg) => arg.includes("mcp") || arg.includes("stdio")));
|
|
14
|
+
if (_mcpMode) {
|
|
15
|
+
const noop = () => { };
|
|
16
|
+
console.log = noop;
|
|
17
|
+
console.error = noop;
|
|
18
|
+
console.warn = noop;
|
|
19
|
+
console.info = noop;
|
|
20
|
+
console.debug = noop;
|
|
21
|
+
}
|
|
2
22
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
23
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
24
|
import { CallToolRequestSchema, ListToolsRequestSchema, InitializeRequestSchema, PingRequestSchema, RootsListChangedNotificationSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
@@ -183,22 +203,13 @@ function parseArguments() {
|
|
|
183
203
|
}
|
|
184
204
|
return directories;
|
|
185
205
|
}
|
|
186
|
-
|
|
206
|
+
// Defer parseArguments() call to runServer() to avoid module-level side effects
|
|
207
|
+
let directoryArgs = [];
|
|
187
208
|
// Async initialization function to be called in runServer()
|
|
188
209
|
async function initializeDirectories() {
|
|
189
|
-
//
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// During MCP operation, suppress ALL console output to prevent protocol corruption
|
|
193
|
-
if (isMCP) {
|
|
194
|
-
const noop = () => { };
|
|
195
|
-
console.error = noop;
|
|
196
|
-
console.log = noop;
|
|
197
|
-
console.warn = noop;
|
|
198
|
-
console.info = noop;
|
|
199
|
-
console.debug = noop;
|
|
200
|
-
}
|
|
201
|
-
if (!isMCP &&
|
|
210
|
+
// Use the already-determined MCP mode from top of file
|
|
211
|
+
// Console suppression is already done at module load time via _mcpMode
|
|
212
|
+
if (!_mcpMode &&
|
|
202
213
|
(approvedFoldersFromArgs.length > 0 ||
|
|
203
214
|
directoryArgs.length > 0 ||
|
|
204
215
|
ignoredFolders.length > 0 ||
|
|
@@ -248,7 +259,7 @@ async function initializeDirectories() {
|
|
|
248
259
|
const errorMsg = `Error: Approved folder ${dir} is not a directory`;
|
|
249
260
|
console.error(errorMsg);
|
|
250
261
|
// In MCP mode, don't exit - just skip invalid directories
|
|
251
|
-
if (!
|
|
262
|
+
if (!_mcpMode) {
|
|
252
263
|
process.exit(1);
|
|
253
264
|
}
|
|
254
265
|
}
|
|
@@ -257,13 +268,13 @@ async function initializeDirectories() {
|
|
|
257
268
|
const errorMsg = `Error accessing approved folder ${dir}: ${error}`;
|
|
258
269
|
console.error(errorMsg);
|
|
259
270
|
// In MCP mode, don't exit - just skip invalid directories
|
|
260
|
-
if (!
|
|
271
|
+
if (!_mcpMode) {
|
|
261
272
|
process.exit(1);
|
|
262
273
|
}
|
|
263
274
|
}
|
|
264
275
|
}));
|
|
265
276
|
// Only log initialization if not running under MCP
|
|
266
|
-
if (!
|
|
277
|
+
if (!_mcpMode) {
|
|
267
278
|
console.error(`Initialized with ${allowedDirectories.length} approved ${allowedDirectories.length === 1 ? "directory" : "directories"}`);
|
|
268
279
|
}
|
|
269
280
|
}
|
|
@@ -291,7 +302,7 @@ async function initializeDirectories() {
|
|
|
291
302
|
const errorMsg = `Error: Legacy directory ${dir} is not a directory`;
|
|
292
303
|
console.error(errorMsg);
|
|
293
304
|
// In MCP mode, don't exit - just skip invalid directories
|
|
294
|
-
if (!
|
|
305
|
+
if (!_mcpMode) {
|
|
295
306
|
process.exit(1);
|
|
296
307
|
}
|
|
297
308
|
}
|
|
@@ -300,7 +311,7 @@ async function initializeDirectories() {
|
|
|
300
311
|
const errorMsg = `Error accessing legacy directory ${dir}: ${error}`;
|
|
301
312
|
console.error(errorMsg);
|
|
302
313
|
// In MCP mode, don't exit - just skip invalid directories
|
|
303
|
-
if (!
|
|
314
|
+
if (!_mcpMode) {
|
|
304
315
|
process.exit(1);
|
|
305
316
|
}
|
|
306
317
|
}
|
|
@@ -322,7 +333,7 @@ async function initializeDirectories() {
|
|
|
322
333
|
// Priority 1: --approved-commands from CLI (supersedes .env)
|
|
323
334
|
if (approvedCommandsFromArgs.length > 0) {
|
|
324
335
|
finalApprovedCommands = approvedCommandsFromArgs;
|
|
325
|
-
if (!
|
|
336
|
+
if (!_mcpMode) {
|
|
326
337
|
console.error(` Approved commands (from CLI): ${finalApprovedCommands.join(", ")}`);
|
|
327
338
|
}
|
|
328
339
|
}
|
|
@@ -335,13 +346,13 @@ async function initializeDirectories() {
|
|
|
335
346
|
finalApprovedCommands = process.env.APPROVED_COMMANDS.split(",")
|
|
336
347
|
.map((c) => c.trim())
|
|
337
348
|
.filter((c) => c.length > 0);
|
|
338
|
-
if (!
|
|
349
|
+
if (!_mcpMode) {
|
|
339
350
|
console.error(` Approved commands (from .env): ${finalApprovedCommands.join(", ")}`);
|
|
340
351
|
}
|
|
341
352
|
}
|
|
342
353
|
}
|
|
343
354
|
catch (error) {
|
|
344
|
-
if (!
|
|
355
|
+
if (!_mcpMode) {
|
|
345
356
|
console.error(" Note: Could not load .env file (this is okay if using CLI args)");
|
|
346
357
|
}
|
|
347
358
|
}
|
|
@@ -349,14 +360,14 @@ async function initializeDirectories() {
|
|
|
349
360
|
// Initialize shell tool with approved commands
|
|
350
361
|
if (finalApprovedCommands.length > 0) {
|
|
351
362
|
initializeShellTool(finalApprovedCommands);
|
|
352
|
-
if (!
|
|
363
|
+
if (!_mcpMode) {
|
|
353
364
|
console.error(`Initialized shell tool with ${finalApprovedCommands.length} approved command(s)`);
|
|
354
365
|
}
|
|
355
366
|
}
|
|
356
367
|
else {
|
|
357
368
|
initializeShellTool([]);
|
|
358
369
|
// Only log shell initialization if not running under MCP
|
|
359
|
-
if (!
|
|
370
|
+
if (!_mcpMode) {
|
|
360
371
|
console.error("Shell tool initialized with no pre-approved commands (all commands require approval)");
|
|
361
372
|
}
|
|
362
373
|
}
|
|
@@ -625,6 +636,8 @@ server.oninitialized = async () => {
|
|
|
625
636
|
};
|
|
626
637
|
// Start server
|
|
627
638
|
export async function runServer() {
|
|
639
|
+
// Parse arguments here (not at module level) to ensure console suppression is active
|
|
640
|
+
directoryArgs = parseArguments();
|
|
628
641
|
// Initialize directories before starting server
|
|
629
642
|
// BUT: Don't exit on errors during MCP mode - just log and continue
|
|
630
643
|
try {
|
|
@@ -633,9 +646,7 @@ export async function runServer() {
|
|
|
633
646
|
catch (error) {
|
|
634
647
|
// In MCP mode, don't crash the server on init errors
|
|
635
648
|
// Just continue with empty configuration
|
|
636
|
-
|
|
637
|
-
process.argv.some((arg) => arg.includes("mcp") || arg.includes("stdio"));
|
|
638
|
-
if (!isMCP) {
|
|
649
|
+
if (!_mcpMode) {
|
|
639
650
|
// In non-MCP mode, we can show errors and exit
|
|
640
651
|
throw error;
|
|
641
652
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@n0zer0d4y/vulcan-file-ops",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
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",
|