@meldocio/mcp-stdio-proxy 1.0.0 → 1.0.1

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.
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const axios = require('axios');
4
+ const https = require('https');
4
5
  const { URL } = require('url');
5
6
 
6
7
  // JSON-RPC error codes
@@ -40,8 +41,10 @@ process.stdin.on('data', (chunk) => {
40
41
 
41
42
  // Process complete lines
42
43
  for (const line of lines) {
43
- if (line.trim()) {
44
- handleLine(line.trim());
44
+ const trimmed = line.trim();
45
+ // Skip empty lines but don't exit
46
+ if (trimmed) {
47
+ handleLine(trimmed);
45
48
  }
46
49
  }
47
50
  });
@@ -52,18 +55,33 @@ process.stdin.on('end', () => {
52
55
  if (buffer.trim()) {
53
56
  handleLine(buffer.trim());
54
57
  }
58
+ // Don't exit - Claude Desktop may reconnect
59
+ // The process will be terminated by Claude Desktop when needed
55
60
  });
56
61
 
57
- // Handle errors
62
+ // Handle errors - don't exit, just log
58
63
  process.stdin.on('error', (error) => {
59
- sendError(null, JSON_RPC_ERROR_CODES.INTERNAL_ERROR, `Input error: ${error.message}`);
60
- process.exit(1);
64
+ // Log to stderr but don't exit - Claude Desktop may close stdin
65
+ // Silently handle stdin errors - they're normal when Claude Desktop closes the connection
66
+ });
67
+
68
+ // Handle stdout errors
69
+ process.stdout.on('error', (error) => {
70
+ // If stdout is closed (e.g., Claude Desktop disconnected), exit gracefully
71
+ if (error.code === 'EPIPE') {
72
+ process.exit(0);
73
+ }
61
74
  });
62
75
 
63
76
  /**
64
77
  * Handle a single line from stdin
65
78
  */
66
79
  function handleLine(line) {
80
+ // Skip empty lines
81
+ if (!line || !line.trim()) {
82
+ return;
83
+ }
84
+
67
85
  try {
68
86
  const request = JSON.parse(line);
69
87
  handleRequest(request);
@@ -81,11 +99,14 @@ function validateRequest(request) {
81
99
  return { valid: false, error: 'Request must be an object' };
82
100
  }
83
101
 
84
- if (request.jsonrpc !== '2.0') {
102
+ // Allow requests without jsonrpc for compatibility (some MCP clients may omit it)
103
+ if (request.jsonrpc && request.jsonrpc !== '2.0') {
85
104
  return { valid: false, error: 'jsonrpc must be "2.0"' };
86
105
  }
87
106
 
88
- if (!request.method && !Array.isArray(request)) {
107
+ // Allow requests without method if they're notifications (id is null/undefined)
108
+ // But batch requests must be arrays
109
+ if (!request.method && !Array.isArray(request) && request.id !== null && request.id !== undefined) {
89
110
  return { valid: false, error: 'Request must have a method or be a batch array' };
90
111
  }
91
112
 
@@ -96,6 +117,11 @@ function validateRequest(request) {
96
117
  * Handle a JSON-RPC request
97
118
  */
98
119
  async function handleRequest(request) {
120
+ // Handle null/undefined requests
121
+ if (!request) {
122
+ return;
123
+ }
124
+
99
125
  // Handle batch requests (array of requests)
100
126
  if (Array.isArray(request)) {
101
127
  // Process batch requests sequentially
@@ -122,14 +148,23 @@ async function handleRequest(request) {
122
148
  */
123
149
  async function processSingleRequest(request) {
124
150
  try {
151
+ // Ensure request has jsonrpc field
152
+ const requestWithJsonRpc = {
153
+ ...request,
154
+ jsonrpc: request.jsonrpc || '2.0'
155
+ };
156
+
125
157
  // Make HTTP request to MCP API
126
- const response = await axios.post(rpcEndpoint, request, {
158
+ const response = await axios.post(rpcEndpoint, requestWithJsonRpc, {
127
159
  headers: {
128
160
  'Authorization': `Bearer ${token}`,
129
- 'Content-Type': 'application/json'
161
+ 'Content-Type': 'application/json',
162
+ 'User-Agent': '@meldocio/mcp-stdio-proxy/1.0.0'
130
163
  },
131
164
  timeout: REQUEST_TIMEOUT,
132
- validateStatus: (status) => status < 500 // Don't throw on 4xx errors
165
+ validateStatus: (status) => status < 500, // Don't throw on 4xx errors
166
+ // Keep connection alive for better performance
167
+ httpsAgent: new https.Agent({ keepAlive: true, keepAliveMsecs: 1000 })
133
168
  });
134
169
 
135
170
  // Handle successful response
@@ -146,7 +181,12 @@ async function processSingleRequest(request) {
146
181
  }
147
182
  }
148
183
 
184
+ // Ensure stdout is flushed immediately
149
185
  process.stdout.write(JSON.stringify(responseData) + '\n');
186
+ // Flush stdout to ensure data is sent immediately
187
+ if (process.stdout.isTTY) {
188
+ process.stdout.flush();
189
+ }
150
190
  } else {
151
191
  // HTTP error status
152
192
  const errorMessage = response.data?.error?.message ||
@@ -202,4 +242,8 @@ function sendError(id, code, message) {
202
242
  };
203
243
 
204
244
  process.stdout.write(JSON.stringify(errorResponse) + '\n');
245
+ // Flush stdout to ensure data is sent immediately
246
+ if (process.stdout.isTTY) {
247
+ process.stdout.flush();
248
+ }
205
249
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meldocio/mcp-stdio-proxy",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "MCP stdio proxy for meldoc - connects Claude Desktop to meldoc MCP API",
5
5
  "main": "bin/meldoc-mcp-proxy.js",
6
6
  "bin": {
@@ -46,4 +46,4 @@
46
46
  "bin/**/*.js"
47
47
  ]
48
48
  }
49
- }
49
+ }