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.
Files changed (2) hide show
  1. package/index.js +85 -60
  2. 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
- console.error(JSON.stringify({
16
- jsonrpc: '2.0',
17
- error: {
18
- code: -32600,
19
- message: 'REPORTDASH_API_KEY environment variable is required. Get your API key from ReportDash DataStore app settings.'
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 (!mcpRequest.platform) mcpRequest.platform = 'claude';
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(JSON.stringify({
59
- jsonrpc: '2.0',
60
- error: {
61
- code: -32700,
62
- message: 'Parse error: ' + error.message
63
- },
64
- id: null
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(JSON.stringify({
100
- jsonrpc: '2.0',
101
- error: {
102
- code: res.statusCode,
103
- message: `API error: ${res.statusCode}${data ? ' - ' + data : ''}`,
104
- data: { statusCode: res.statusCode, body: data }
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(JSON.stringify({
115
- jsonrpc: '2.0',
116
- error: {
117
- code: res.statusCode,
118
- message: `API error: ${res.statusCode}${data ? ' - ' + data : ''}`,
119
- data: { statusCode: res.statusCode, body: data }
120
- },
121
- id: mcpRequest.id || null
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(JSON.stringify({
130
- jsonrpc: '2.0',
131
- error: {
132
- code: -32603,
133
- message: 'Request timeout after 30 seconds'
134
- },
135
- id: mcpRequest.id ?? null
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(JSON.stringify({
143
- jsonrpc: '2.0',
144
- error: {
145
- code: -32603,
146
- message: 'Request timeout after 30 seconds'
147
- },
148
- id: mcpRequest.id || null
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(`API Key: ${API_KEY.substring(0, 10)}...${API_KEY.substring(API_KEY.length - 4)}\n`);
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) => { 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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reportdash-datastore-mcp-claude-desktop",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "ReportDash DataStore MCP server for Claude Desktop",
5
5
  "main": "index.js",
6
6
  "bin": {