redash-mcp 3.0.3 → 3.0.4
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/dist/bird/tools.js +220 -189
- package/dist/index.js +414 -323
- package/dist/redash-client.js +25 -1
- package/dist/tool-error.js +40 -0
- package/package.json +1 -1
package/dist/redash-client.js
CHANGED
|
@@ -1,4 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
function validateRedashUrl(raw) {
|
|
2
|
+
if (raw === undefined)
|
|
3
|
+
return undefined;
|
|
4
|
+
const trimmed = raw.trim();
|
|
5
|
+
if (trimmed.length === 0)
|
|
6
|
+
return undefined;
|
|
7
|
+
if (/[\n\r]/.test(raw)) {
|
|
8
|
+
throw new Error("REDASH_URL must not contain newlines");
|
|
9
|
+
}
|
|
10
|
+
let parsed;
|
|
11
|
+
try {
|
|
12
|
+
parsed = new URL(trimmed);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
throw new Error(`REDASH_URL is not a valid URL: ${raw}`);
|
|
16
|
+
}
|
|
17
|
+
if (parsed.username || parsed.password) {
|
|
18
|
+
throw new Error("REDASH_URL must not contain credentials");
|
|
19
|
+
}
|
|
20
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
21
|
+
throw new Error(`REDASH_URL must use http or https scheme, got: ${parsed.protocol}`);
|
|
22
|
+
}
|
|
23
|
+
return trimmed.replace(/\/$/, "");
|
|
24
|
+
}
|
|
25
|
+
const REDASH_URL = validateRedashUrl(process.env.REDASH_URL);
|
|
2
26
|
const REDASH_API_KEY = process.env.REDASH_API_KEY;
|
|
3
27
|
export { REDASH_URL, REDASH_API_KEY };
|
|
4
28
|
export async function redashFetch(path, options) {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared error handler for MCP tool callbacks.
|
|
3
|
+
* Logs the full error to stderr for debugging, then returns a
|
|
4
|
+
* user-friendly MCP error response without leaking internal details.
|
|
5
|
+
*/
|
|
6
|
+
export function handleToolError(toolName, error) {
|
|
7
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
8
|
+
// Log full detail to stderr so operators can debug.
|
|
9
|
+
console.error(`[${toolName}] ${detail}`);
|
|
10
|
+
// Derive a safe, user-facing message.
|
|
11
|
+
let userMessage;
|
|
12
|
+
if (detail.includes("Query timed out")) {
|
|
13
|
+
userMessage = "The query timed out. Try simplifying the query or increasing timeout_secs.";
|
|
14
|
+
}
|
|
15
|
+
else if (detail.includes("Query failed")) {
|
|
16
|
+
userMessage = "The query execution failed. Please check the SQL syntax and try again.";
|
|
17
|
+
}
|
|
18
|
+
else if (detail.includes("401") || detail.includes("Check your REDASH_API_KEY")) {
|
|
19
|
+
userMessage = "Authentication failed. Please verify your Redash API key.";
|
|
20
|
+
}
|
|
21
|
+
else if (detail.includes("403") || detail.includes("Access denied")) {
|
|
22
|
+
userMessage = "Access denied. You do not have permission for this resource.";
|
|
23
|
+
}
|
|
24
|
+
else if (/\b404\b/.test(detail) || detail.includes("Redash API error (404)")) {
|
|
25
|
+
userMessage = "The requested resource was not found. Please check the ID and try again.";
|
|
26
|
+
}
|
|
27
|
+
else if (detail.includes("Redash API error")) {
|
|
28
|
+
userMessage = "The Redash API returned an error. Please try again later.";
|
|
29
|
+
}
|
|
30
|
+
else if (detail.includes("fetch failed") || detail.includes("ECONNREFUSED") || detail.includes("ENOTFOUND")) {
|
|
31
|
+
userMessage = "Unable to connect to the Redash server. Please check REDASH_URL and network connectivity.";
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
userMessage = "An unexpected error occurred. Please try again or check the server logs.";
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: "text", text: userMessage }],
|
|
38
|
+
isError: true,
|
|
39
|
+
};
|
|
40
|
+
}
|