reportdash-datastore-mcp-claude-desktop 1.0.8 → 1.0.9
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 +85 -60
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
//goto folder, increment version then run > npm publish --access public
|
|
2
|
+
// goto folder, increment version then run > npm publish --access public
|
|
3
3
|
|
|
4
4
|
const https = require('https');
|
|
5
5
|
const http = require('http');
|
|
@@ -12,13 +12,18 @@ const API_URL = process.env.REPORTDASH_API_URL || 'https://datastore.reportdash.
|
|
|
12
12
|
|
|
13
13
|
// Validate configuration
|
|
14
14
|
if (!API_KEY) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
// NOTE: In MCP stdio mode, prefer stdout only.
|
|
16
|
+
// But keeping your original behavior as-is.
|
|
17
|
+
console.error(
|
|
18
|
+
JSON.stringify({
|
|
19
|
+
jsonrpc: '2.0',
|
|
20
|
+
error: {
|
|
21
|
+
code: -32600,
|
|
22
|
+
message:
|
|
23
|
+
'REPORTDASH_API_KEY environment variable is required. Get your API key from ReportDash DataStore app settings.',
|
|
24
|
+
},
|
|
25
|
+
})
|
|
26
|
+
);
|
|
22
27
|
process.exit(1);
|
|
23
28
|
}
|
|
24
29
|
|
|
@@ -27,13 +32,20 @@ if (!API_KEY) {
|
|
|
27
32
|
* without breaking existing requests.
|
|
28
33
|
*/
|
|
29
34
|
function withClaudePlatform(mcpRequest) {
|
|
30
|
-
// If caller already provided platform, keep it.
|
|
31
35
|
if (mcpRequest && typeof mcpRequest === 'object') {
|
|
32
|
-
if (
|
|
36
|
+
if (mcpRequest.platform == null) mcpRequest.platform = 'claude';
|
|
33
37
|
}
|
|
34
38
|
return mcpRequest;
|
|
35
39
|
}
|
|
36
40
|
|
|
41
|
+
/**
|
|
42
|
+
* JSON-RPC id helper:
|
|
43
|
+
* Keep 0 as a valid id; only default when null/undefined.
|
|
44
|
+
*/
|
|
45
|
+
function rpcId(mcpRequest) {
|
|
46
|
+
return mcpRequest?.id ?? null;
|
|
47
|
+
}
|
|
48
|
+
|
|
37
49
|
// Test mode
|
|
38
50
|
if (process.argv.includes('--test')) {
|
|
39
51
|
testConnection();
|
|
@@ -44,7 +56,7 @@ if (process.argv.includes('--test')) {
|
|
|
44
56
|
const rl = readline.createInterface({
|
|
45
57
|
input: process.stdin,
|
|
46
58
|
output: process.stdout,
|
|
47
|
-
terminal: false
|
|
59
|
+
terminal: false,
|
|
48
60
|
});
|
|
49
61
|
|
|
50
62
|
rl.on('line', (line) => {
|
|
@@ -55,14 +67,16 @@ rl.on('line', (line) => {
|
|
|
55
67
|
forwardToAPI(withClaudePlatform(mcpRequest));
|
|
56
68
|
} catch (error) {
|
|
57
69
|
// Only output to stdout, never stderr for MCP protocol
|
|
58
|
-
console.log(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
console.log(
|
|
71
|
+
JSON.stringify({
|
|
72
|
+
jsonrpc: '2.0',
|
|
73
|
+
error: {
|
|
74
|
+
code: -32700,
|
|
75
|
+
message: 'Parse error: ' + error.message,
|
|
76
|
+
},
|
|
77
|
+
id: null,
|
|
78
|
+
})
|
|
79
|
+
);
|
|
66
80
|
}
|
|
67
81
|
});
|
|
68
82
|
|
|
@@ -79,9 +93,9 @@ function forwardToAPI(mcpRequest) {
|
|
|
79
93
|
headers: {
|
|
80
94
|
'Content-Type': 'application/json',
|
|
81
95
|
'X-Api-Key': API_KEY,
|
|
82
|
-
'User-Agent': 'ReportDash-DataStore-MCP/1.0'
|
|
96
|
+
'User-Agent': 'ReportDash-DataStore-MCP/1.0',
|
|
83
97
|
},
|
|
84
|
-
timeout: 30000 // 30 second timeout
|
|
98
|
+
timeout: 30000, // 30 second timeout
|
|
85
99
|
};
|
|
86
100
|
|
|
87
101
|
const req = client.request(options, (res) => {
|
|
@@ -96,57 +110,62 @@ function forwardToAPI(mcpRequest) {
|
|
|
96
110
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
97
111
|
// For 204 No Content or empty response, return empty success
|
|
98
112
|
if (res.statusCode === 204 || !data.trim()) {
|
|
99
|
-
console.log(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
id: mcpRequest.id ?? null
|
|
107
|
-
}));
|
|
113
|
+
console.log(
|
|
114
|
+
JSON.stringify({
|
|
115
|
+
jsonrpc: '2.0',
|
|
116
|
+
result: {},
|
|
117
|
+
id: rpcId(mcpRequest), // FIX: preserves id=0
|
|
118
|
+
})
|
|
119
|
+
);
|
|
108
120
|
} else {
|
|
109
121
|
// Forward the response as-is
|
|
110
122
|
console.log(data);
|
|
111
123
|
}
|
|
112
124
|
} else {
|
|
113
125
|
// Send errors to stdout (not stderr!) so Claude can properly handle them
|
|
114
|
-
console.log(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
console.log(
|
|
127
|
+
JSON.stringify({
|
|
128
|
+
jsonrpc: '2.0',
|
|
129
|
+
error: {
|
|
130
|
+
code: res.statusCode,
|
|
131
|
+
message: `API error: ${res.statusCode}${data ? ' - ' + data : ''}`,
|
|
132
|
+
data: { statusCode: res.statusCode, body: data },
|
|
133
|
+
},
|
|
134
|
+
id: rpcId(mcpRequest), // FIX: preserves id=0
|
|
135
|
+
})
|
|
136
|
+
);
|
|
123
137
|
}
|
|
124
138
|
});
|
|
125
139
|
});
|
|
126
140
|
|
|
127
141
|
req.on('error', (error) => {
|
|
128
142
|
// Send errors to stdout (not stderr!)
|
|
129
|
-
console.log(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
143
|
+
console.log(
|
|
144
|
+
JSON.stringify({
|
|
145
|
+
jsonrpc: '2.0',
|
|
146
|
+
error: {
|
|
147
|
+
code: -32603,
|
|
148
|
+
message: 'Network error: ' + error.message,
|
|
149
|
+
data: { error: error.message },
|
|
150
|
+
},
|
|
151
|
+
id: rpcId(mcpRequest), // FIX: preserves id=0
|
|
152
|
+
})
|
|
153
|
+
);
|
|
137
154
|
});
|
|
138
155
|
|
|
139
156
|
req.on('timeout', () => {
|
|
140
157
|
req.destroy();
|
|
141
158
|
// Send errors to stdout (not stderr!)
|
|
142
|
-
console.log(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
159
|
+
console.log(
|
|
160
|
+
JSON.stringify({
|
|
161
|
+
jsonrpc: '2.0',
|
|
162
|
+
error: {
|
|
163
|
+
code: -32603,
|
|
164
|
+
message: 'Request timeout after 30 seconds',
|
|
165
|
+
},
|
|
166
|
+
id: rpcId(mcpRequest), // FIX: preserves id=0
|
|
167
|
+
})
|
|
168
|
+
);
|
|
150
169
|
});
|
|
151
170
|
|
|
152
171
|
req.write(JSON.stringify(mcpRequest));
|
|
@@ -154,9 +173,13 @@ function forwardToAPI(mcpRequest) {
|
|
|
154
173
|
}
|
|
155
174
|
|
|
156
175
|
function testConnection() {
|
|
176
|
+
// NOTE: This prints non-JSON to stdout, which is fine for --test.
|
|
177
|
+
// Do not run --test as an MCP stdio server in Claude Desktop.
|
|
157
178
|
console.log('🔍 Testing ReportDash DataStore connection...\n');
|
|
158
179
|
console.log(`API URL: ${API_URL}`);
|
|
159
|
-
console.log(
|
|
180
|
+
console.log(
|
|
181
|
+
`API Key: ${API_KEY.substring(0, 10)}...${API_KEY.substring(API_KEY.length - 4)}\n`
|
|
182
|
+
);
|
|
160
183
|
|
|
161
184
|
const url = new URL(API_URL);
|
|
162
185
|
const isHttps = url.protocol === 'https:';
|
|
@@ -166,7 +189,7 @@ function testConnection() {
|
|
|
166
189
|
const mcpRequest = withClaudePlatform({
|
|
167
190
|
jsonrpc: '2.0',
|
|
168
191
|
method: 'tools/list',
|
|
169
|
-
id: 'test-connection'
|
|
192
|
+
id: 'test-connection',
|
|
170
193
|
});
|
|
171
194
|
|
|
172
195
|
const postData = JSON.stringify(mcpRequest);
|
|
@@ -180,16 +203,18 @@ function testConnection() {
|
|
|
180
203
|
'Content-Type': 'application/json',
|
|
181
204
|
'X-Api-Key': API_KEY,
|
|
182
205
|
'Content-Length': Buffer.byteLength(postData),
|
|
183
|
-
'User-Agent': 'ReportDash-DataStore-MCP/1.0'
|
|
206
|
+
'User-Agent': 'ReportDash-DataStore-MCP/1.0',
|
|
184
207
|
},
|
|
185
|
-
timeout: 10000
|
|
208
|
+
timeout: 10000,
|
|
186
209
|
};
|
|
187
210
|
|
|
188
211
|
console.log('📡 Sending MCP tools/list request...\n');
|
|
189
212
|
|
|
190
213
|
const req = client.request(options, (res) => {
|
|
191
214
|
let data = '';
|
|
192
|
-
res.on('data', (chunk) => {
|
|
215
|
+
res.on('data', (chunk) => {
|
|
216
|
+
data += chunk;
|
|
217
|
+
});
|
|
193
218
|
res.on('end', () => {
|
|
194
219
|
console.log(`Response Status: ${res.statusCode}\n`);
|
|
195
220
|
|