@jtalk22/slack-mcp 1.2.0 → 1.2.2

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.
@@ -0,0 +1,206 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Slack MCP Server Demo</title>
7
+ <meta name="description" content="Video demo of session-based Slack access for Claude with DMs, channels, search, and threads.">
8
+ <meta property="og:type" content="website">
9
+ <meta property="og:title" content="Slack MCP Server - Session Access Demo">
10
+ <meta property="og:description" content="Video walkthrough of session-based Slack workflows in Claude.">
11
+ <meta property="og:url" content="https://jtalk22.github.io/slack-mcp-server/public/demo-video.html">
12
+ <meta property="og:image" content="https://raw.githubusercontent.com/jtalk22/slack-mcp-server/main/docs/images/demo-poster.png">
13
+ <meta name="twitter:card" content="summary_large_image">
14
+ <meta name="twitter:title" content="Slack MCP Server - Session Access Demo">
15
+ <meta name="twitter:description" content="Video walkthrough of session-based Slack workflows in Claude.">
16
+ <meta name="twitter:image" content="https://raw.githubusercontent.com/jtalk22/slack-mcp-server/main/docs/images/demo-poster.png">
17
+ <style>
18
+ * {
19
+ margin: 0;
20
+ padding: 0;
21
+ box-sizing: border-box;
22
+ }
23
+ body {
24
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
25
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
26
+ min-height: 100vh;
27
+ display: flex;
28
+ flex-direction: column;
29
+ align-items: center;
30
+ justify-content: center;
31
+ padding: 2rem;
32
+ }
33
+ .container {
34
+ max-width: 900px;
35
+ width: 100%;
36
+ }
37
+ h1 {
38
+ color: #ffffff;
39
+ font-size: 1.75rem;
40
+ font-weight: 600;
41
+ text-align: center;
42
+ margin-bottom: 0.5rem;
43
+ }
44
+ .subtitle {
45
+ color: #94a3b8;
46
+ text-align: center;
47
+ margin-bottom: 1.5rem;
48
+ font-size: 1rem;
49
+ }
50
+ .cta-strip {
51
+ margin: 0 auto 1rem;
52
+ background: rgba(15, 52, 96, 0.72);
53
+ border: 1px solid rgba(255, 255, 255, 0.16);
54
+ border-radius: 12px;
55
+ padding: 10px 14px;
56
+ display: flex;
57
+ justify-content: space-between;
58
+ align-items: center;
59
+ gap: 10px;
60
+ flex-wrap: wrap;
61
+ font-size: 0.8125rem;
62
+ }
63
+ .cta-strip .links {
64
+ display: flex;
65
+ gap: 8px;
66
+ flex-wrap: wrap;
67
+ }
68
+ .cta-strip .links a {
69
+ color: #d8efff;
70
+ text-decoration: none;
71
+ border: 1px solid rgba(255, 255, 255, 0.24);
72
+ border-radius: 999px;
73
+ padding: 4px 8px;
74
+ }
75
+ .cta-strip .links a:hover {
76
+ background: rgba(255, 255, 255, 0.08);
77
+ }
78
+ .cta-strip .note {
79
+ color: rgba(255, 255, 255, 0.82);
80
+ }
81
+ .cta-strip .note a {
82
+ color: #9ee7ff;
83
+ text-decoration: underline;
84
+ }
85
+ .video-wrapper {
86
+ position: relative;
87
+ border-radius: 12px;
88
+ overflow: hidden;
89
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
90
+ background: #0f0f1a;
91
+ }
92
+ video {
93
+ width: 100%;
94
+ display: block;
95
+ border-radius: 12px;
96
+ }
97
+ .controls {
98
+ display: flex;
99
+ justify-content: center;
100
+ gap: 1rem;
101
+ margin-top: 1.5rem;
102
+ }
103
+ .btn {
104
+ padding: 0.75rem 1.5rem;
105
+ border-radius: 8px;
106
+ border: none;
107
+ font-size: 0.875rem;
108
+ font-weight: 500;
109
+ cursor: pointer;
110
+ transition: all 0.2s;
111
+ }
112
+ .btn-primary {
113
+ background: #4ecdc4;
114
+ color: #1a1a2e;
115
+ }
116
+ .btn-primary:hover {
117
+ background: #5eead4;
118
+ transform: translateY(-1px);
119
+ }
120
+ .btn-secondary {
121
+ background: rgba(255, 255, 255, 0.1);
122
+ color: #ffffff;
123
+ border: 1px solid rgba(255, 255, 255, 0.2);
124
+ }
125
+ .btn-secondary:hover {
126
+ background: rgba(255, 255, 255, 0.15);
127
+ }
128
+ .back-link {
129
+ margin-top: 2rem;
130
+ text-align: center;
131
+ }
132
+ .back-link a {
133
+ color: #94a3b8;
134
+ text-decoration: none;
135
+ font-size: 0.875rem;
136
+ }
137
+ .back-link a:hover {
138
+ color: #ffffff;
139
+ }
140
+ </style>
141
+ </head>
142
+ <body>
143
+ <div class="container">
144
+ <h1>Slack MCP Server</h1>
145
+ <p class="subtitle">Full workspace access via local session mirroring</p>
146
+ <div class="cta-strip">
147
+ <div class="links">
148
+ <a href="https://www.npmjs.com/package/@jtalk22/slack-mcp" target="_blank" rel="noopener noreferrer">Install</a>
149
+ <a href="https://github.com/jtalk22/slack-mcp-server/blob/main/docs/API.md" target="_blank" rel="noopener noreferrer">API Docs</a>
150
+ <a href="https://github.com/jtalk22/slack-mcp-server/blob/main/CHANGELOG.md" target="_blank" rel="noopener noreferrer">Changelog</a>
151
+ </div>
152
+ <div class="note">
153
+ Team rollout? Review <a href="https://github.com/jtalk22/slack-mcp-server/blob/main/docs/DEPLOYMENT-MODES.md" target="_blank" rel="noopener noreferrer">Deployment Modes</a>.
154
+ </div>
155
+ </div>
156
+
157
+ <div class="video-wrapper">
158
+ <video id="demo" poster="../docs/images/demo-poster.png" playsinline>
159
+ <source src="../docs/videos/demo-claude-v1.2.webm" type="video/webm">
160
+ <source src="../docs/images/demo-claude-v1.2.gif" type="image/gif">
161
+ Your browser does not support the video tag.
162
+ </video>
163
+ </div>
164
+
165
+ <div class="controls">
166
+ <button class="btn btn-primary" onclick="togglePlay()">Play / Pause</button>
167
+ <button class="btn btn-secondary" onclick="restart()">Restart</button>
168
+ </div>
169
+
170
+ <div class="back-link">
171
+ <a href="https://github.com/jtalk22/slack-mcp-server">← Back to Repository</a>
172
+ </div>
173
+ </div>
174
+
175
+ <script>
176
+ const video = document.getElementById('demo');
177
+
178
+ // Autoplay with 1 second delay
179
+ setTimeout(() => {
180
+ video.play().catch(() => {
181
+ // Autoplay blocked, user will need to click
182
+ console.log('Autoplay blocked, click to play');
183
+ });
184
+ }, 1000);
185
+
186
+ function togglePlay() {
187
+ if (video.paused) {
188
+ video.play();
189
+ } else {
190
+ video.pause();
191
+ }
192
+ }
193
+
194
+ function restart() {
195
+ video.currentTime = 0;
196
+ video.play();
197
+ }
198
+
199
+ // Loop the video
200
+ video.addEventListener('ended', () => {
201
+ video.currentTime = 0;
202
+ video.play();
203
+ });
204
+ </script>
205
+ </body>
206
+ </html>
package/public/demo.html CHANGED
@@ -8,18 +8,18 @@
8
8
  <!-- Open Graph / Social Sharing -->
