@anyshift/mcp-proxy 0.2.3-dev → 0.2.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/dist/index.js CHANGED
@@ -125,7 +125,7 @@ const ENABLE_LOGGING = process.env.MCP_PROXY_ENABLE_LOGGING === 'true';
125
125
  // Validate configuration
126
126
  // CHILD_COMMAND is now optional - if not provided, proxy runs in standalone mode (JQ only)
127
127
  if (!CHILD_COMMAND) {
128
- console.error('[mcp-proxy] No child command specified - running in standalone mode (JQ only)');
128
+ console.debug('[mcp-proxy] No child command specified - running in standalone mode (JQ only)');
129
129
  if (!ENABLE_JQ) {
130
130
  console.error('ERROR: Standalone mode requires JQ to be enabled (MCP_PROXY_ENABLE_JQ must not be false)');
131
131
  process.exit(1);
@@ -168,41 +168,45 @@ for (const [key, value] of Object.entries(process.env)) {
168
168
  // CONFIGURATION SUMMARY
169
169
  // ============================================================================
170
170
  if (ENABLE_LOGGING) {
171
- console.error('[mcp-proxy] Configuration:');
172
- console.error(` Mode: ${CHILD_COMMAND ? 'wrapper' : 'standalone (JQ only)'}`);
171
+ console.debug('[mcp-proxy] Configuration:');
172
+ console.debug(` Mode: ${CHILD_COMMAND ? 'wrapper' : 'standalone (JQ only)'}`);
173
173
  if (CHILD_COMMAND) {
174
- console.error(` Child command: ${CHILD_COMMAND}`);
175
- console.error(` Child args: [${CHILD_ARGS.join(', ')}]`);
174
+ console.debug(` Child command: ${CHILD_COMMAND}`);
175
+ console.debug(` Child args: [${CHILD_ARGS.join(', ')}]`);
176
176
  }
177
- console.error(` Max tokens: ${MAX_TOKENS}`);
178
- console.error(` Chars per token: ${CHARS_PER_TOKEN}`);
179
- console.error(` Write to file: ${WRITE_TO_FILE}`);
177
+ console.debug(` Max tokens: ${MAX_TOKENS}`);
178
+ console.debug(` Chars per token: ${CHARS_PER_TOKEN}`);
179
+ console.debug(` Write to file: ${WRITE_TO_FILE}`);
180
180
  if (WRITE_TO_FILE) {
181
- console.error(` Output path: ${OUTPUT_PATH}`);
182
- console.error(` Min chars for write: ${MIN_CHARS_FOR_WRITE}`);
181
+ console.debug(` Output path: ${OUTPUT_PATH}`);
182
+ console.debug(` Min chars for write: ${MIN_CHARS_FOR_WRITE}`);
183
183
  }
184
- console.error(` JQ tool enabled: ${ENABLE_JQ}`);
184
+ console.debug(` JQ tool enabled: ${ENABLE_JQ}`);
185
185
  if (CHILD_COMMAND) {
186
- console.error(` Pass-through env vars: ${Object.keys(childEnv).length}`);
186
+ console.debug(` Pass-through env vars: ${Object.keys(childEnv).length}`);
187
187
  }
188
188
  }
189
189
  // ============================================================================
190
190
  // MAIN PROXY LOGIC
191
191
  // ============================================================================
192
192
  async function main() {
193
- console.error('[mcp-proxy] Starting generic MCP proxy...');
193
+ console.debug('[mcp-proxy] Starting generic MCP proxy...');
194
194
  // ------------------------------------------------------------------------
195
195
  // 1. SPAWN CHILD MCP SERVER (if configured)
196
196
  // ------------------------------------------------------------------------
197
197
  let childClient = null;
198
198
  let childToolsResponse = { tools: [] };
199
199
  if (CHILD_COMMAND) {
200
- console.error(`[mcp-proxy] Spawning child MCP: ${CHILD_COMMAND}`);
200
+ console.debug(`[mcp-proxy] Spawning child MCP: ${CHILD_COMMAND}`);
201
201
  const childTransport = new StdioClientTransport({
202
202
  command: CHILD_COMMAND,
203
203
  args: CHILD_ARGS,
204
204
  env: childEnv // All values are defined strings (filtered in extraction loop)
205
205
  });
206
+ // Log errors instead of crashing silently
207
+ childTransport.onerror = (error) => {
208
+ console.error('[mcp-proxy] Child error:', error.message);
209
+ };
206
210
  childClient = new Client({
207
211
  name: 'mcp-proxy-client',
208
212
  version: '1.0.0'
@@ -210,15 +214,17 @@ async function main() {
210
214
  capabilities: {}
211
215
  });
212
216
  await childClient.connect(childTransport);
213
- console.error('[mcp-proxy] Connected to child MCP');
217
+ console.debug('[mcp-proxy] Connected to child MCP');
218
+ // Give child 50ms to stabilize before making requests
219
+ await new Promise(resolve => setTimeout(resolve, 50));
214
220
  // ------------------------------------------------------------------------
215
221
  // 2. DISCOVER TOOLS FROM CHILD MCP
216
222
  // ------------------------------------------------------------------------
217
223
  childToolsResponse = await childClient.listTools();
218
- console.error(`[mcp-proxy] Discovered ${childToolsResponse.tools.length} tools from child MCP`);
224
+ console.debug(`[mcp-proxy] Discovered ${childToolsResponse.tools.length} tools from child MCP`);
219
225
  }
220
226
  else {
221
- console.error('[mcp-proxy] Standalone mode - no child MCP');
227
+ console.debug('[mcp-proxy] Standalone mode - no child MCP');
222
228
  }
223
229
  // ------------------------------------------------------------------------
224
230
  // 3. CREATE PROXY SERVER
@@ -267,7 +273,7 @@ async function main() {
267
273
  ...childToolsResponse.tools,
268
274
  ...(jqTool ? [jqTool.toolDefinition] : [])
269
275
  ];
270
- console.error(`[mcp-proxy] Exposing ${allTools.length} tools total (${childToolsResponse.tools.length} from child${jqTool ? ' + 1 JQ' : ''})`);
276
+ console.debug(`[mcp-proxy] Exposing ${allTools.length} tools total (${childToolsResponse.tools.length} from child${jqTool ? ' + 1 JQ' : ''})`);
271
277
  // ------------------------------------------------------------------------
272
278
  // 6. HANDLE TOOL LIST REQUESTS
273
279
  // ------------------------------------------------------------------------
@@ -281,14 +287,14 @@ async function main() {
281
287
  const toolName = request.params.name;
282
288
  const toolArgs = request.params.arguments || {};
283
289
  if (ENABLE_LOGGING) {
284
- console.error(`[mcp-proxy] Tool call: ${toolName}`);
290
+ console.debug(`[mcp-proxy] Tool call: ${toolName}`);
285
291
  }
286
292
  try {
287
293
  let result;
288
294
  // Handle JQ tool locally (if enabled)
289
295
  if (toolName === 'execute_jq_query' && jqTool) {
290
296
  if (ENABLE_LOGGING) {
291
- console.error('[mcp-proxy] Executing JQ tool locally');
297
+ console.debug('[mcp-proxy] Executing JQ tool locally');
292
298
  }
293
299
  result = await jqTool.handler({
294
300
  params: { arguments: toolArgs }
@@ -306,7 +312,7 @@ async function main() {
306
312
  };
307
313
  }
308
314
  if (ENABLE_LOGGING) {
309
- console.error(`[mcp-proxy] Forwarding to child MCP: ${toolName}`);
315
+ console.debug(`[mcp-proxy] Forwarding to child MCP: ${toolName}`);
310
316
  }
311
317
  result = await childClient.callTool({
312
318
  name: toolName,
@@ -336,7 +342,7 @@ async function main() {
336
342
  item.text = resultText;
337
343
  fileWasWritten = true;
338
344
  if (ENABLE_LOGGING) {
339
- console.error(`[mcp-proxy] File writing applied for ${toolName} (${originalLength} chars written to file)`);
345
+ console.debug(`[mcp-proxy] File writing applied for ${toolName} (${originalLength} chars written to file)`);
340
346
  }
341
347
  }
342
348
  }
@@ -346,7 +352,7 @@ async function main() {
346
352
  if (!fileWasWritten) {
347
353
  item.text = truncateResponseIfNeeded(truncationConfig, item.text);
348
354
  if (item.text.length < originalLength && ENABLE_LOGGING) {
349
- console.error(`[mcp-proxy] Truncated response: ${originalLength} → ${item.text.length} chars`);
355
+ console.debug(`[mcp-proxy] Truncated response: ${originalLength} → ${item.text.length} chars`);
350
356
  }
351
357
  }
352
358
  }
@@ -370,8 +376,10 @@ async function main() {
370
376
  // ------------------------------------------------------------------------
371
377
  const transport = new StdioServerTransport();
372
378
  await server.connect(transport);
373
- console.error('[mcp-proxy] Proxy server ready on stdio');
374
- console.error('[mcp-proxy] Waiting for MCP protocol messages...');
379
+ console.debug('[mcp-proxy] Proxy server ready on stdio');
380
+ console.debug('[mcp-proxy] Waiting for MCP protocol messages...');
381
+ // Prevent EPIPE from crashing the process
382
+ process.on('SIGPIPE', () => { });
375
383
  }
376
384
  // ============================================================================
377
385
  // START THE PROXY
@@ -32,7 +32,7 @@ export const validatePathWithinAllowedDirs = (filePath, allowedPaths) => {
32
32
  const allowedPathReal = realpathSync(path.resolve(allowedPath));
33
33
  // Check if the real path is within this allowed directory
34
34
  if (realPath.startsWith(allowedPathReal + path.sep) || realPath === allowedPathReal) {
35
- console.error(`[validatePathWithinAllowedDirs] Path allowed (within ${allowedPathReal}): ${realPath}`);
35
+ console.debug(`[validatePathWithinAllowedDirs] Path allowed (within ${allowedPathReal}): ${realPath}`);
36
36
  return realPath;
37
37
  }
38
38
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anyshift/mcp-proxy",
3
- "version": "0.2.3-dev",
3
+ "version": "0.2.3",
4
4
  "description": "Generic MCP proxy that adds truncation, file writing, and JQ capabilities to any MCP server",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",