redash-mcp 2.0.3 β†’ 2.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.
@@ -3,7 +3,9 @@
3
3
  "allow": [
4
4
  "Bash(git clone:*)",
5
5
  "Bash(npm:*)",
6
- "Bash(git push:*)"
6
+ "Bash(git push:*)",
7
+ "WebFetch(domain:registry.npmjs.org)",
8
+ "Bash(NPM_TOKEN=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 npm publish:*)"
7
9
  ]
8
10
  },
9
11
  "enabledMcpjsonServers": [
package/dist/setup.js CHANGED
@@ -2,10 +2,8 @@
2
2
  import * as fs from "fs";
3
3
  import * as path from "path";
4
4
  import * as os from "os";
5
- import * as readline from "readline";
6
5
  import { execSync } from "child_process";
7
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
8
- const ask = (q) => new Promise((res) => rl.question(q, res));
6
+ import * as p from "@clack/prompts";
9
7
  function findNpxPath() {
10
8
  try {
11
9
  const result = execSync("which npx", { encoding: "utf8" }).trim();
@@ -18,9 +16,9 @@ function findNpxPath() {
18
16
  "/opt/homebrew/bin/npx",
19
17
  "/usr/bin/npx",
20
18
  ];
21
- for (const p of candidates) {
22
- if (fs.existsSync(p))
23
- return p;
19
+ for (const c of candidates) {
20
+ if (fs.existsSync(c))
21
+ return c;
24
22
  }
25
23
  return "npx";
26
24
  }
@@ -40,38 +38,66 @@ function getClaudeCodeConfigPath() {
40
38
  return path.join(os.homedir(), ".claude", "settings.json");
41
39
  }
42
40
  export async function main() {
43
- console.log("\nπŸ”§ redash-mcp μ„€μΉ˜ λ§ˆλ²•μ‚¬\n");
44
- console.log("μ„€μΉ˜ λŒ€μƒμ„ μ„ νƒν•˜μ„Έμš”:");
45
- console.log(" 1) Claude Desktop");
46
- console.log(" 2) Claude Code (CLI)");
47
- console.log(" 3) λ‘˜ λ‹€");
48
- const target = (await ask("\n선택 (1/2/3) [1]: ")).trim() || "1";
49
- const redashUrl = (await ask("Redash URL을 μž…λ ₯ν•˜μ„Έμš” (예: https://redash.example.com): ")).trim().replace(/\/$/, "");
50
- const apiKey = (await ask("Redash API ν‚€λ₯Ό μž…λ ₯ν•˜μ„Έμš”: ")).trim();
51
- rl.close();
52
- if (!redashUrl || !apiKey) {
53
- console.error("\n❌ URLκ³Ό API ν‚€λ₯Ό λͺ¨λ‘ μž…λ ₯ν•΄μ•Ό ν•©λ‹ˆλ‹€.");
54
- process.exit(1);
41
+ p.intro("redash-mcp μ„€μΉ˜ λ§ˆλ²•μ‚¬");
42
+ const targets = await p.multiselect({
43
+ message: "μ„€μΉ˜ λŒ€μƒμ„ μ„ νƒν•˜μ„Έμš” (μŠ€νŽ˜μ΄μŠ€λ°”λ‘œ 선택, μ—”ν„°λ‘œ 확인)",
44
+ options: [
45
+ { value: "desktop", label: "Claude Desktop" },
46
+ { value: "cli", label: "Claude Code (CLI)" },
47
+ ],
48
+ required: true,
49
+ });
50
+ if (p.isCancel(targets)) {
51
+ p.cancel("μ„€μΉ˜κ°€ μ·¨μ†Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.");
52
+ process.exit(0);
55
53
  }
54
+ const redashUrl = await p.text({
55
+ message: "Redash URL을 μž…λ ₯ν•˜μ„Έμš”",
56
+ placeholder: "https://redash.example.com",
57
+ validate(value) {
58
+ if (!value)
59
+ return "URL을 μž…λ ₯ν•΄μ£Όμ„Έμš”.";
60
+ if (!value.startsWith("http://") && !value.startsWith("https://"))
61
+ return "http:// λ˜λŠ” https://둜 μ‹œμž‘ν•΄μ•Ό ν•©λ‹ˆλ‹€.";
62
+ },
63
+ });
64
+ if (p.isCancel(redashUrl)) {
65
+ p.cancel("μ„€μΉ˜κ°€ μ·¨μ†Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.");
66
+ process.exit(0);
67
+ }
68
+ const apiKey = await p.text({
69
+ message: "Redash API ν‚€λ₯Ό μž…λ ₯ν•˜μ„Έμš”",
70
+ validate(value) {
71
+ if (!value)
72
+ return "API ν‚€λ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”.";
73
+ },
74
+ });
75
+ if (p.isCancel(apiKey)) {
76
+ p.cancel("μ„€μΉ˜κ°€ μ·¨μ†Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.");
77
+ process.exit(0);
78
+ }
79
+ const url = redashUrl.replace(/\/$/, "");
56
80
  const npxPath = findNpxPath();
57
81
  const mcpEntry = {
58
82
  command: npxPath,
59
83
  args: ["-y", "redash-mcp"],
60
84
  env: {
61
- REDASH_URL: redashUrl,
85
+ REDASH_URL: url,
62
86
  REDASH_API_KEY: apiKey,
63
87
  },
64
88
  };
65
- if (target === "1" || target === "3") {
89
+ const s = p.spinner();
90
+ if (targets.includes("desktop")) {
91
+ s.start("Claude Desktop μ„€μ • 쀑...");
66
92
  setupDesktop(mcpEntry);
93
+ s.stop("Claude Desktop μ„€μ • μ™„λ£Œ");
67
94
  }
68
- if (target === "2" || target === "3") {
95
+ if (targets.includes("cli")) {
96
+ s.start("Claude Code (CLI) μ„€μ • 쀑...");
69
97
  setupClaudeCode(mcpEntry);
98
+ s.stop("Claude Code (CLI) μ„€μ • μ™„λ£Œ");
70
99
  }
71
- if (!["1", "2", "3"].includes(target)) {
72
- console.error("\n❌ 잘λͺ»λœ μ„ νƒμž…λ‹ˆλ‹€. 1, 2, 3 쀑 ν•˜λ‚˜λ₯Ό μž…λ ₯ν•˜μ„Έμš”.");
73
- process.exit(1);
74
- }
100
+ p.outro("μ„€μΉ˜κ°€ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€. μž¬μ‹œμž‘ ν›„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.");
75
101
  }
76
102
  function setupDesktop(mcpEntry) {
77
103
  const configPath = getDesktopConfigPath();
@@ -82,8 +108,7 @@ function setupDesktop(mcpEntry) {
82
108
  config.mcpServers ??= {};
83
109
  }
84
110
  catch {
85
- console.error("\n❌ claude_desktop_config.json νŒŒμΌμ„ 읽을 수 μ—†μŠ΅λ‹ˆλ‹€.");
86
- process.exit(1);
111
+ throw new Error(`claude_desktop_config.json νŒŒμΌμ„ 읽을 수 μ—†μŠ΅λ‹ˆλ‹€: ${configPath}`);
87
112
  }
88
113
  }
89
114
  else {
@@ -91,9 +116,6 @@ function setupDesktop(mcpEntry) {
91
116
  }
92
117
  config.mcpServers["redash-mcp"] = mcpEntry;
93
118
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf8");
94
- console.log("\nβœ… Claude Desktop μ„€μ • μ™„λ£Œ!");
95
- console.log(` μ„€μ • 파일: ${configPath}`);
96
- console.log(" πŸ‘‰ Claude Desktop을 μž¬μ‹œμž‘ν•˜λ©΄ ν™œμ„±ν™”λ©λ‹ˆλ‹€.");
97
119
  }
98
120
  function setupClaudeCode(mcpEntry) {
99
121
  const configPath = getClaudeCodeConfigPath();
@@ -103,8 +125,7 @@ function setupClaudeCode(mcpEntry) {
103
125
  config = JSON.parse(fs.readFileSync(configPath, "utf8"));
104
126
  }
105
127
  catch {
106
- console.error("\n❌ Claude Code settings.json νŒŒμΌμ„ 읽을 수 μ—†μŠ΅λ‹ˆλ‹€.");
107
- process.exit(1);
128
+ throw new Error(`Claude Code settings.json νŒŒμΌμ„ 읽을 수 μ—†μŠ΅λ‹ˆλ‹€: ${configPath}`);
108
129
  }
109
130
  }
110
131
  else {
@@ -113,7 +134,4 @@ function setupClaudeCode(mcpEntry) {
113
134
  config.mcpServers ??= {};
114
135
  config.mcpServers["redash-mcp"] = mcpEntry;
115
136
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf8");
116
- console.log("\nβœ… Claude Code (CLI) μ„€μ • μ™„λ£Œ!");
117
- console.log(` μ„€μ • 파일: ${configPath}`);
118
- console.log(" πŸ‘‰ μƒˆ Claude Code μ„Έμ…˜μ—μ„œ λ°”λ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.");
119
137
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redash-mcp",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "description": "MCP server for Redash",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -13,6 +13,7 @@
13
13
  "start": "node dist/index.js"
14
14
  },
15
15
  "dependencies": {
16
+ "@clack/prompts": "^1.1.0",
16
17
  "@modelcontextprotocol/sdk": "^1.0.0",
17
18
  "zod": "^3.0.0"
18
19
  },