9
9
  <meta property="og:type" content="website">
10
10
  <meta property="og:url" content="https://jtalk22.github.io/slack-mcp-server/public/demo.html">
11
- <meta property="og:title" content="Slack MCP Server - Direct Access for Claude">
12
- <meta property="og:description" content="Give Claude full access to DMs and Channels without OAuth. Try the interactive simulator.">
11
+ <meta property="og:title" content="Slack MCP Server - Session Access Demo">
12
+ <meta property="og:description" content="Interactive demo for session-based Slack access in Claude: DMs, channels, search, and threads.">
13
13
  <meta property="og:image" content="https://raw.githubusercontent.com/jtalk22/slack-mcp-server/main/docs/images/demo-main.png">
14
14
 
15
15
  <!-- Twitter Card -->
16
16
  <meta name="twitter:card" content="summary_large_image">
17
- <meta name="twitter:title" content="Slack MCP Server - Direct Access for Claude">
18
- <meta name="twitter:description" content="Give Claude full access to DMs and Channels without OAuth. Try the interactive simulator.">
17
+ <meta name="twitter:title" content="Slack MCP Server - Session Access Demo">
18
+ <meta name="twitter:description" content="Interactive demo for session-based Slack access in Claude: DMs, channels, search, and threads.">
19
19
  <meta name="twitter:image" content="https://raw.githubusercontent.com/jtalk22/slack-mcp-server/main/docs/images/demo-main.png">
