@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.
- package/bin/meldoc-mcp-proxy.js +117 -5
- package/package.json +1 -1
package/bin/meldoc-mcp-proxy.js
CHANGED
|
@@ -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 =
|
|
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 -
|
|
90
|
-
|
|
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
|
-
|
|
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
|
|
349
|
+
id: id,
|
|
238
350
|
error: {
|
|
239
351
|
code: code,
|
|
240
352
|
message: message
|