@jtalk22/slack-mcp 3.2.4 → 4.0.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 +86 -48
- package/docs/API.md +1 -1
- package/lib/public-metadata.js +6 -5
- package/lib/public-pages.js +139 -0
- package/lib/token-store.js +2 -2
- package/package.json +11 -9
- package/public/share.html +7 -8
- package/server.json +3 -3
- package/src/server.js +1 -1
- package/src/web-server.js +18 -13
package/README.md
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
# Slack MCP Server
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@jtalk22/slack-mcp)
|
|
4
|
-
[](https://www.npmjs.com/package/@jtalk22/slack-mcp)
|
|
5
4
|
[](https://registry.modelcontextprotocol.io)
|
|
6
5
|
[](https://opensource.org/licenses/MIT)
|
|
7
6
|
|
|
8
|
-
Give
|
|
9
|
-
|
|
10
|
-
## Verify & Proof
|
|
7
|
+
Give your AI agent full Slack access. No app registration, no admin approval, no OAuth. One command, 16 tools, works with any MCP client.
|
|
11
8
|
|
|
12
9
|
```bash
|
|
13
10
|
npx -y @jtalk22/slack-mcp --setup
|
|
14
|
-
npx -y @jtalk22/slack-mcp@latest --version
|
|
15
|
-
npx -y @jtalk22/slack-mcp@latest --doctor
|
|
16
|
-
npx -y @jtalk22/slack-mcp@latest --status
|
|
17
11
|
```
|
|
18
12
|
|
|
19
|
-
[
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
> **Ask Claude to catch you up on #engineering from the last 24 hours.** Search for that deployment thread from last week. Find every message mentioning the API key. Send a reply. All from your editor.
|
|
16
|
+
|
|
17
|
+
[Interactive demo](https://jtalk22.github.io/slack-mcp-server/public/demo.html) · [Latest release](https://github.com/jtalk22/slack-mcp-server/releases/latest)
|
|
18
|
+
|
|
19
|
+
## Why This Exists
|
|
20
|
+
|
|
21
|
+
Slack's official MCP server requires a registered app, admin approval, and [doesn't work with Claude Code or GitHub Copilot](https://github.com/anthropics/claude-code/issues/30564) due to OAuth/DCR incompatibility. Screenshotting messages is not a workflow.
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
This server uses your browser's session tokens instead. If you can see it in Slack, your AI agent can see it too. No app install, no scopes, no admin.
|
|
24
|
+
|
|
25
|
+

|
|
22
26
|
|
|
23
27
|
## Tools
|
|
24
28
|
|
|
@@ -41,35 +45,19 @@ npx -y @jtalk22/slack-mcp@latest --status
|
|
|
41
45
|
| `slack_remove_reaction` | Remove an emoji reaction from a message | **destructive** |
|
|
42
46
|
| `slack_conversations_mark` | Mark a conversation as read | **destructive** |
|
|
43
47
|
|
|
44
|
-
All
|
|
45
|
-
|
|
46
|
-
\* `slack_refresh_tokens` modifies local token file only — no external Slack state.
|
|
47
|
-
|
|
48
|
-
## Cloud
|
|
49
|
-
|
|
50
|
-
Slack MCP Cloud provides 15 managed tools with hosted credential handling. Team adds 3 AI compound workflows for summaries, action items, and decisions.
|
|
51
|
-
|
|
52
|
-
| Plan | Price | Includes |
|
|
53
|
-
|------|-------|----------|
|
|
54
|
-
| Solo | $19/mo | 15 standard tools, AES-256-GCM encrypted storage, 5K requests/mo |
|
|
55
|
-
| Team | $49/mo | 15 standard + 3 AI compound tools, 3 workspaces, 25K requests/mo |
|
|
48
|
+
12 read-only, 4 write-path. All carry [MCP safety annotations](https://modelcontextprotocol.io/specification/2025-03-26/server/tools#annotations).
|
|
56
49
|
|
|
57
|
-
|
|
50
|
+
\* `slack_refresh_tokens` modifies local token file only.
|
|
58
51
|
|
|
59
|
-
|
|
52
|
+
## Install
|
|
60
53
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
**Runtime:** Node.js 20+
|
|
54
|
+
**Node.js 20+**
|
|
64
55
|
|
|
65
56
|
```bash
|
|
66
57
|
npx -y @jtalk22/slack-mcp --setup
|
|
67
|
-
npx -y @jtalk22/slack-mcp@latest --version
|
|
68
|
-
npx -y @jtalk22/slack-mcp@latest --doctor
|
|
69
|
-
npx -y @jtalk22/slack-mcp@latest --status
|
|
70
58
|
```
|
|
71
59
|
|
|
72
|
-
The setup wizard handles token extraction and validation
|
|
60
|
+
The setup wizard handles token extraction and validation.
|
|
73
61
|
|
|
74
62
|
<details>
|
|
75
63
|
<summary><strong>Claude Desktop (macOS)</strong></summary>
|
|
@@ -114,7 +102,7 @@ Edit `%APPDATA%\Claude\claude_desktop_config.json`:
|
|
|
114
102
|
</details>
|
|
115
103
|
|
|
116
104
|
<details>
|
|
117
|
-
<summary><strong>Claude Code
|
|
105
|
+
<summary><strong>Claude Code</strong></summary>
|
|
118
106
|
|
|
119
107
|
Add to `~/.claude.json`:
|
|
120
108
|
|
|
@@ -132,6 +120,41 @@ Add to `~/.claude.json`:
|
|
|
132
120
|
|
|
133
121
|
</details>
|
|
134
122
|
|
|
123
|
+
<details>
|
|
124
|
+
<summary><strong>Cursor / Copilot / Other MCP clients</strong></summary>
|
|
125
|
+
|
|
126
|
+
Any client that supports stdio MCP servers works. Add to your client's MCP config:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"slack": {
|
|
131
|
+
"command": "npx",
|
|
132
|
+
"args": ["-y", "@jtalk22/slack-mcp"],
|
|
133
|
+
"env": {
|
|
134
|
+
"SLACK_TOKEN": "xoxc-your-token",
|
|
135
|
+
"SLACK_COOKIE": "xoxd-your-cookie"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
On macOS, tokens are auto-extracted from Chrome — `env` block is optional.
|
|
142
|
+
|
|
143
|
+
</details>
|
|
144
|
+
|
|
145
|
+
<details>
|
|
146
|
+
<summary><strong>Claude Web / Remote MCP</strong></summary>
|
|
147
|
+
|
|
148
|
+
For browser-based clients that can't run local processes, use the hosted HTTP endpoint:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
https://mcp.revasserlabs.com/oauth/mcp
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Add this as a remote MCP server in your client's settings. Transport: Streamable HTTP. Auth: OAuth 2.1 + PKCE.
|
|
155
|
+
|
|
156
|
+
</details>
|
|
157
|
+
|
|
135
158
|
<details>
|
|
136
159
|
<summary><strong>Docker</strong></summary>
|
|
137
160
|
|
|
@@ -154,7 +177,19 @@ docker pull ghcr.io/jtalk22/slack-mcp-server:latest
|
|
|
154
177
|
|
|
155
178
|
</details>
|
|
156
179
|
|
|
157
|
-
Restart
|
|
180
|
+
Restart your client after configuration. Full setup: [docs/SETUP.md](docs/SETUP.md)
|
|
181
|
+
|
|
182
|
+
## How It Works
|
|
183
|
+
|
|
184
|
+
Session tokens (`xoxc-` + `xoxd-`) from your browser. If you can see it in Slack, this server can see it too.
|
|
185
|
+
|
|
186
|
+
**Token persistence** — four-layer fallback:
|
|
187
|
+
1. Environment variables (`SLACK_TOKEN`, `SLACK_COOKIE`)
|
|
188
|
+
2. Token file (`~/.slack-mcp-tokens.json`, chmod 600)
|
|
189
|
+
3. macOS Keychain (encrypted)
|
|
190
|
+
4. Chrome auto-extraction (macOS)
|
|
191
|
+
|
|
192
|
+
Tokens expire. The server notices before you do — proactive health monitoring, automatic refresh on macOS, warnings when tokens age out. File writes are atomic (temp file → chmod → rename) to prevent corruption. Concurrent refresh attempts are mutex-locked.
|
|
158
193
|
|
|
159
194
|
## Hosted HTTP Mode
|
|
160
195
|
|
|
@@ -172,32 +207,31 @@ Details: [docs/DEPLOYMENT-MODES.md](docs/DEPLOYMENT-MODES.md)
|
|
|
172
207
|
|
|
173
208
|
## Troubleshooting
|
|
174
209
|
|
|
175
|
-
**Tokens expired:** Run `npx -y @jtalk22/slack-mcp --setup` or use `slack_refresh_tokens`
|
|
210
|
+
**Tokens expired:** Run `npx -y @jtalk22/slack-mcp --setup` or use `slack_refresh_tokens` (macOS).
|
|
176
211
|
|
|
177
|
-
**DMs not showing:** Use `slack_list_conversations` with `discover_dms=true
|
|
212
|
+
**DMs not showing:** Use `slack_list_conversations` with `discover_dms=true`.
|
|
178
213
|
|
|
179
|
-
**
|
|
214
|
+
**Client not seeing tools:** Check JSON syntax in config, restart client fully.
|
|
180
215
|
|
|
181
216
|
More: [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md)
|
|
182
217
|
|
|
183
218
|
## Docs
|
|
184
219
|
|
|
185
|
-
- [Setup Guide](docs/SETUP.md)
|
|
186
|
-
- [API Reference](docs/API.md)
|
|
187
|
-
- [
|
|
188
|
-
- [
|
|
189
|
-
- [
|
|
190
|
-
- [
|
|
191
|
-
- [
|
|
192
|
-
- [Docs Index](docs/INDEX.md) — Full documentation index
|
|
220
|
+
- [Setup Guide](docs/SETUP.md)
|
|
221
|
+
- [API Reference](docs/API.md)
|
|
222
|
+
- [Architecture](docs/ARCHITECTURE.md)
|
|
223
|
+
- [Deployment Modes](docs/DEPLOYMENT-MODES.md)
|
|
224
|
+
- [Use Case Recipes](docs/USE_CASE_RECIPES.md)
|
|
225
|
+
- [Troubleshooting](docs/TROUBLESHOOTING.md)
|
|
226
|
+
- [Compatibility](docs/COMPATIBILITY.md)
|
|
193
227
|
|
|
194
228
|
## Security
|
|
195
229
|
|
|
196
|
-
- Token files
|
|
197
|
-
- macOS Keychain
|
|
230
|
+
- Token files: `chmod 600` (owner-only)
|
|
231
|
+
- macOS Keychain encrypted backup
|
|
198
232
|
- Web server binds to localhost only
|
|
199
|
-
- API keys
|
|
200
|
-
- See [SECURITY.md](SECURITY.md)
|
|
233
|
+
- API keys: `crypto.randomBytes`
|
|
234
|
+
- See [SECURITY.md](SECURITY.md)
|
|
201
235
|
|
|
202
236
|
## Contributing
|
|
203
237
|
|
|
@@ -209,4 +243,8 @@ MIT — See [LICENSE](LICENSE)
|
|
|
209
243
|
|
|
210
244
|
## Disclaimer
|
|
211
245
|
|
|
212
|
-
|
|
246
|
+
Not affiliated with Slack Technologies, Inc. Uses browser session credentials — check your workspace's acceptable use policy.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
Managed hosting available — [mcp.revasserlabs.com](https://mcp.revasserlabs.com)
|
package/docs/API.md
CHANGED
package/lib/public-metadata.js
CHANGED
|
@@ -9,13 +9,14 @@ export const RELEASE_VERSION = packageJson.version;
|
|
|
9
9
|
export const PUBLIC_METADATA = Object.freeze({
|
|
10
10
|
projectName: "slack-mcp-server",
|
|
11
11
|
packageName: packageJson.name,
|
|
12
|
+
canonicalShortDescription: packageJson.description,
|
|
12
13
|
canonicalRepoUrl: "https://github.com/jtalk22/slack-mcp-server",
|
|
13
14
|
canonicalSiteUrl: "https://mcp.revasserlabs.com",
|
|
15
|
+
cloudPricingUrl: "https://mcp.revasserlabs.com/pricing",
|
|
16
|
+
cloudDocsUrl: "https://mcp.revasserlabs.com/docs",
|
|
17
|
+
cloudSecurityUrl: "https://mcp.revasserlabs.com/security",
|
|
18
|
+
cloudSupportUrl: "https://mcp.revasserlabs.com/support",
|
|
19
|
+
cloudStatusUrl: "https://mcp.revasserlabs.com/status",
|
|
14
20
|
supportEmail: "support@revasserlabs.com",
|
|
15
|
-
privacyEmail: "privacy@revasserlabs.com",
|
|
16
21
|
selfHostedToolCount: 16,
|
|
17
|
-
cloudManagedToolCount: 15,
|
|
18
|
-
teamAiWorkflowCount: 3,
|
|
19
|
-
cloudSoloPrice: "$19/mo",
|
|
20
|
-
cloudTeamPrice: "$49/mo",
|
|
21
22
|
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
import { PUBLIC_METADATA } from "./public-metadata.js";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const ROOT = resolve(__dirname, "..");
|
|
9
|
+
const TEMPLATE_DIR = resolve(ROOT, "templates", "public-pages");
|
|
10
|
+
|
|
11
|
+
const GITHUB_PAGES_ROOT = "https://jtalk22.github.io/slack-mcp-server";
|
|
12
|
+
const GITHUB_DOCS_ROOT = `${PUBLIC_METADATA.canonicalRepoUrl}/blob/main/docs`;
|
|
13
|
+
const SOCIAL_IMAGE_URL = `${GITHUB_PAGES_ROOT}/docs/images/social-preview-v3.png`;
|
|
14
|
+
const ICON_URL = `${GITHUB_PAGES_ROOT}/docs/assets/icon-512.png`;
|
|
15
|
+
const NPM_URL = "https://www.npmjs.com/package/@jtalk22/slack-mcp";
|
|
16
|
+
const RELEASES_URL = `${PUBLIC_METADATA.canonicalRepoUrl}/releases/latest`;
|
|
17
|
+
const SETUP_URL = `${PUBLIC_METADATA.canonicalRepoUrl}/blob/main/docs/SETUP.md`;
|
|
18
|
+
const DEMO_VIDEO_URL = `${GITHUB_PAGES_ROOT}/docs/videos/demo-claude-mobile-20s.mp4`;
|
|
19
|
+
|
|
20
|
+
function template(name) {
|
|
21
|
+
return readFileSync(resolve(TEMPLATE_DIR, name), "utf8");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function replaceTokens(source, replacements) {
|
|
25
|
+
return source.replace(/\{\{([A-Z0-9_]+)\}\}/g, (match, key) => {
|
|
26
|
+
if (!(key in replacements)) {
|
|
27
|
+
throw new Error(`Missing template token: ${key}`);
|
|
28
|
+
}
|
|
29
|
+
return replacements[key];
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function rootDecisionPanel() {
|
|
34
|
+
return `
|
|
35
|
+
<section class="stage" style="padding-top:0">
|
|
36
|
+
<div class="decision-grid" aria-label="Self-host info">
|
|
37
|
+
<article class="decision-card">
|
|
38
|
+
<span class="decision-label">Self-host</span>
|
|
39
|
+
<h2>${PUBLIC_METADATA.selfHostedToolCount} tools and full operator control.</h2>
|
|
40
|
+
<p>Session-based auth, stdio transport. Works with Claude, ChatGPT, Cursor, Copilot, Gemini, Windsurf, and any other MCP client.</p>
|
|
41
|
+
<ul>
|
|
42
|
+
<li>stdio, web, and Docker paths stay fully under your control</li>
|
|
43
|
+
<li>No OAuth app registration or admin approval needed</li>
|
|
44
|
+
<li>Token persistence with automatic refresh on macOS</li>
|
|
45
|
+
</ul>
|
|
46
|
+
<p class="decision-links"><a href="${SETUP_URL}">Setup guide</a> · <a href="${RELEASES_URL}">Latest release</a> · <a href="${NPM_URL}">npm</a></p>
|
|
47
|
+
</article>
|
|
48
|
+
</div>
|
|
49
|
+
</section>
|
|
50
|
+
`.trim();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function shareLinks() {
|
|
54
|
+
return `
|
|
55
|
+
<a href="${SETUP_URL}" rel="noopener">Install (\`--setup\`)</a>
|
|
56
|
+
<a href="${SETUP_URL}" rel="noopener">Verify (\`--version/--doctor/--status\`)</a>
|
|
57
|
+
<a href="${RELEASES_URL}" rel="noopener">Latest Release</a>
|
|
58
|
+
<a href="${GITHUB_PAGES_ROOT}/" rel="noopener">Autoplay Demo Landing</a>
|
|
59
|
+
<a href="${DEMO_VIDEO_URL}" rel="noopener">20s Mobile Clip</a>
|
|
60
|
+
<a href="${NPM_URL}" rel="noopener">npm Package</a>
|
|
61
|
+
<a href="${PUBLIC_METADATA.canonicalSiteUrl}" rel="noopener" style="background:rgba(240,194,70,0.18);border-color:rgba(240,194,70,0.45);color:#f0c246">Cloud</a>
|
|
62
|
+
`.trim();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function shareNote() {
|
|
66
|
+
return `<strong>Verify in 30 seconds:</strong> <code>--version</code>, <code>--doctor</code>, <code>--status</code>. Self-host gives ${PUBLIC_METADATA.selfHostedToolCount} tools with session-based auth. Works with any MCP client — Claude, ChatGPT, Cursor, Copilot, Gemini, Windsurf. Managed hosting available at <a href="${PUBLIC_METADATA.canonicalSiteUrl}">mcp.revasserlabs.com</a>.`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function demoLinks() {
|
|
70
|
+
return `
|
|
71
|
+
<a href="${PUBLIC_METADATA.canonicalSiteUrl}" target="_blank" rel="noopener noreferrer" style="background:rgba(240,194,70,0.18);border-color:rgba(240,194,70,0.45);color:#f0c246">Cloud</a>
|
|
72
|
+
<a href="${NPM_URL}" target="_blank" rel="noopener noreferrer">npm Install</a>
|
|
73
|
+
<a href="${SETUP_URL}" target="_blank" rel="noopener noreferrer">Setup Guide</a>
|
|
74
|
+
`.trim();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function demoNote() {
|
|
78
|
+
return `Self-host free for ${PUBLIC_METADATA.selfHostedToolCount} tools with session-based auth. Works with Claude, ChatGPT, Cursor, Copilot, Gemini, Windsurf, and any other MCP client. No OAuth app, no admin approval. Managed hosting available at <a href="${PUBLIC_METADATA.canonicalSiteUrl}" target="_blank" rel="noopener noreferrer">mcp.revasserlabs.com</a>.`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function demoFooterLinks() {
|
|
82
|
+
return `<a href="${PUBLIC_METADATA.canonicalRepoUrl}">GitHub</a> · <a href="${NPM_URL}" style="color:#94a3b8;text-decoration:none;font-size:0.875rem">npm</a> · <a href="${PUBLIC_METADATA.canonicalSiteUrl}" style="color:#f0c246;text-decoration:none;font-size:0.875rem">Cloud</a>`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function commonTokens() {
|
|
86
|
+
return {
|
|
87
|
+
CANONICAL_SITE_URL: PUBLIC_METADATA.canonicalSiteUrl,
|
|
88
|
+
CLOUD_PRICING_URL: PUBLIC_METADATA.cloudPricingUrl,
|
|
89
|
+
CLOUD_WORKFLOWS_URL: PUBLIC_METADATA.canonicalSiteUrl + "/workflows",
|
|
90
|
+
CLOUD_OFFICIAL_COMPARISON_URL: PUBLIC_METADATA.canonicalSiteUrl + "/official-slack-mcp-vs-managed",
|
|
91
|
+
CLOUD_GEMINI_CLI_URL: PUBLIC_METADATA.canonicalSiteUrl + "/gemini-cli",
|
|
92
|
+
CLOUD_READINESS_URL: PUBLIC_METADATA.canonicalSiteUrl + "/readiness",
|
|
93
|
+
CLOUD_DOCS_URL: PUBLIC_METADATA.cloudDocsUrl,
|
|
94
|
+
CLOUD_SECURITY_URL: PUBLIC_METADATA.cloudSecurityUrl,
|
|
95
|
+
CLOUD_PROCUREMENT_URL: PUBLIC_METADATA.canonicalSiteUrl + "/procurement",
|
|
96
|
+
CLOUD_MARKETPLACE_READINESS_URL: PUBLIC_METADATA.canonicalSiteUrl + "/marketplace-readiness",
|
|
97
|
+
CLOUD_SUPPORT_URL: PUBLIC_METADATA.cloudSupportUrl,
|
|
98
|
+
CLOUD_DEPLOYMENT_URL: PUBLIC_METADATA.canonicalSiteUrl + "/deployment",
|
|
99
|
+
CLOUD_STATUS_URL: PUBLIC_METADATA.cloudStatusUrl,
|
|
100
|
+
CLOUD_SELF_HOST_URL: PUBLIC_METADATA.canonicalSiteUrl + "/self-host",
|
|
101
|
+
CLOUD_ACCOUNT_URL: PUBLIC_METADATA.canonicalSiteUrl + "/account",
|
|
102
|
+
GITHUB_REPO_URL: PUBLIC_METADATA.canonicalRepoUrl,
|
|
103
|
+
GITHUB_PAGES_ROOT,
|
|
104
|
+
GITHUB_DOCS_ROOT,
|
|
105
|
+
ICON_URL,
|
|
106
|
+
SOCIAL_IMAGE_URL,
|
|
107
|
+
NPM_URL,
|
|
108
|
+
RELEASES_URL,
|
|
109
|
+
SETUP_URL,
|
|
110
|
+
RELEASE_HEALTH_URL: RELEASES_URL,
|
|
111
|
+
VERSION_PARITY_URL: RELEASES_URL,
|
|
112
|
+
RUNBOOK_URL: SETUP_URL,
|
|
113
|
+
SELF_HOSTED_TOOL_COUNT: String(PUBLIC_METADATA.selfHostedToolCount),
|
|
114
|
+
CLOUD_MANAGED_TOOL_COUNT: "15",
|
|
115
|
+
TEAM_AI_WORKFLOW_COUNT: "3",
|
|
116
|
+
CLOUD_SOLO_PRICE: "$19/mo",
|
|
117
|
+
CLOUD_TEAM_PRICE: "$49/mo",
|
|
118
|
+
CLOUD_TURNKEY_LAUNCH_PRICE: "$2.5k+",
|
|
119
|
+
CLOUD_MANAGED_RELIABILITY_PRICE: "$800/mo+",
|
|
120
|
+
SUPPORT_EMAIL: PUBLIC_METADATA.supportEmail,
|
|
121
|
+
ROOT_DECISION_PANEL: rootDecisionPanel(),
|
|
122
|
+
SHARE_LINKS: shareLinks(),
|
|
123
|
+
SHARE_NOTE: shareNote(),
|
|
124
|
+
DEMO_LINKS: demoLinks(),
|
|
125
|
+
DEMO_NOTE: demoNote(),
|
|
126
|
+
DEMO_FOOTER_LINKS: demoFooterLinks(),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function buildPublicPages() {
|
|
131
|
+
const tokens = commonTokens();
|
|
132
|
+
return {
|
|
133
|
+
"index.html": replaceTokens(template("index.html.tpl"), tokens),
|
|
134
|
+
"public/share.html": replaceTokens(template("share.html.tpl"), tokens),
|
|
135
|
+
"public/demo.html": replaceTokens(template("demo.html.tpl"), tokens),
|
|
136
|
+
"public/demo-video.html": replaceTokens(template("demo-video.html.tpl"), tokens),
|
|
137
|
+
"public/demo-claude.html": replaceTokens(template("demo-claude.html.tpl"), tokens),
|
|
138
|
+
};
|
|
139
|
+
}
|
package/lib/token-store.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* 4. Chrome auto-extraction (fallback)
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { readFileSync, writeFileSync, existsSync, renameSync, unlinkSync } from "fs";
|
|
11
|
+
import { readFileSync, writeFileSync, existsSync, renameSync, unlinkSync, chmodSync } from "fs";
|
|
12
12
|
import { homedir, platform } from "os";
|
|
13
13
|
import { join } from "path";
|
|
14
14
|
import { execSync, execFileSync } from "child_process";
|
|
@@ -79,7 +79,7 @@ function atomicWriteSync(filePath, content) {
|
|
|
79
79
|
try {
|
|
80
80
|
writeFileSync(tempPath, content);
|
|
81
81
|
if (IS_MACOS || platform() === 'linux') {
|
|
82
|
-
try {
|
|
82
|
+
try { chmodSync(tempPath, 0o600); } catch {}
|
|
83
83
|
}
|
|
84
84
|
renameSync(tempPath, filePath); // Atomic on POSIX systems
|
|
85
85
|
} catch (e) {
|
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": "
|
|
5
|
-
"description": "Session-based
|
|
4
|
+
"version": "4.0.0",
|
|
5
|
+
"description": "Slack MCP server. Session-based auth, 16 tools, stdio transport. Works with any MCP client.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "src/server.js",
|
|
8
8
|
"bin": {
|
|
@@ -25,19 +25,19 @@
|
|
|
25
25
|
"tokens:clear": "node scripts/token-cli.js clear",
|
|
26
26
|
"screenshot": "node scripts/capture-screenshots.js",
|
|
27
27
|
"build:social-preview": "node scripts/build-social-preview.js",
|
|
28
|
+
"build:public-pages": "node scripts/generate-public-pages.js",
|
|
28
29
|
"build:demo-mobile": "node scripts/build-mobile-demo.js",
|
|
29
30
|
"build:demo-mobile:gif": "node scripts/build-mobile-demo.js --gif",
|
|
30
31
|
"record-demo": "node scripts/record-demo.js",
|
|
31
32
|
"social-preview:update": "node scripts/update-github-social-preview.js --headed",
|
|
32
33
|
"cf:browser": "node scripts/cloudflare-browser-tool.js",
|
|
33
|
-
"metrics:release-health": "node scripts/collect-release-health.js",
|
|
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",
|
|
37
34
|
"verify:attribution-guardrail": "node scripts/verify-attribution-guardrail.js",
|
|
35
|
+
"verify:public-pages": "node scripts/verify-generated-public-pages.js",
|
|
38
36
|
"verify:version-parity": "node scripts/check-version-parity.js",
|
|
39
37
|
"verify:public-surface": "node scripts/check-public-surface-integrity.js",
|
|
40
|
-
"verify:release-dry-run": "node scripts/release-preflight.js"
|
|
38
|
+
"verify:release-dry-run": "node scripts/release-preflight.js",
|
|
39
|
+
"smoke:browser": "node scripts/browser-smoke.js",
|
|
40
|
+
"smoke:browser:live": "node scripts/browser-smoke.js --mode live"
|
|
41
41
|
},
|
|
42
42
|
"keywords": [
|
|
43
43
|
"claude",
|
|
@@ -51,7 +51,9 @@
|
|
|
51
51
|
"mcp-server",
|
|
52
52
|
"session-based",
|
|
53
53
|
"claude-code",
|
|
54
|
+
"gemini-cli",
|
|
54
55
|
"local-first",
|
|
56
|
+
"remote-mcp",
|
|
55
57
|
"session-mirroring",
|
|
56
58
|
"slack-mcp",
|
|
57
59
|
"secure-by-default",
|
|
@@ -62,9 +64,9 @@
|
|
|
62
64
|
"productivity"
|
|
63
65
|
],
|
|
64
66
|
"author": {
|
|
65
|
-
"name": "
|
|
67
|
+
"name": "Revasser",
|
|
66
68
|
"email": "support@revasserlabs.com",
|
|
67
|
-
"url": "https://
|
|
69
|
+
"url": "https://mcp.revasserlabs.com"
|
|
68
70
|
},
|
|
69
71
|
"license": "MIT",
|
|
70
72
|
"repository": {
|
package/public/share.html
CHANGED
|
@@ -4,18 +4,19 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>Slack MCP Server</title>
|
|
7
|
-
<meta name="description" content="Session-based Slack MCP for Claude.
|
|
7
|
+
<meta name="description" content="Session-based Slack MCP for Claude. Self-host locally or use the managed Cloud path with Gemini CLI support, pricing, security/procurement review, deployment review, and hosted credentials.">
|
|
8
8
|
<meta property="og:type" content="website">
|
|
9
9
|
<meta property="og:title" content="Slack MCP Server">
|
|
10
|
-
<meta property="og:description" content="Session-based Slack MCP for Claude. Self-host 16 tools for free or use Cloud for 15 managed tools and support.">
|
|
10
|
+
<meta property="og:description" content="Session-based Slack MCP for Claude. Self-host 16 tools for free or use Cloud for 15 managed tools, Gemini CLI support, security/procurement review, deployment review, and support.">
|
|
11
11
|
<meta property="og:url" content="https://jtalk22.github.io/slack-mcp-server/public/share.html">
|
|
12
12
|
<meta property="og:image" content="https://jtalk22.github.io/slack-mcp-server/docs/images/social-preview-v3.png">
|
|
13
13
|
<meta property="og:image:width" content="1280">
|
|
14
14
|
<meta property="og:image:height" content="640">
|
|
15
15
|
<meta name="twitter:card" content="summary_large_image">
|
|
16
16
|
<meta name="twitter:title" content="Slack MCP Server">
|
|
17
|
-
<meta name="twitter:description" content="Session-based Slack MCP for Claude. Self-host 16 tools for free or use Cloud for 15 managed tools and support.">
|
|
17
|
+
<meta name="twitter:description" content="Session-based Slack MCP for Claude. Self-host 16 tools for free or use Cloud for 15 managed tools, Gemini CLI support, security/procurement review, deployment review, and support.">
|
|
18
18
|
<meta name="twitter:image" content="https://jtalk22.github.io/slack-mcp-server/docs/images/social-preview-v3.png">
|
|
19
|
+
<link rel="icon" href="https://jtalk22.github.io/slack-mcp-server/docs/assets/icon-512.png" type="image/png">
|
|
19
20
|
<style>
|
|
20
21
|
:root {
|
|
21
22
|
--bg-1: #0b1436;
|
|
@@ -106,25 +107,23 @@
|
|
|
106
107
|
<body>
|
|
107
108
|
<main class="wrap">
|
|
108
109
|
<h1>Slack MCP Server</h1>
|
|
109
|
-
<p class="sub">Give Claude full access to your Slack. Self-host 16 tools for free, or use Cloud for 15 managed tools
|
|
110
|
+
<p class="sub">Give Claude full access to your Slack. Self-host 16 tools for free, or use Cloud for 15 managed tools, Gemini CLI support, hosted credentials, rollout support, and buyer-facing security review.</p>
|
|
110
111
|
|
|
111
112
|
<a class="preview" href="https://github.com/jtalk22/slack-mcp-server" rel="noopener">
|
|
112
113
|
<img src="https://jtalk22.github.io/slack-mcp-server/docs/images/social-preview-v3.png" alt="Slack MCP Server social preview card">
|
|
113
114
|
</a>
|
|
114
115
|
|
|
115
116
|
<div class="links">
|
|
116
|
-
|
|
117
|
+
<a href="https://github.com/jtalk22/slack-mcp-server/blob/main/docs/SETUP.md" rel="noopener">Install (`--setup`)</a>
|
|
117
118
|
<a href="https://github.com/jtalk22/slack-mcp-server/blob/main/docs/SETUP.md" rel="noopener">Verify (`--version/--doctor/--status`)</a>
|
|
118
119
|
<a href="https://github.com/jtalk22/slack-mcp-server/releases/latest" rel="noopener">Latest Release</a>
|
|
119
|
-
<a href="https://github.com/jtalk22/slack-mcp-server/issues/new?template=deployment-intake.md" rel="noopener">Deployment Intake</a>
|
|
120
|
-
<a href="https://github.com/jtalk22/slack-mcp-server/blob/main/docs/SUPPORT-BOUNDARIES.md" rel="noopener">Support</a>
|
|
121
120
|
<a href="https://jtalk22.github.io/slack-mcp-server/" rel="noopener">Autoplay Demo Landing</a>
|
|
122
121
|
<a href="https://jtalk22.github.io/slack-mcp-server/docs/videos/demo-claude-mobile-20s.mp4" rel="noopener">20s Mobile Clip</a>
|
|
123
122
|
<a href="https://www.npmjs.com/package/@jtalk22/slack-mcp" rel="noopener">npm Package</a>
|
|
124
123
|
<a href="https://mcp.revasserlabs.com" rel="noopener" style="background:rgba(240,194,70,0.18);border-color:rgba(240,194,70,0.45);color:#f0c246">Cloud</a>
|
|
125
124
|
</div>
|
|
126
125
|
|
|
127
|
-
<p class="note"><strong>Verify in 30 seconds:</strong> <code>--version</code>, <code>--doctor</code>, <code>--status</code>.
|
|
126
|
+
<p class="note"><strong>Verify in 30 seconds:</strong> <code>--version</code>, <code>--doctor</code>, <code>--status</code>. Self-host gives 16 tools with session-based auth. Works with any MCP client — Claude, ChatGPT, Cursor, Copilot, Gemini, Windsurf. Managed hosting available at <a href="https://mcp.revasserlabs.com">mcp.revasserlabs.com</a>.</p>
|
|
128
127
|
</main>
|
|
129
128
|
</body>
|
|
130
129
|
</html>
|
package/server.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
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
|
|
5
|
+
"description": "Slack MCP server. Session-based auth, 16 tools, stdio transport. Works with any MCP client.",
|
|
6
6
|
"websiteUrl": "https://mcp.revasserlabs.com",
|
|
7
7
|
"icons": [
|
|
8
8
|
{
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"url": "https://github.com/jtalk22/slack-mcp-server",
|
|
18
18
|
"source": "github"
|
|
19
19
|
},
|
|
20
|
-
"version": "
|
|
20
|
+
"version": "4.0.0",
|
|
21
21
|
"remotes": [
|
|
22
22
|
{
|
|
23
23
|
"type": "streamable-http",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
{
|
|
29
29
|
"registryType": "npm",
|
|
30
30
|
"identifier": "@jtalk22/slack-mcp",
|
|
31
|
-
"version": "
|
|
31
|
+
"version": "4.0.0",
|
|
32
32
|
"transport": {
|
|
33
33
|
"type": "stdio"
|
|
34
34
|
},
|
package/src/server.js
CHANGED
|
@@ -150,7 +150,7 @@ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
|
150
150
|
}
|
|
151
151
|
case "summarize-channel": {
|
|
152
152
|
const channelId = args?.channel_id || "";
|
|
153
|
-
const days = parseInt(args?.days) || 7;
|
|
153
|
+
const days = parseInt(args?.days, 10) || 7;
|
|
154
154
|
const since = Math.floor(Date.now() / 1000) - (days * 24 * 60 * 60);
|
|
155
155
|
return {
|
|
156
156
|
messages: [
|
package/src/web-server.js
CHANGED
|
@@ -11,8 +11,7 @@ import express from "express";
|
|
|
11
11
|
import { randomBytes } from "crypto";
|
|
12
12
|
import { fileURLToPath } from "url";
|
|
13
13
|
import { dirname, join } from "path";
|
|
14
|
-
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
15
|
-
import { execSync } from "child_process";
|
|
14
|
+
import { existsSync, readFileSync, writeFileSync, chmodSync } from "fs";
|
|
16
15
|
import { homedir } from "os";
|
|
17
16
|
import { loadTokensReadOnly } from "../lib/token-store.js";
|
|
18
17
|
import { PUBLIC_METADATA, RELEASE_VERSION } from "../lib/public-metadata.js";
|
|
@@ -60,7 +59,7 @@ function getOrCreateAPIKey() {
|
|
|
60
59
|
const newKey = `smcp_${randomBytes(24).toString('base64url')}`;
|
|
61
60
|
try {
|
|
62
61
|
writeFileSync(API_KEY_FILE, newKey);
|
|
63
|
-
|
|
62
|
+
chmodSync(API_KEY_FILE, 0o600);
|
|
64
63
|
} catch {}
|
|
65
64
|
|
|
66
65
|
return newKey;
|
|
@@ -98,6 +97,12 @@ app.use((req, res, next) => {
|
|
|
98
97
|
next();
|
|
99
98
|
});
|
|
100
99
|
|
|
100
|
+
function safeParseInt(value, fallback, max = 10000) {
|
|
101
|
+
const n = parseInt(value, 10);
|
|
102
|
+
if (isNaN(n) || n < 1) return fallback;
|
|
103
|
+
return Math.min(n, max);
|
|
104
|
+
}
|
|
105
|
+
|
|
101
106
|
// API Key authentication
|
|
102
107
|
function authenticate(req, res, next) {
|
|
103
108
|
const authHeader = req.headers.authorization;
|
|
@@ -209,7 +214,7 @@ app.get("/conversations", authenticate, async (req, res) => {
|
|
|
209
214
|
try {
|
|
210
215
|
const result = await handleListConversations({
|
|
211
216
|
types: req.query.types || "im,mpim",
|
|
212
|
-
limit:
|
|
217
|
+
limit: safeParseInt(req.query.limit, 100)
|
|
213
218
|
});
|
|
214
219
|
res.json(extractContent(result));
|
|
215
220
|
} catch (e) {
|
|
@@ -222,7 +227,7 @@ app.get("/conversations/unreads", authenticate, async (req, res) => {
|
|
|
222
227
|
try {
|
|
223
228
|
const result = await handleConversationsUnreads({
|
|
224
229
|
types: req.query.types || "im,mpim,public_channel,private_channel",
|
|
225
|
-
limit:
|
|
230
|
+
limit: safeParseInt(req.query.limit, 50)
|
|
226
231
|
});
|
|
227
232
|
res.json(extractContent(result));
|
|
228
233
|
} catch (e) {
|
|
@@ -235,7 +240,7 @@ app.get("/conversations/:id/history", authenticate, async (req, res) => {
|
|
|
235
240
|
try {
|
|
236
241
|
const result = await handleConversationsHistory({
|
|
237
242
|
channel_id: req.params.id,
|
|
238
|
-
limit:
|
|
243
|
+
limit: safeParseInt(req.query.limit, 50),
|
|
239
244
|
oldest: req.query.oldest,
|
|
240
245
|
latest: req.query.latest,
|
|
241
246
|
resolve_users: req.query.resolve_users !== "false"
|
|
@@ -253,7 +258,7 @@ app.get("/conversations/:id/full", authenticate, async (req, res) => {
|
|
|
253
258
|
channel_id: req.params.id,
|
|
254
259
|
oldest: req.query.oldest,
|
|
255
260
|
latest: req.query.latest,
|
|
256
|
-
max_messages:
|
|
261
|
+
max_messages: safeParseInt(req.query.max_messages, 2000, 50000),
|
|
257
262
|
include_threads: req.query.include_threads !== "false",
|
|
258
263
|
output_file: req.query.output_file
|
|
259
264
|
});
|
|
@@ -312,7 +317,7 @@ app.get("/search", authenticate, async (req, res) => {
|
|
|
312
317
|
}
|
|
313
318
|
const result = await handleSearchMessages({
|
|
314
319
|
query: req.query.q,
|
|
315
|
-
count:
|
|
320
|
+
count: safeParseInt(req.query.count, 20)
|
|
316
321
|
});
|
|
317
322
|
res.json(extractContent(result));
|
|
318
323
|
} catch (e) {
|
|
@@ -347,7 +352,7 @@ app.post("/messages", authenticate, async (req, res) => {
|
|
|
347
352
|
app.get("/users", authenticate, async (req, res) => {
|
|
348
353
|
try {
|
|
349
354
|
const result = await handleListUsers({
|
|
350
|
-
limit:
|
|
355
|
+
limit: safeParseInt(req.query.limit, 100)
|
|
351
356
|
});
|
|
352
357
|
res.json(extractContent(result));
|
|
353
358
|
} catch (e) {
|
|
@@ -369,7 +374,7 @@ app.get("/users/search", authenticate, async (req, res) => {
|
|
|
369
374
|
}
|
|
370
375
|
const result = await handleUsersSearch({
|
|
371
376
|
query: req.query.q,
|
|
372
|
-
limit:
|
|
377
|
+
limit: safeParseInt(req.query.limit, 20)
|
|
373
378
|
});
|
|
374
379
|
res.json(extractContent(result));
|
|
375
380
|
} catch (e) {
|
|
@@ -452,9 +457,9 @@ async function main() {
|
|
|
452
457
|
console.error(`\n${"═".repeat(60)}`);
|
|
453
458
|
console.error(` Slack Web API Server v${RELEASE_VERSION}`);
|
|
454
459
|
console.error(`${"═".repeat(60)}`);
|
|
455
|
-
console.error(`\n Dashboard: http://localhost:${PORT}/?key=${API_KEY}
|
|
456
|
-
console.error(`\n API Key: ${API_KEY}`);
|
|
457
|
-
console.error(`\n curl -H "Authorization: Bearer
|
|
460
|
+
console.error(`\n Dashboard: http://localhost:${PORT}/?key=${API_KEY.slice(0, 8)}...`);
|
|
461
|
+
console.error(`\n API Key: ${API_KEY.slice(0, 8)}${"*".repeat(12)}`);
|
|
462
|
+
console.error(`\n curl -H "Authorization: Bearer <key>" http://localhost:${PORT}/health`);
|
|
458
463
|
console.error(`\n Security: Bound to localhost only (127.0.0.1)`);
|
|
459
464
|
console.error(`\n${"═".repeat(60)}\n`);
|
|
460
465
|
});
|