20
20
 
21
21
  <!-- SEO -->
22
- <meta name="description" content="Full Slack access for Claude - DMs, channels, search. No OAuth. No admin approval. Interactive demo simulator.">
22
+ <meta name="description" content="Session-based Slack access for Claude. Interactive demo for DMs, channels, search, and thread workflows.">
23
23
  <link rel="preconnect" href="https://fonts.googleapis.com">
24
24
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
25
25
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
@@ -74,12 +74,45 @@
74
74
  color: white;
75
75
  text-decoration: underline;
76
76
  }
77
+ .cta-strip {
78
+ background: rgba(15, 52, 96, 0.9);
79
+ border-bottom: 1px solid rgba(255, 255, 255, 0.12);
80
+ padding: 10px 16px;
81
+ display: flex;
82
+ justify-content: space-between;
83
+ align-items: center;
84
+ gap: 12px;
85
+ flex-wrap: wrap;
86
+ font-size: 13px;
87
+ }
88
+ .cta-links {
89
+ display: flex;
90
+ gap: 10px;
91
+ flex-wrap: wrap;
92
+ }
93
+ .cta-links a {
94
+ color: #d8efff;
95
+ text-decoration: none;
96
+ padding: 4px 8px;
97
+ border: 1px solid rgba(255, 255, 255, 0.25);
98
+ border-radius: 999px;
99
+ }
100
+ .cta-links a:hover {
101
+ background: rgba(255, 255, 255, 0.1);
102
+ }
103
+ .cta-note {
104
+ color: rgba(255, 255, 255, 0.75);
105
+ }
106
+ .cta-note a {
107
+ color: #9ee7ff;
108
+ text-decoration: underline;
109
+ }
77
110
 
78
111
  /* Main Layout */
79
112
  .split-container {
80
113
  display: grid;
81
114
  grid-template-columns: 420px 1fr;
82
- height: calc(100vh - 44px);
115
+ height: calc(100vh - 88px);
83
116
  overflow: hidden;
84
117
  }
85
118
 
@@ -600,6 +633,16 @@
600
633
  STATIC PREVIEW - No real data. Run <code>npm run web</code> for live dashboard.
601
634
  <a href="https://github.com/jtalk22/slack-mcp-server">View on GitHub</a>
602
635
  </div>
636
+ <div class="cta-strip">
637
+ <div class="cta-links">
638
+ <a href="https://www.npmjs.com/package/@jtalk22/slack-mcp" target="_blank" rel="noopener noreferrer">Install</a>
639
+ <a href="https://github.com/jtalk22/slack-mcp-server/blob/main/docs/API.md" target="_blank" rel="noopener noreferrer">API Docs</a>
640
+ <a href="https://github.com/jtalk22/slack-mcp-server/blob/main/CHANGELOG.md" target="_blank" rel="noopener noreferrer">Changelog</a>
641
+ </div>
642
+ <div class="cta-note">
643
+ Team rollout? Review <a href="https://github.com/jtalk22/slack-mcp-server/blob/main/docs/DEPLOYMENT-MODES.md" target="_blank" rel="noopener noreferrer">Deployment Modes</a>.
644
+ </div>
645
+ </div>
603
646
 
604
647
  <div class="split-container">
