@jtalk22/slack-mcp 3.0.0 → 3.2.0
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/README.md +63 -28
- package/docs/SETUP.md +64 -29
- package/docs/TROUBLESHOOTING.md +28 -0
- package/lib/handlers.js +156 -0
- package/lib/slack-client.js +11 -3
- package/lib/token-store.js +6 -5
- package/lib/tools.js +131 -0
- package/package.json +35 -36
- package/public/index.html +10 -6
- package/public/share.html +128 -0
- package/scripts/setup-wizard.js +1 -1
- package/server.json +10 -4
- package/src/server-http.js +16 -1
- package/src/server.js +31 -7
- package/src/web-server.js +119 -4
- package/docs/CLOUDFLARE-BROWSER-TOOLKIT.md +0 -67
- package/docs/COMMUNICATION-STYLE.md +0 -66
- package/docs/COMPATIBILITY.md +0 -19
- package/docs/DEPLOYMENT-MODES.md +0 -55
- package/docs/HN-LAUNCH.md +0 -72
- package/docs/INDEX.md +0 -40
- package/docs/INSTALL-PROOF.md +0 -18
- package/docs/LAUNCH-COPY-v3.0.0.md +0 -73
- package/docs/LAUNCH-MATRIX.md +0 -22
- package/docs/LAUNCH-OPS.md +0 -71
- package/docs/RELEASE-HEALTH.md +0 -90
- package/docs/SUPPORT-BOUNDARIES.md +0 -49
- package/docs/USE_CASE_RECIPES.md +0 -69
- package/docs/WEB-API.md +0 -303
- package/docs/images/demo-channel-messages.png +0 -0
- package/docs/images/demo-channels.png +0 -0
- package/docs/images/demo-claude-mobile-360x800.png +0 -0
- package/docs/images/demo-claude-mobile-390x844.png +0 -0
- package/docs/images/demo-main-mobile-360x800.png +0 -0
- package/docs/images/demo-main-mobile-390x844.png +0 -0
- package/docs/images/demo-main.png +0 -0
- package/docs/images/demo-messages.png +0 -0
- package/docs/images/demo-poster.png +0 -0
- package/docs/images/demo-sidebar.png +0 -0
- package/docs/images/diagram-oauth-comparison.svg +0 -80
- package/docs/images/diagram-session-flow.svg +0 -105
- package/docs/images/web-api-mobile-360x800.png +0 -0
- package/docs/images/web-api-mobile-390x844.png +0 -0
- package/public/demo-claude.html +0 -1958
- package/public/demo-video.html +0 -235
- package/public/demo.html +0 -1196
- package/scripts/build-release-health-delta.js +0 -201
- package/scripts/capture-screenshots.js +0 -146
- package/scripts/check-owner-attribution.sh +0 -80
- package/scripts/check-public-language.sh +0 -25
- package/scripts/check-version-parity.js +0 -176
- package/scripts/cloudflare-browser-tool.js +0 -237
- package/scripts/collect-release-health.js +0 -150
- package/scripts/record-demo.js +0 -162
- package/scripts/release-preflight.js +0 -243
- package/scripts/setup-git-hooks.sh +0 -15
- package/scripts/verify-core.js +0 -159
- package/scripts/verify-install-flow.js +0 -193
- package/scripts/verify-web.js +0 -269
package/lib/tools.js
CHANGED
|
@@ -268,5 +268,136 @@ export const TOOLS = [
|
|
|
268
268
|
idempotentHint: true,
|
|
269
269
|
openWorldHint: true
|
|
270
270
|
}
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: "slack_add_reaction",
|
|
274
|
+
description: "Add an emoji reaction to a message",
|
|
275
|
+
inputSchema: {
|
|
276
|
+
type: "object",
|
|
277
|
+
properties: {
|
|
278
|
+
channel_id: {
|
|
279
|
+
type: "string",
|
|
280
|
+
description: "Channel or DM ID containing the message"
|
|
281
|
+
},
|
|
282
|
+
timestamp: {
|
|
283
|
+
type: "string",
|
|
284
|
+
description: "Message timestamp to react to"
|
|
285
|
+
},
|
|
286
|
+
reaction: {
|
|
287
|
+
type: "string",
|
|
288
|
+
description: "Emoji name without colons (e.g., 'thumbsup', 'eyes', 'white_check_mark')"
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
required: ["channel_id", "timestamp", "reaction"]
|
|
292
|
+
},
|
|
293
|
+
annotations: {
|
|
294
|
+
title: "Add Reaction",
|
|
295
|
+
readOnlyHint: false,
|
|
296
|
+
destructiveHint: false,
|
|
297
|
+
idempotentHint: true,
|
|
298
|
+
openWorldHint: true
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
name: "slack_remove_reaction",
|
|
303
|
+
description: "Remove an emoji reaction from a message",
|
|
304
|
+
inputSchema: {
|
|
305
|
+
type: "object",
|
|
306
|
+
properties: {
|
|
307
|
+
channel_id: {
|
|
308
|
+
type: "string",
|
|
309
|
+
description: "Channel or DM ID containing the message"
|
|
310
|
+
},
|
|
311
|
+
timestamp: {
|
|
312
|
+
type: "string",
|
|
313
|
+
description: "Message timestamp to remove reaction from"
|
|
314
|
+
},
|
|
315
|
+
reaction: {
|
|
316
|
+
type: "string",
|
|
317
|
+
description: "Emoji name without colons (e.g., 'thumbsup', 'eyes')"
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
required: ["channel_id", "timestamp", "reaction"]
|
|
321
|
+
},
|
|
322
|
+
annotations: {
|
|
323
|
+
title: "Remove Reaction",
|
|
324
|
+
readOnlyHint: false,
|
|
325
|
+
destructiveHint: false,
|
|
326
|
+
idempotentHint: true,
|
|
327
|
+
openWorldHint: true
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
name: "slack_conversations_mark",
|
|
332
|
+
description: "Mark a conversation as read up to a specific message timestamp",
|
|
333
|
+
inputSchema: {
|
|
334
|
+
type: "object",
|
|
335
|
+
properties: {
|
|
336
|
+
channel_id: {
|
|
337
|
+
type: "string",
|
|
338
|
+
description: "Channel or DM ID to mark as read"
|
|
339
|
+
},
|
|
340
|
+
timestamp: {
|
|
341
|
+
type: "string",
|
|
342
|
+
description: "Message timestamp to mark as read up to (all messages at or before this are marked read)"
|
|
343
|
+
}
|
|
344
|
+
},
|
|
345
|
+
required: ["channel_id", "timestamp"]
|
|
346
|
+
},
|
|
347
|
+
annotations: {
|
|
348
|
+
title: "Mark as Read",
|
|
349
|
+
readOnlyHint: false,
|
|
350
|
+
destructiveHint: false,
|
|
351
|
+
idempotentHint: true,
|
|
352
|
+
openWorldHint: true
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
name: "slack_conversations_unreads",
|
|
357
|
+
description: "Get channels and DMs with unread messages, sorted by unread count (highest first)",
|
|
358
|
+
inputSchema: {
|
|
359
|
+
type: "object",
|
|
360
|
+
properties: {
|
|
361
|
+
types: {
|
|
362
|
+
type: "string",
|
|
363
|
+
description: "Comma-separated types: im, mpim, public_channel, private_channel (default all)",
|
|
364
|
+
default: "im,mpim,public_channel,private_channel"
|
|
365
|
+
},
|
|
366
|
+
limit: {
|
|
367
|
+
type: "number",
|
|
368
|
+
description: "Maximum conversations to return (default 50)"
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
annotations: {
|
|
373
|
+
title: "Unread Conversations",
|
|
374
|
+
readOnlyHint: true,
|
|
375
|
+
idempotentHint: true,
|
|
376
|
+
openWorldHint: true
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
name: "slack_users_search",
|
|
381
|
+
description: "Search workspace users by name, display name, or email. Case-insensitive partial match.",
|
|
382
|
+
inputSchema: {
|
|
383
|
+
type: "object",
|
|
384
|
+
properties: {
|
|
385
|
+
query: {
|
|
386
|
+
type: "string",
|
|
387
|
+
description: "Search term to match against name, display name, real name, or email"
|
|
388
|
+
},
|
|
389
|
+
limit: {
|
|
390
|
+
type: "number",
|
|
391
|
+
description: "Maximum results to return (default 20)"
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
required: ["query"]
|
|
395
|
+
},
|
|
396
|
+
annotations: {
|
|
397
|
+
title: "Search Users",
|
|
398
|
+
readOnlyHint: true,
|
|
399
|
+
idempotentHint: true,
|
|
400
|
+
openWorldHint: true
|
|
401
|
+
}
|
|
271
402
|
}
|
|
272
403
|
];
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jtalk22/slack-mcp",
|
|
3
3
|
"mcpName": "io.github.jtalk22/slack-mcp-server",
|
|
4
|
-
"version": "3.
|
|
5
|
-
"description": "Session-based Slack
|
|
4
|
+
"version": "3.2.0",
|
|
5
|
+
"description": "Session-based Slack MCP for Claude and MCP clients: local-first workflows, secure-default HTTP.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "src/server.js",
|
|
8
8
|
"bin": {
|
|
@@ -24,56 +24,52 @@
|
|
|
24
24
|
"tokens:auto": "node scripts/token-cli.js auto",
|
|
25
25
|
"tokens:clear": "node scripts/token-cli.js clear",
|
|
26
26
|
"screenshot": "node scripts/capture-screenshots.js",
|
|
27
|
+
"build:social-preview": "node scripts/build-social-preview.js",
|
|
28
|
+
"build:demo-mobile": "node scripts/build-mobile-demo.js",
|
|
29
|
+
"build:demo-mobile:gif": "node scripts/build-mobile-demo.js --gif",
|
|
27
30
|
"record-demo": "node scripts/record-demo.js",
|
|
31
|
+
"social-preview:update": "node scripts/update-github-social-preview.js --headed",
|
|
28
32
|
"cf:browser": "node scripts/cloudflare-browser-tool.js",
|
|
29
33
|
"metrics:release-health": "node scripts/collect-release-health.js",
|
|
30
34
|
"metrics:release-health:delta": "node scripts/build-release-health-delta.js",
|
|
35
|
+
"impact:push:v3": "node scripts/impact-push-v3.js --dry-run",
|
|
36
|
+
"impact:push:v3:apply": "node scripts/impact-push-v3.js --apply",
|
|
31
37
|
"verify:version-parity": "node scripts/check-version-parity.js",
|
|
32
38
|
"verify:release-dry-run": "node scripts/release-preflight.js"
|
|
33
39
|
},
|
|
34
40
|
"keywords": [
|
|
41
|
+
"claude",
|
|
35
42
|
"mcp",
|
|
36
|
-
"mcp-server",
|
|
37
43
|
"model-context-protocol",
|
|
38
44
|
"slack",
|
|
39
45
|
"slack-api",
|
|
40
|
-
"slack-mcp",
|
|
41
|
-
"slack-integration",
|
|
42
|
-
"claude",
|
|
43
46
|
"claude-desktop",
|
|
44
|
-
"claude-code",
|
|
45
|
-
"claude-connectors",
|
|
46
|
-
"anthropic",
|
|
47
|
-
"cursor",
|
|
48
|
-
"llm",
|
|
49
|
-
"automation",
|
|
50
|
-
"workflow-automation",
|
|
51
|
-
"developer-tools",
|
|
52
47
|
"cli",
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"message-search",
|
|
56
|
-
"direct-messages",
|
|
57
|
-
"channels",
|
|
58
|
-
"workspace",
|
|
48
|
+
"developer-tools",
|
|
49
|
+
"mcp-server",
|
|
59
50
|
"session-based",
|
|
51
|
+
"claude-code",
|
|
52
|
+
"local-first",
|
|
60
53
|
"session-mirroring",
|
|
61
|
-
"slack-
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"open-source"
|
|
54
|
+
"slack-mcp",
|
|
55
|
+
"secure-by-default",
|
|
56
|
+
"llm",
|
|
57
|
+
"slack-integration",
|
|
58
|
+
"ai-agents",
|
|
59
|
+
"automation",
|
|
60
|
+
"productivity"
|
|
69
61
|
],
|
|
70
|
-
"author":
|
|
62
|
+
"author": {
|
|
63
|
+
"name": "James Lambert",
|
|
64
|
+
"email": "james@revasser.nyc",
|
|
65
|
+
"url": "https://github.com/jtalk22"
|
|
66
|
+
},
|
|
71
67
|
"license": "MIT",
|
|
72
68
|
"repository": {
|
|
73
69
|
"type": "git",
|
|
74
70
|
"url": "git+https://github.com/jtalk22/slack-mcp-server.git"
|
|
75
71
|
},
|
|
76
|
-
"homepage": "https://jtalk22.github.io/slack-mcp-server/
|
|
72
|
+
"homepage": "https://jtalk22.github.io/slack-mcp-server/",
|
|
77
73
|
"bugs": {
|
|
78
74
|
"url": "https://github.com/jtalk22/slack-mcp-server/issues"
|
|
79
75
|
},
|
|
@@ -87,12 +83,15 @@
|
|
|
87
83
|
"files": [
|
|
88
84
|
"src/",
|
|
89
85
|
"lib/",
|
|
90
|
-
"public/",
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"docs/
|
|
95
|
-
"docs/
|
|
86
|
+
"public/index.html",
|
|
87
|
+
"public/share.html",
|
|
88
|
+
"scripts/setup-wizard.js",
|
|
89
|
+
"scripts/token-cli.js",
|
|
90
|
+
"docs/SETUP.md",
|
|
91
|
+
"docs/API.md",
|
|
92
|
+
"docs/TROUBLESHOOTING.md",
|
|
93
|
+
"docs/assets/icon.svg",
|
|
94
|
+
"docs/assets/icon-512.png",
|
|
96
95
|
"README.md",
|
|
97
96
|
"LICENSE",
|
|
98
97
|
"server.json",
|
package/public/index.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>Slack Web
|
|
6
|
+
<title>Slack MCP Server — Web Dashboard</title>
|
|
7
7
|
<style>
|
|
8
8
|
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&family=Space+Grotesk:wght@500;600;700&display=swap');
|
|
9
9
|
|
|
@@ -253,7 +253,11 @@
|
|
|
253
253
|
</div>
|
|
254
254
|
|
|
255
255
|
<div class="container">
|
|
256
|
-
<h1>Slack Web API <span id="status" class="status"></span></h1>
|
|
256
|
+
<h1>Slack Web API <span style="font-size:0.55em;opacity:0.5;font-weight:400;vertical-align:middle">v3.2.0</span> <span id="status" class="status"></span></h1>
|
|
257
|
+
<div style="background:rgba(240,194,70,0.08);border:1px solid rgba(240,194,70,0.2);border-radius:8px;padding:8px 14px;margin-bottom:16px;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px;font-size:13px;color:#d4c48a">
|
|
258
|
+
<span>Skip local setup? <strong style="color:#f0c246">Slack MCP Cloud</strong> gives you 16 tools with one URL — no tokens to manage.</span>
|
|
259
|
+
<a href="https://jtalk22.github.io/slack-mcp-server/cloud.html" style="color:#f0c246;font-weight:600;text-decoration:none;white-space:nowrap" target="_blank">Learn more →</a>
|
|
260
|
+
</div>
|
|
257
261
|
<div class="grid">
|
|
258
262
|
<div class="sidebar">
|
|
259
263
|
<h3>CONVERSATIONS</h3>
|
|
@@ -267,7 +271,7 @@
|
|
|
267
271
|
</div>
|
|
268
272
|
<div class="main-panel">
|
|
269
273
|
<div class="search-section">
|
|
270
|
-
<input type="text" id="searchQuery" placeholder="Search messages...">
|
|
274
|
+
<input type="text" id="searchQuery" placeholder="Search messages..." onkeypress="if(event.key==='Enter')searchMessages()">
|
|
271
275
|
<button onclick="searchMessages()">Search</button>
|
|
272
276
|
</div>
|
|
273
277
|
<h2 id="channelName">Select a conversation</h2>
|
|
@@ -377,7 +381,7 @@
|
|
|
377
381
|
try {
|
|
378
382
|
const data = await api('/conversations?types=' + types);
|
|
379
383
|
list.innerHTML = data.conversations.map(c =>
|
|
380
|
-
'<li onclick="loadHistory(\'' + c.id + '\', \'' + c.name.replace(/'/g, "
|
|
384
|
+
'<li onclick="loadHistory(\'' + c.id + '\', \'' + escapeHtml(c.name).replace(/'/g, "'") + '\', this)"><div>' + escapeHtml(c.name) + '</div><div class="type">' + escapeHtml(c.type) + '</div></li>'
|
|
381
385
|
).join('');
|
|
382
386
|
} catch (e) { list.innerHTML = '<li class="error-msg">' + e.message + '</li>'; }
|
|
383
387
|
}
|
|
@@ -397,7 +401,7 @@
|
|
|
397
401
|
const container = document.getElementById('messages');
|
|
398
402
|
if (!messages || messages.length === 0) { container.innerHTML = '<div class="loading">No messages</div>'; return; }
|
|
399
403
|
container.innerHTML = messages.map(m =>
|
|
400
|
-
'<div class="message"><div class="header"><span class="user">' + (m.user || m.user_id || 'Unknown') + '</span><span class="time">' + new Date(m.datetime).toLocaleString() + '</span></div><div class="text">' + escapeHtml(m.text || '') + '</div></div>'
|
|
404
|
+
'<div class="message"><div class="header"><span class="user">' + escapeHtml(m.user || m.user_id || 'Unknown') + '</span><span class="time">' + new Date(m.datetime).toLocaleString() + '</span></div><div class="text">' + escapeHtml(m.text || '') + '</div></div>'
|
|
401
405
|
).join('');
|
|
402
406
|
container.scrollTop = container.scrollHeight;
|
|
403
407
|
}
|
|
@@ -423,7 +427,7 @@
|
|
|
423
427
|
const data = await api('/search?q=' + encodeURIComponent(query));
|
|
424
428
|
if (data.matches && data.matches.length > 0) {
|
|
425
429
|
container.innerHTML = data.matches.map(m =>
|
|
426
|
-
'<div class="message"><div class="header"><span class="user">' + (m.user || 'Unknown') + ' in #' + m.channel + '</span><span class="time">' + new Date(m.datetime).toLocaleString() + '</span></div><div class="text">' + escapeHtml(m.text || '') + '</div></div>'
|
|
430
|
+
'<div class="message"><div class="header"><span class="user">' + escapeHtml(m.user || 'Unknown') + ' in #' + escapeHtml(m.channel || '') + '</span><span class="time">' + new Date(m.datetime).toLocaleString() + '</span></div><div class="text">' + escapeHtml(m.text || '') + '</div></div>'
|
|
427
431
|
).join('');
|
|
428
432
|
} else { container.innerHTML = '<div class="loading">No results found</div>'; }
|
|
429
433
|
} catch (e) { container.innerHTML = '<div class="error-msg">' + e.message + '</div>'; }
|
|
@@ -0,0 +1,128 @@
|
|
|
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">
|
|
6
|
+
<title>Slack MCP Server v3.2.0</title>
|
|
7
|
+
<meta name="description" content="Session-based Slack MCP for Claude. Local-first stdio/web with secure-default hosted HTTP in v3.">
|
|
8
|
+
<meta property="og:type" content="website">
|
|
9
|
+
<meta property="og:title" content="Slack MCP Server v3.2.0">
|
|
10
|
+
<meta property="og:description" content="Session-based Slack MCP for Claude. Local-first stdio/web with secure-default hosted HTTP in v3.">
|
|
11
|
+
<meta property="og:url" content="https://jtalk22.github.io/slack-mcp-server/public/share.html">
|
|
12
|
+
<meta property="og:image" content="https://jtalk22.github.io/slack-mcp-server/docs/images/social-preview-v3.png">
|
|
13
|
+
<meta property="og:image:width" content="1280">
|
|
14
|
+
<meta property="og:image:height" content="640">
|
|
15
|
+
<meta name="twitter:card" content="summary_large_image">
|
|
16
|
+
<meta name="twitter:title" content="Slack MCP Server v3.2.0">
|
|
17
|
+
<meta name="twitter:description" content="Session-based Slack MCP for Claude. Local-first stdio/web with secure-default hosted HTTP in v3.">
|
|
18
|
+
<meta name="twitter:image" content="https://jtalk22.github.io/slack-mcp-server/docs/images/social-preview-v3.png">
|
|
19
|
+
<style>
|
|
20
|
+
:root {
|
|
21
|
+
--bg-1: #0b1436;
|
|
22
|
+
--bg-2: #0e1d49;
|
|
23
|
+
--line: rgba(131, 161, 224, 0.36);
|
|
24
|
+
--text: #edf4ff;
|
|
25
|
+
--muted: #b4c4e8;
|
|
26
|
+
--link-bg: rgba(17, 57, 120, 0.7);
|
|
27
|
+
--link-bg-hover: rgba(22, 71, 148, 0.85);
|
|
28
|
+
--accent: #54d8cf;
|
|
29
|
+
}
|
|
30
|
+
* { box-sizing: border-box; }
|
|
31
|
+
body {
|
|
32
|
+
margin: 0;
|
|
33
|
+
min-height: 100vh;
|
|
34
|
+
color: var(--text);
|
|
35
|
+
background:
|
|
36
|
+
radial-gradient(900px 430px at 12% 0%, #2b4f98 0%, transparent 60%),
|
|
37
|
+
radial-gradient(980px 480px at 100% 100%, #124b8c 0%, transparent 64%),
|
|
38
|
+
linear-gradient(145deg, var(--bg-1), var(--bg-2));
|
|
39
|
+
font-family: "Space Grotesk", "IBM Plex Sans", "Segoe UI", Arial, sans-serif;
|
|
40
|
+
display: grid;
|
|
41
|
+
place-items: center;
|
|
42
|
+
padding: 20px;
|
|
43
|
+
}
|
|
44
|
+
.wrap {
|
|
45
|
+
width: min(980px, 100%);
|
|
46
|
+
border: 1px solid var(--line);
|
|
47
|
+
border-radius: 16px;
|
|
48
|
+
background: linear-gradient(165deg, rgba(17, 41, 92, 0.72), rgba(10, 22, 56, 0.9));
|
|
49
|
+
box-shadow: 0 18px 38px rgba(0, 0, 0, 0.28);
|
|
50
|
+
padding: 16px;
|
|
51
|
+
}
|
|
52
|
+
h1 {
|
|
53
|
+
margin: 0;
|
|
54
|
+
line-height: 1.08;
|
|
55
|
+
letter-spacing: -0.02em;
|
|
56
|
+
font-size: clamp(30px, 5vw, 48px);
|
|
57
|
+
}
|
|
58
|
+
.sub {
|
|
59
|
+
margin: 8px 0 14px;
|
|
60
|
+
color: var(--muted);
|
|
61
|
+
font-size: clamp(16px, 2.4vw, 22px);
|
|
62
|
+
line-height: 1.25;
|
|
63
|
+
}
|
|
64
|
+
.preview {
|
|
65
|
+
display: block;
|
|
66
|
+
border-radius: 12px;
|
|
67
|
+
overflow: hidden;
|
|
68
|
+
border: 1px solid rgba(135, 163, 225, 0.4);
|
|
69
|
+
text-decoration: none;
|
|
70
|
+
margin-bottom: 14px;
|
|
71
|
+
}
|
|
72
|
+
.preview img {
|
|
73
|
+
width: 100%;
|
|
74
|
+
display: block;
|
|
75
|
+
}
|
|
76
|
+
.links {
|
|
77
|
+
display: flex;
|
|
78
|
+
flex-wrap: wrap;
|
|
79
|
+
gap: 10px;
|
|
80
|
+
margin-bottom: 8px;
|
|
81
|
+
}
|
|
82
|
+
.links a {
|
|
83
|
+
display: inline-block;
|
|
84
|
+
text-decoration: none;
|
|
85
|
+
border: 1px solid rgba(131, 161, 224, 0.5);
|
|
86
|
+
border-radius: 10px;
|
|
87
|
+
padding: 9px 12px;
|
|
88
|
+
color: var(--text);
|
|
89
|
+
background: var(--link-bg);
|
|
90
|
+
font-weight: 600;
|
|
91
|
+
font-size: 14px;
|
|
92
|
+
}
|
|
93
|
+
.links a:hover { background: var(--link-bg-hover); }
|
|
94
|
+
.note {
|
|
95
|
+
color: #9fb4de;
|
|
96
|
+
font-size: 13px;
|
|
97
|
+
line-height: 1.45;
|
|
98
|
+
}
|
|
99
|
+
.note strong { color: var(--accent); }
|
|
100
|
+
@media (max-width: 640px) {
|
|
101
|
+
body { padding: 10px; }
|
|
102
|
+
.wrap { padding: 12px; }
|
|
103
|
+
}
|
|
104
|
+
</style>
|
|
105
|
+
</head>
|
|
106
|
+
<body>
|
|
107
|
+
<main class="wrap">
|
|
108
|
+
<h1>Slack MCP Server v3.2.0</h1>
|
|
109
|
+
<p class="sub">Give Claude full access to your Slack. Read channels, search messages, send replies, get AI summaries. Self-host free or Cloud from $19/mo.</p>
|
|
110
|
+
|
|
111
|
+
<a class="preview" href="https://github.com/jtalk22/slack-mcp-server" rel="noopener">
|
|
112
|
+
<img src="https://jtalk22.github.io/slack-mcp-server/docs/images/social-preview-v3.png" alt="Slack MCP Server social preview card">
|
|
113
|
+
</a>
|
|
114
|
+
|
|
115
|
+
<div class="links">
|
|
116
|
+
<a href="https://github.com/jtalk22/slack-mcp-server/blob/main/docs/SETUP.md" rel="noopener">Install (`--setup`)</a>
|
|
117
|
+
<a href="https://github.com/jtalk22/slack-mcp-server/blob/main/README.md#install--verify" rel="noopener">Verify (`--version/--doctor/--status`)</a>
|
|
118
|
+
<a href="https://github.com/jtalk22/slack-mcp-server/releases/latest" rel="noopener">Latest Release</a>
|
|
119
|
+
<a href="https://jtalk22.github.io/slack-mcp-server/" rel="noopener">Autoplay Demo Landing</a>
|
|
120
|
+
<a href="https://jtalk22.github.io/slack-mcp-server/docs/videos/demo-claude-mobile-20s.mp4" rel="noopener">20s Mobile Clip</a>
|
|
121
|
+
<a href="https://www.npmjs.com/package/@jtalk22/slack-mcp" rel="noopener">npm Package</a>
|
|
122
|
+
<a href="https://jtalk22.github.io/slack-mcp-server/cloud.html" rel="noopener" style="background:rgba(240,194,70,0.18);border-color:rgba(240,194,70,0.45);color:#f0c246">Cloud ($19/mo)</a>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<p class="note"><strong>Verify in 30 seconds:</strong> <code>--version</code>, <code>--doctor</code>, <code>--status</code>. Maintainer/operator: <code>jtalk22</code> (<code>james@revasser.nyc</code>).</p>
|
|
126
|
+
</main>
|
|
127
|
+
</body>
|
|
128
|
+
</html>
|
package/scripts/setup-wizard.js
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from "../lib/token-store.js";
|
|
24
24
|
|
|
25
25
|
const IS_MACOS = platform() === 'darwin';
|
|
26
|
-
const VERSION = "3.
|
|
26
|
+
const VERSION = "3.2.0";
|
|
27
27
|
const MIN_NODE_MAJOR = 20;
|
|
28
28
|
const AUTH_TEST_URL = process.env.SLACK_MCP_AUTH_TEST_URL || "https://slack.com/api/auth.test";
|
|
29
29
|
|
package/server.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.jtalk22/slack-mcp-server",
|
|
4
4
|
"title": "Slack MCP Server",
|
|
5
|
-
"description": "Session-based Slack
|
|
6
|
-
"websiteUrl": "https://jtalk22.github.io/slack-mcp-server/
|
|
5
|
+
"description": "Session-based Slack MCP for Claude and MCP clients: local-first workflows, secure-default HTTP.",
|
|
6
|
+
"websiteUrl": "https://jtalk22.github.io/slack-mcp-server/",
|
|
7
7
|
"icons": [
|
|
8
8
|
{
|
|
9
9
|
"src": "https://raw.githubusercontent.com/jtalk22/slack-mcp-server/main/docs/assets/icon-512.png",
|
|
@@ -17,12 +17,18 @@
|
|
|
17
17
|
"url": "https://github.com/jtalk22/slack-mcp-server",
|
|
18
18
|
"source": "github"
|
|
19
19
|
},
|
|
20
|
-
"version": "3.
|
|
20
|
+
"version": "3.2.0",
|
|
21
|
+
"remotes": [
|
|
22
|
+
{
|
|
23
|
+
"type": "streamable-http",
|
|
24
|
+
"url": "https://mcp.revasserlabs.com/oauth/mcp"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
21
27
|
"packages": [
|
|
22
28
|
{
|
|
23
29
|
"registryType": "npm",
|
|
24
30
|
"identifier": "@jtalk22/slack-mcp",
|
|
25
|
-
"version": "3.
|
|
31
|
+
"version": "3.2.0",
|
|
26
32
|
"transport": {
|
|
27
33
|
"type": "stdio"
|
|
28
34
|
},
|
package/src/server-http.js
CHANGED
|
@@ -27,10 +27,15 @@ import {
|
|
|
27
27
|
handleSendMessage,
|
|
28
28
|
handleGetThread,
|
|
29
29
|
handleListUsers,
|
|
30
|
+
handleAddReaction,
|
|
31
|
+
handleRemoveReaction,
|
|
32
|
+
handleConversationsMark,
|
|
33
|
+
handleConversationsUnreads,
|
|
34
|
+
handleUsersSearch,
|
|
30
35
|
} from "../lib/handlers.js";
|
|
31
36
|
|
|
32
37
|
const SERVER_NAME = "slack-mcp-server";
|
|
33
|
-
const SERVER_VERSION = "3.
|
|
38
|
+
const SERVER_VERSION = "3.2.0";
|
|
34
39
|
const PORT = process.env.PORT || 3000;
|
|
35
40
|
const HTTP_INSECURE = process.env.SLACK_MCP_HTTP_INSECURE === "1";
|
|
36
41
|
const HTTP_AUTH_TOKEN = process.env.SLACK_MCP_HTTP_AUTH_TOKEN || process.env.SLACK_API_KEY || null;
|
|
@@ -115,6 +120,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
115
120
|
return await handleGetThread(args);
|
|
116
121
|
case "slack_list_users":
|
|
117
122
|
return await handleListUsers(args);
|
|
123
|
+
case "slack_add_reaction":
|
|
124
|
+
return await handleAddReaction(args);
|
|
125
|
+
case "slack_remove_reaction":
|
|
126
|
+
return await handleRemoveReaction(args);
|
|
127
|
+
case "slack_conversations_mark":
|
|
128
|
+
return await handleConversationsMark(args);
|
|
129
|
+
case "slack_conversations_unreads":
|
|
130
|
+
return await handleConversationsUnreads(args);
|
|
131
|
+
case "slack_users_search":
|
|
132
|
+
return await handleUsersSearch(args);
|
|
118
133
|
default:
|
|
119
134
|
return {
|
|
120
135
|
content: [{
|
package/src/server.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* - Network error retry with exponential backoff
|
|
12
12
|
* - Background token health monitoring
|
|
13
13
|
*
|
|
14
|
-
* @version 3.
|
|
14
|
+
* @version 3.2.0
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -41,6 +41,11 @@ import {
|
|
|
41
41
|
handleSendMessage,
|
|
42
42
|
handleGetThread,
|
|
43
43
|
handleListUsers,
|
|
44
|
+
handleAddReaction,
|
|
45
|
+
handleRemoveReaction,
|
|
46
|
+
handleConversationsMark,
|
|
47
|
+
handleConversationsUnreads,
|
|
48
|
+
handleUsersSearch,
|
|
44
49
|
} from "../lib/handlers.js";
|
|
45
50
|
|
|
46
51
|
// Background refresh interval (4 hours)
|
|
@@ -48,7 +53,7 @@ const BACKGROUND_REFRESH_INTERVAL = 4 * 60 * 60 * 1000;
|
|
|
48
53
|
|
|
49
54
|
// Package info
|
|
50
55
|
const SERVER_NAME = "slack-mcp-server";
|
|
51
|
-
const SERVER_VERSION = "3.
|
|
56
|
+
const SERVER_VERSION = "3.2.0";
|
|
52
57
|
|
|
53
58
|
// MCP Prompts - predefined prompt templates for common Slack operations
|
|
54
59
|
const PROMPTS = [
|
|
@@ -255,6 +260,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
255
260
|
case "slack_list_users":
|
|
256
261
|
return await handleListUsers(args);
|
|
257
262
|
|
|
263
|
+
case "slack_add_reaction":
|
|
264
|
+
return await handleAddReaction(args);
|
|
265
|
+
|
|
266
|
+
case "slack_remove_reaction":
|
|
267
|
+
return await handleRemoveReaction(args);
|
|
268
|
+
|
|
269
|
+
case "slack_conversations_mark":
|
|
270
|
+
return await handleConversationsMark(args);
|
|
271
|
+
|
|
272
|
+
case "slack_conversations_unreads":
|
|
273
|
+
return await handleConversationsUnreads(args);
|
|
274
|
+
|
|
275
|
+
case "slack_users_search":
|
|
276
|
+
return await handleUsersSearch(args);
|
|
277
|
+
|
|
258
278
|
default:
|
|
259
279
|
return {
|
|
260
280
|
content: [{
|
|
@@ -306,11 +326,15 @@ async function main() {
|
|
|
306
326
|
// Use unref() so this timer doesn't prevent the process from exiting
|
|
307
327
|
// when the MCP transport closes (prevents zombie processes)
|
|
308
328
|
const backgroundTimer = setInterval(async () => {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
329
|
+
try {
|
|
330
|
+
const health = await checkTokenHealth(console);
|
|
331
|
+
if (health.refreshed) {
|
|
332
|
+
console.error("Background: tokens refreshed successfully");
|
|
333
|
+
} else if (health.critical) {
|
|
334
|
+
console.error("Background: tokens critical - open Slack in Chrome");
|
|
335
|
+
}
|
|
336
|
+
} catch (err) {
|
|
337
|
+
console.error(`Background health check failed: ${err.message}`);
|
|
314
338
|
}
|
|
315
339
|
}, BACKGROUND_REFRESH_INTERVAL);
|
|
316
340
|
backgroundTimer.unref();
|