reportdash-datastore-mcp-claude-desktop 1.0.10 ā 1.0.12
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/index.js +58 -45
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -19,7 +19,7 @@ if (!API_KEY) {
|
|
|
19
19
|
error: {
|
|
20
20
|
code: -32600,
|
|
21
21
|
message:
|
|
22
|
-
'REPORTDASH_API_KEY environment variable is required. Get your API key from ReportDash DataStore
|
|
22
|
+
'REPORTDASH_API_KEY environment variable is required. Get your API key from ReportDash DataStore > Destinations > API Access.',
|
|
23
23
|
},
|
|
24
24
|
id: null,
|
|
25
25
|
}) + '\n'
|
|
@@ -100,6 +100,9 @@ function forwardToAPI(mcpRequest) {
|
|
|
100
100
|
|
|
101
101
|
const body = JSON.stringify(mcpRequest);
|
|
102
102
|
|
|
103
|
+
const hasId = mcpRequest && Object.prototype.hasOwnProperty.call(mcpRequest, 'id');
|
|
104
|
+
const reqId = hasId ? mcpRequest.id : undefined;
|
|
105
|
+
|
|
103
106
|
const options = {
|
|
104
107
|
hostname: url.hostname,
|
|
105
108
|
port: url.port || (isHttps ? 443 : 80),
|
|
@@ -118,82 +121,91 @@ function forwardToAPI(mcpRequest) {
|
|
|
118
121
|
let data = '';
|
|
119
122
|
res.on('data', (chunk) => (data += chunk));
|
|
120
123
|
res.on('end', () => {
|
|
121
|
-
|
|
124
|
+
// Notifications MUST NOT get responses
|
|
125
|
+
if (!hasId) return;
|
|
122
126
|
|
|
123
|
-
// 204
|
|
127
|
+
// 204 / empty => empty result
|
|
124
128
|
if (res.statusCode === 204 || !data.trim()) {
|
|
125
129
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
126
|
-
|
|
130
|
+
process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: reqId, result: {} }) + '\n');
|
|
127
131
|
} else {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
message: `API error: ${res.statusCode} (empty body)
|
|
133
|
-
})
|
|
132
|
+
process.stdout.write(
|
|
133
|
+
JSON.stringify({
|
|
134
|
+
jsonrpc: '2.0',
|
|
135
|
+
id: reqId,
|
|
136
|
+
error: { code: res.statusCode, message: `API error: ${res.statusCode} (empty body)` },
|
|
137
|
+
}) + '\n'
|
|
134
138
|
);
|
|
135
139
|
}
|
|
136
140
|
return;
|
|
137
141
|
}
|
|
138
142
|
|
|
139
|
-
// Always re-serialize to 1-line JSON for MCP framing
|
|
140
143
|
let parsed;
|
|
141
144
|
try {
|
|
142
145
|
parsed = JSON.parse(data);
|
|
143
146
|
} catch (e) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
147
|
+
process.stdout.write(
|
|
148
|
+
JSON.stringify({
|
|
149
|
+
jsonrpc: '2.0',
|
|
150
|
+
id: reqId,
|
|
151
|
+
error: {
|
|
152
|
+
code: -32603,
|
|
153
|
+
message: 'API returned non-JSON response',
|
|
154
|
+
data: { statusCode: res.statusCode, body: data },
|
|
155
|
+
},
|
|
156
|
+
}) + '\n'
|
|
151
157
|
);
|
|
152
158
|
return;
|
|
153
159
|
}
|
|
154
160
|
|
|
161
|
+
// Success
|
|
155
162
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
156
|
-
//
|
|
157
|
-
// If it returns something else, wrap it.
|
|
163
|
+
// If backend returned a JSON-RPC object, enforce id
|
|
158
164
|
if (parsed && typeof parsed === 'object' && parsed.jsonrpc === '2.0') {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
165
|
+
if (!Object.prototype.hasOwnProperty.call(parsed, 'id')) parsed.id = reqId;
|
|
166
|
+
// IMPORTANT: never allow null id
|
|
167
|
+
if (parsed.id === null) parsed.id = reqId;
|
|
168
|
+
process.stdout.write(JSON.stringify(parsed) + '\n');
|
|
162
169
|
} else {
|
|
163
|
-
|
|
170
|
+
process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: reqId, result: parsed }) + '\n');
|
|
164
171
|
}
|
|
165
172
|
} else {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
+
// Error
|
|
174
|
+
process.stdout.write(
|
|
175
|
+
JSON.stringify({
|
|
176
|
+
jsonrpc: '2.0',
|
|
177
|
+
id: reqId,
|
|
178
|
+
error: {
|
|
179
|
+
code: res.statusCode,
|
|
180
|
+
message: `API error: ${res.statusCode}`,
|
|
181
|
+
data: parsed,
|
|
182
|
+
},
|
|
183
|
+
}) + '\n'
|
|
173
184
|
);
|
|
174
185
|
}
|
|
175
186
|
});
|
|
176
187
|
});
|
|
177
188
|
|
|
178
189
|
req.on('error', (error) => {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
})
|
|
190
|
+
if (!hasId) return; // notification: no response
|
|
191
|
+
process.stdout.write(
|
|
192
|
+
JSON.stringify({
|
|
193
|
+
jsonrpc: '2.0',
|
|
194
|
+
id: reqId,
|
|
195
|
+
error: { code: -32603, message: 'Network error: ' + error.message },
|
|
196
|
+
}) + '\n'
|
|
186
197
|
);
|
|
187
198
|
});
|
|
188
199
|
|
|
189
200
|
req.on('timeout', () => {
|
|
190
201
|
req.destroy();
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
202
|
+
if (!hasId) return; // notification: no response
|
|
203
|
+
process.stdout.write(
|
|
204
|
+
JSON.stringify({
|
|
205
|
+
jsonrpc: '2.0',
|
|
206
|
+
id: reqId,
|
|
207
|
+
error: { code: -32603, message: 'Request timeout after 30 seconds' },
|
|
208
|
+
}) + '\n'
|
|
197
209
|
);
|
|
198
210
|
});
|
|
199
211
|
|
|
@@ -201,6 +213,7 @@ function forwardToAPI(mcpRequest) {
|
|
|
201
213
|
req.end();
|
|
202
214
|
}
|
|
203
215
|
|
|
216
|
+
|
|
204
217
|
function testConnection() {
|
|
205
218
|
console.log('š Testing ReportDash DataStore connection...\n');
|
|
206
219
|
console.log(`API URL: ${API_URL}`);
|
|
@@ -277,7 +290,7 @@ function testConnection() {
|
|
|
277
290
|
console.log('ā Connection failed');
|
|
278
291
|
console.log(`Status: ${res.statusCode}`);
|
|
279
292
|
console.log(`Response: ${data}`);
|
|
280
|
-
console.log('\nš” Check your API key in ReportDash DataStore
|
|
293
|
+
console.log('\nš” Check your API key in ReportDash DataStore > Destinations > API Access');
|
|
281
294
|
}
|
|
282
295
|
});
|
|
283
296
|
});
|