605
648
  <!-- LEFT: Claude Chat Panel -->
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ EXPECTED_NAME="${EXPECTED_GIT_NAME:-jtalk22}"
5
+ EXPECTED_EMAIL="${EXPECTED_GIT_EMAIL:-james@revasser.nyc}"
6
+ BANNED_REGEX='(?i)(co-authored-by|generated with|\bclaude\b|\bgpt\b|\bcopilot\b|\bgemini\b|\bai\b)'
7
+
8
+ die() {
9
+ echo "ERROR: $*" >&2
10
+ exit 1
11
+ }
12
+
13
+ contains_banned_markers() {
14
+ local text="$1"
15
+ if command -v rg >/dev/null 2>&1; then
16
+ rg -Niq "$BANNED_REGEX" <<<"$text"
17
+ else
18
+ grep -Eiq '(Co-authored-by|Generated with|Claude|GPT|Copilot|Gemini)' <<<"$text" \
19
+ || grep -Eiq '(^|[^[:alnum:]_])[Aa][Ii]([^[:alnum:]_]|$)' <<<"$text"
20
+ fi
21
+ }
22
+
23
+ if [[ "${SKIP_LOCAL_CONFIG_CHECK:-0}" != "1" ]]; then
24
+ local_name="$(git config --get user.name || true)"
25
+ local_email="$(git config --get user.email || true)"
26
+
27
+ [[ -n "$local_name" ]] || die "Missing repo-local git user.name"
28
+ [[ -n "$local_email" ]] || die "Missing repo-local git user.email"
29
+
30
+ [[ "$local_name" == "$EXPECTED_NAME" ]] \
31
+ || die "Repo-local user.name is '$local_name' (expected '$EXPECTED_NAME')"
32
+ [[ "$local_email" == "$EXPECTED_EMAIL" ]] \
33
+ || die "Repo-local user.email is '$local_email' (expected '$EXPECTED_EMAIL')"
34
+ fi
35
+
36
+ default_range="HEAD"
37
+ if git rev-parse --verify origin/main >/dev/null 2>&1; then
38
+ default_range="origin/main..HEAD"
39
+ fi
40
+
41
+ range="${1:-${GIT_CHECK_RANGE:-$default_range}}"
42
+
43
+ git rev-list --count "$range" >/dev/null 2>&1 || die "Invalid commit range: $range"
44
+ commit_count="$(git rev-list --count "$range")"
45
+
46
+ if [[ "$commit_count" -eq 0 ]]; then
47
+ echo "No commits to validate in range '$range'."
48
+ exit 0
49
+ fi
50
+
51
+ errors=0
52
+
53
+ while IFS= read -r sha; do
54
+ author_name="$(git show -s --format=%an "$sha")"
55
+ author_email="$(git show -s --format=%ae "$sha")"
56
+ committer_name="$(git show -s --format=%cn "$sha")"
57
+ committer_email="$(git show -s --format=%ce "$sha")"
58
+ body="$(git show -s --format=%B "$sha")"
59
+
60
+ if [[ "$author_name" != "$EXPECTED_NAME" || "$author_email" != "$EXPECTED_EMAIL" ]]; then
61
+ echo "Commit $sha has author '$author_name <$author_email>' (expected '$EXPECTED_NAME <$EXPECTED_EMAIL>')." >&2
62
+ errors=1
63
+ fi
64
+
65
+ if [[ "$committer_name" != "$EXPECTED_NAME" || "$committer_email" != "$EXPECTED_EMAIL" ]]; then
66
+ echo "Commit $sha has committer '$committer_name <$committer_email>' (expected '$EXPECTED_NAME <$EXPECTED_EMAIL>')." >&2
67
+ errors=1
68
+ fi
69
+
70
+ if contains_banned_markers "$body"; then
71
+ echo "Commit $sha contains disallowed attribution markers in commit message." >&2
72
+ errors=1
73
+ fi
74
+ done < <(git rev-list "$range")
75
+
76
+ if [[ "$errors" -ne 0 ]]; then
77
+ exit 1
78
+ fi
79
+
80
+ echo "Owner-only attribution check passed for $commit_count commit(s) in '$range'."
@@ -73,6 +73,10 @@ async function recordDemo() {
73
73
  await page.goto(`file://${demoPath}`);
74
74
  await page.waitForTimeout(1000);
75
75
 
76
+ // Hold on initial frame for a few seconds (visible first frame in GIF)
77
+ console.log('⏸️ Holding initial frame (3s)...');
78
+ await page.waitForTimeout(3000);
79
+
76
80
  // Set slow speed for video recording
77
81
  console.log(`⏱️ Setting speed to ${CONFIG.speed}x...`);
78
82
  await page.selectOption('#speedSelect', CONFIG.speed);
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ repo_root="$(git rev-parse --show-toplevel)"
5
+ cd "$repo_root"
6
+
7
+ [[ -d .githooks ]] || {
8
+ echo "Missing .githooks directory." >&2
9
+ exit 1
10
+ }
11
+
12
+ git config core.hooksPath .githooks
13
+ find .githooks -maxdepth 1 -type f -exec chmod +x {} +
14
+
15
+ echo "Configured git hooks path: .githooks"
@@ -16,7 +16,7 @@ import { loadTokens, saveTokens, extractFromChrome, isAutoRefreshAvailable, TOKE
16
16
  import { slackAPI } from "../lib/slack-client.js";
17
17
 
18
18
  const IS_MACOS = platform() === 'darwin';
19
- const VERSION = "1.2.0";
19
+ const VERSION = "1.2.2";
20
20
 
21
21
  // ANSI colors
22
22
  const colors = {
@@ -69,24 +69,27 @@ async function pressEnterToContinue(rl) {
69
69
  }
70
70
 
71
71
  async function validateTokens(token, cookie) {
72
- try {
73
- // Temporarily set env vars for validation
74
- const oldToken = process.env.SLACK_TOKEN;
75
- const oldCookie = process.env.SLACK_COOKIE;
76
- process.env.SLACK_TOKEN = token;
77
- process.env.SLACK_COOKIE = cookie;
78
-
79
- const result = await slackAPI("auth.test", {});
72
+ const hadOldToken = Object.prototype.hasOwnProperty.call(process.env, "SLACK_TOKEN");
73
+ const hadOldCookie = Object.prototype.hasOwnProperty.call(process.env, "SLACK_COOKIE");
74
+ const oldToken = process.env.SLACK_TOKEN;
75
+ const oldCookie = process.env.SLACK_COOKIE;
80
76
 
81
- // Restore env vars
82
- if (oldToken) process.env.SLACK_TOKEN = oldToken;
83
- else delete process.env.SLACK_TOKEN;
84
- if (oldCookie) process.env.SLACK_COOKIE = oldCookie;
85
- else delete process.env.SLACK_COOKIE;
77
+ // Temporarily set env vars for validation
78
+ process.env.SLACK_TOKEN = token;
79
+ process.env.SLACK_COOKIE = cookie;
86
80
 
81
+ try {
82
+ const result = await slackAPI("auth.test", {});
87
83
  return { valid: true, user: result.user, team: result.team };
88
84
  } catch (e) {
89
85
  return { valid: false, error: e.message };
86
+ } finally {
87
+ // Always restore prior process env state
88
+ if (hadOldToken) process.env.SLACK_TOKEN = oldToken;
89
+ else delete process.env.SLACK_TOKEN;
90
+
91
+ if (hadOldCookie) process.env.SLACK_COOKIE = oldCookie;
92
+ else delete process.env.SLACK_COOKIE;
90
93
  }
91
94
  }
92
95
 
@@ -175,7 +178,7 @@ async function runManualSetup(rl) {
175
178
  " .teams)[0]].token",
176
179
  ], 55);
177
180
  print();
178
- print(" Copy the token (starts with ${colors.cyan}xoxc-${colors.reset})");
181
+ print(` Copy the token (starts with ${colors.cyan}xoxc-${colors.reset})`);
179
182
  print();
180
183
 
181
184
  const token = await question(rl, `${colors.bold}Paste your token:${colors.reset} `);
@@ -187,7 +190,7 @@ async function runManualSetup(rl) {
187
190
 
188
191
  print();
189
192
  print(`${colors.bold}Step 4:${colors.reset} Go to ${colors.cyan}Application${colors.reset} tab → ${colors.cyan}Cookies${colors.reset} → slack.com`);
190
- print(" Find the '${colors.cyan}d${colors.reset}' cookie and copy its value");
193
+ print(` Find the '${colors.cyan}d${colors.reset}' cookie and copy its value`);
191
194
  print();
192
195
 
193
196
  const cookie = await question(rl, `${colors.bold}Paste your cookie:${colors.reset} `);
@@ -229,7 +232,7 @@ async function showStatus() {
229
232
  if (!creds) {
230
233
  error("No tokens found");
231
234
  print();
232
- print("Run setup wizard: npx @jtalk22/slack-mcp --setup");
235
+ print("Run setup wizard: npx -y @jtalk22/slack-mcp --setup");
233
236
  process.exit(1);
234
237
  }
235
238
 
@@ -254,7 +257,7 @@ async function showStatus() {
254
257
  error("Status: INVALID");
255
258
  print(`Error: ${e.message}`);
256
259
  print();
257
- print("Run setup wizard to refresh: npx @jtalk22/slack-mcp --setup");
260
+ print("Run setup wizard to refresh: npx -y @jtalk22/slack-mcp --setup");
258
261
  process.exit(1);
259
262
  }
260
263
  }
@@ -265,11 +268,11 @@ async function showHelp() {
265
268
  print("Full Slack access for Claude via MCP. Session mirroring bypasses OAuth.");
266
269
  print();
267
270
  print(`${colors.bold}Usage:${colors.reset}`);
268
- print(" npx @jtalk22/slack-mcp Start MCP server (stdio)");
269
- print(" npx @jtalk22/slack-mcp --setup Interactive token setup wizard");
270
- print(" npx @jtalk22/slack-mcp --status Check token health");
271
- print(" npx @jtalk22/slack-mcp --version Print version");
272
- print(" npx @jtalk22/slack-mcp --help Show this help");
271
+ print(" npx -y @jtalk22/slack-mcp Start MCP server (stdio)");
272
+ print(" npx -y @jtalk22/slack-mcp --setup Interactive token setup wizard");
273
+ print(" npx -y @jtalk22/slack-mcp --status Check token health");
274
+ print(" npx -y @jtalk22/slack-mcp --version Print version");
275
+ print(" npx -y @jtalk22/slack-mcp --help Show this help");
273
276
  print();
274
277
  print(`${colors.bold}npm scripts:${colors.reset}`);
275
278
  print(" npm start Start MCP server");
@@ -342,8 +345,8 @@ async function main() {
342
345
  print(`${colors.green}${colors.bold}Setup complete!${colors.reset}`);
343
346
  print();
344
347
  print("Next steps:");
345
- print(" • Verify: npx @jtalk22/slack-mcp --status");
346
- print(" • Start server: npx @jtalk22/slack-mcp");
348
+ print(" • Verify: npx -y @jtalk22/slack-mcp --status");
349
+ print(" • Start server: npx -y @jtalk22/slack-mcp");
347
350
  print(" • Or add to Claude Desktop config");
348
351
  } else {
349
352
  print(`${colors.red}Setup failed.${colors.reset} See errors above.`);
package/src/cli.js ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * slack-mcp package entrypoint dispatcher.
4
+ *
5
+ * Supports:
6
+ * - default stdio server startup
7
+ * - web/http server modes
8
+ * - setup wizard and its status/help/version flags
9
+ */
10
+
11
+ import { spawn } from "node:child_process";
12
+ import { dirname, join } from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+
15
+ const __dirname = dirname(fileURLToPath(import.meta.url));
16
+
17
+ const args = process.argv.slice(2);
18
+ const firstArg = args[0];
19
+
20
+ const WIZARD_ARGS = new Set([
21
+ "--setup", "setup",
22
+ "--status", "status",
23
+ "--version", "-v",
24
+ "--help", "-h", "help",
25
+ ]);
26
+
27
+ let scriptPath = join(__dirname, "server.js");
28
+ let scriptArgs = args;
29
+
30
+ if (firstArg === "web") {
31
+ scriptPath = join(__dirname, "web-server.js");
32
+ scriptArgs = args.slice(1);
33
+ } else if (firstArg === "http") {
34
+ scriptPath = join(__dirname, "server-http.js");
35
+ scriptArgs = args.slice(1);
36
+ } else if (WIZARD_ARGS.has(firstArg)) {
37
+ scriptPath = join(__dirname, "../scripts/setup-wizard.js");
38
+ scriptArgs = args;
39
+ }
40
+
41
+ const child = spawn(process.execPath, [scriptPath, ...scriptArgs], {
42
+ stdio: "inherit",
43
+ env: process.env,
44
+ });
45
+
46
+ child.on("error", (error) => {
47
+ console.error(`Failed to start ${scriptPath}: ${error.message}`);
48
+ process.exit(1);
49
+ });
50
+
51
+ child.on("exit", (code, signal) => {
52
+ if (signal) {
53
+ process.kill(process.pid, signal);
54
+ return;
55
+ }
56
+ process.exit(code ?? 0);
57
+ });
@@ -30,7 +30,7 @@ import {
30
30
  } from "../lib/handlers.js";
31
31
 
32
32
  const SERVER_NAME = "slack-mcp-server";
33
- const SERVER_VERSION = "1.2.0";
33
+ const SERVER_VERSION = "1.2.2";
34
34
  const PORT = process.env.PORT || 3000;
35
35
 
36
36
  // Create MCP server