@meldocio/mcp-stdio-proxy 1.0.1 → 1.0.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.
@@ -18,7 +18,7 @@ const JSON_RPC_ERROR_CODES = {
18
18
  const token = process.env.MELDOC_MCP_TOKEN;
19
19
  const apiUrl = process.env.MELDOC_API_URL || 'https://api.meldoc.io';
20
20
  const rpcEndpoint = `${apiUrl}/mcp/v1/rpc`;
21
- const REQUEST_TIMEOUT = 30000; // 30 seconds
21
+ const REQUEST_TIMEOUT = 25000; // 25 seconds (less than Claude Desktop's 30s timeout)
22
22
 
23
23
  // Validate token
24
24
  if (!token) {
@@ -86,8 +86,11 @@ function handleLine(line) {
86
86
  const request = JSON.parse(line);
87
87
  handleRequest(request);
88
88
  } catch (parseError) {
89
- // Invalid JSON - send parse error
90
- sendError(null, JSON_RPC_ERROR_CODES.PARSE_ERROR, `Parse error: ${parseError.message}`);
89
+ // Invalid JSON - try to extract id from the raw line if possible
90
+ // For parse errors, we can't reliably get the id, so we skip the response
91
+ // to avoid Zod validation errors in Claude Desktop (it doesn't accept id: null)
92
+ // This is acceptable per JSON-RPC spec - parse errors can be ignored if id is unknown
93
+ console.error(`Parse error: ${parseError.message}`, { to: 'stderr' });
91
94
  }
92
95
  }
93
96
 
@@ -127,7 +130,24 @@ async function handleRequest(request) {
127
130
  // Process batch requests sequentially
128
131
  for (const req of request) {
129
132
  if (req) {
130
- await processSingleRequest(req);
133
+ // Check if this is a protocol method that should be handled locally
134
+ const method = req.method;
135
+ if (method === 'initialize') {
136
+ handleInitialize(req);
137
+ } else if (method === 'initialized' || method === 'notifications/initialized') {
138
+ // Notification - no response needed
139
+ continue;
140
+ } else if (method === 'notifications/cancelled') {
141
+ // Notification - no response needed
142
+ continue;
143
+ } else if (method === 'ping') {
144
+ handlePing(req);
145
+ } else if (method === 'resources/list') {
146
+ handleResourcesList(req);
147
+ } else {
148
+ // Forward to backend
149
+ await processSingleRequest(req);
150
+ }
131
151
  }
132
152
  }
133
153
  return;
@@ -140,11 +160,95 @@ async function handleRequest(request) {
140
160
  return;
141
161
  }
142
162
 
163
+ // Handle MCP protocol methods locally (not forwarded to backend)
164
+ const method = request.method;
165
+ if (method === 'initialize') {
166
+ handleInitialize(request);
167
+ return;
168
+ } else if (method === 'initialized' || method === 'notifications/initialized') {
169
+ // Notification - no response needed per MCP spec
170
+ return;
171
+ } else if (method === 'notifications/cancelled') {
172
+ // Notification - no response needed
173
+ return;
174
+ } else if (method === 'ping') {
175
+ handlePing(request);
176
+ return;
177
+ } else if (method === 'resources/list') {
178
+ // Return empty resources list (resources not supported yet)
179
+ handleResourcesList(request);
180
+ return;
181
+ }
182
+
183
+ // All other methods (tools/*, etc.) are forwarded to backend
143
184
  await processSingleRequest(request);
144
185
  }
145
186
 
187
+ /**
188
+ * Handle MCP initialize method
189
+ * This is called by Claude Desktop to establish the connection
190
+ */
191
+ function handleInitialize(request) {
192
+ const response = {
193
+ jsonrpc: '2.0',
194
+ id: request.id,
195
+ result: {
196
+ protocolVersion: '2025-06-18',
197
+ capabilities: {
198
+ tools: {},
199
+ resources: {}
200
+ },
201
+ serverInfo: {
202
+ name: '@meldocio/mcp-stdio-proxy',
203
+ version: '1.0.2'
204
+ }
205
+ }
206
+ };
207
+
208
+ process.stdout.write(JSON.stringify(response) + '\n');
209
+ if (process.stdout.isTTY) {
210
+ process.stdout.flush();
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Handle MCP ping method (keep-alive)
216
+ */
217
+ function handlePing(request) {
218
+ const response = {
219
+ jsonrpc: '2.0',
220
+ id: request.id,
221
+ result: {}
222
+ };
223
+
224
+ process.stdout.write(JSON.stringify(response) + '\n');
225
+ if (process.stdout.isTTY) {
226
+ process.stdout.flush();
227
+ }
228
+ }
229
+
230
+ /**
231
+ * Handle resources/list method
232
+ * Returns empty list as resources are not supported yet
233
+ */
234
+ function handleResourcesList(request) {
235
+ const response = {
236
+ jsonrpc: '2.0',
237
+ id: request.id,
238
+ result: {
239
+ resources: []
240
+ }
241
+ };
242
+
243
+ process.stdout.write(JSON.stringify(response) + '\n');
244
+ if (process.stdout.isTTY) {
245
+ process.stdout.flush();
246
+ }
247
+ }
248
+
146
249
  /**
147
250
  * Process a single JSON-RPC request
251
+ * Forwards the request to the backend MCP API
148
252
  */
149
253
  async function processSingleRequest(request) {
150
254
  try {
@@ -232,9 +336,17 @@ async function processSingleRequest(request) {
232
336
  * Send JSON-RPC error response
233
337
  */
234
338
  function sendError(id, code, message) {
339
+ // Only send error response if id is defined (not for notifications)
340
+ // Claude Desktop's Zod schema doesn't accept null for id
341
+ if (id === undefined || id === null) {
342
+ // For notifications or parse errors without id, don't send response
343
+ // or send without id field
344
+ return;
345
+ }
346
+
235
347
  const errorResponse = {
236
348
  jsonrpc: '2.0',
237
- id: id !== undefined ? id : null,
349
+ id: id,
238
350
  error: {
239
351
  code: code,
240
352
  message: message
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meldocio/mcp-stdio-proxy",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
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": {