reportdash-datastore-mcp-claude-desktop 1.0.7 → 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 -57
- 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,54 +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
|
-
|
|
113
|
+
console.log(
|
|
114
|
+
JSON.stringify({
|
|
115
|
+
jsonrpc: '2.0',
|
|
116
|
+
result: {},
|
|
117
|
+
id: rpcId(mcpRequest), // FIX: preserves id=0
|
|
118
|
+
})
|
|
119
|
+
);
|
|
104
120
|
} else {
|
|
105
121
|
// Forward the response as-is
|
|
106
122
|
console.log(data);
|
|
107
123
|
}
|
|
108
124
|
} else {
|
|
109
125
|
// Send errors to stdout (not stderr!) so Claude can properly handle them
|
|
110
|
-
console.log(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
+
);
|
|
119
137
|
}
|
|
120
138
|
});
|
|
121
139
|
});
|
|
122
140
|
|
|
123
141
|
req.on('error', (error) => {
|
|
124
142
|
// Send errors to stdout (not stderr!)
|
|
125
|
-
console.log(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
+
);
|
|
134
154
|
});
|
|
135
155
|
|
|
136
156
|
req.on('timeout', () => {
|
|
137
157
|
req.destroy();
|
|
138
158
|
// Send errors to stdout (not stderr!)
|
|
139
|
-
console.log(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
+
);
|
|
147
169
|
});
|
|
148
170
|
|
|
149
171
|
req.write(JSON.stringify(mcpRequest));
|
|
@@ -151,9 +173,13 @@ function forwardToAPI(mcpRequest) {
|
|
|
151
173
|
}
|
|
152
174
|
|
|
153
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.
|
|
154
178
|
console.log('🔍 Testing ReportDash DataStore connection...\n');
|
|
155
179
|
console.log(`API URL: ${API_URL}`);
|
|
156
|
-
console.log(
|
|
180
|
+
console.log(
|
|
181
|
+
`API Key: ${API_KEY.substring(0, 10)}...${API_KEY.substring(API_KEY.length - 4)}\n`
|
|
182
|
+
);
|
|
157
183
|
|
|
158
184
|
const url = new URL(API_URL);
|
|
159
185
|
const isHttps = url.protocol === 'https:';
|
|
@@ -163,7 +189,7 @@ function testConnection() {
|
|
|
163
189
|
const mcpRequest = withClaudePlatform({
|
|
164
190
|
jsonrpc: '2.0',
|
|
165
191
|
method: 'tools/list',
|
|
166
|
-
id: 'test-connection'
|
|
192
|
+
id: 'test-connection',
|
|
167
193
|
});
|
|
168
194
|
|
|
169
195
|
const postData = JSON.stringify(mcpRequest);
|
|
@@ -177,16 +203,18 @@ function testConnection() {
|
|
|
177
203
|
'Content-Type': 'application/json',
|
|
178
204
|
'X-Api-Key': API_KEY,
|
|
179
205
|
'Content-Length': Buffer.byteLength(postData),
|
|
180
|
-
'User-Agent': 'ReportDash-DataStore-MCP/1.0'
|
|
206
|
+
'User-Agent': 'ReportDash-DataStore-MCP/1.0',
|
|
181
207
|
},
|
|
182
|
-
timeout: 10000
|
|
208
|
+
timeout: 10000,
|
|
183
209
|
};
|
|
184
210
|
|
|
185
211
|
console.log('📡 Sending MCP tools/list request...\n');
|
|
186
212
|
|
|
187
213
|
const req = client.request(options, (res) => {
|
|
188
214
|
let data = '';
|
|
189
|
-
res.on('data', (chunk) => {
|
|
215
|
+
res.on('data', (chunk) => {
|
|
216
|
+
data += chunk;
|
|
217
|
+
});
|
|
190
218
|
res.on('end', () => {
|
|
191
219
|
console.log(`Response Status: ${res.statusCode}\n`);
|
|
192
220
|
|