@jtalk22/slack-mcp 3.2.5 → 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 -57
- package/lib/public-metadata.js +0 -65
- package/lib/public-pages.js +31 -71
- package/lib/token-store.js +2 -2
- package/package.json +2 -6
- package/public/share.html +1 -10
- 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.
|
|
22
|
+
|
|
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.
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+

|
|
22
26
|
|
|
23
27
|
## Tools
|
|
24
28
|
|
|
@@ -41,44 +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. Claude is the primary path; Gemini CLI is the second supported client path on the hosted endpoint.
|
|
51
|
-
|
|
52
|
-
- Self-host if you want 16 tools, npm or Docker, and full operator control over runtime and tokens.
|
|
53
|
-
- Use Cloud if you want one remote endpoint, hosted credential handling, deployment review, buyer-facing security review, support, and a hosted account surface.
|
|
54
|
-
- Solo starts at `$19/mo`; Team is `$49/mo` and adds 3 AI workflows plus higher request capacity.
|
|
55
|
-
- Turnkey Team Launch starts at `$2.5k+`; Managed Reliability starts at `$800/mo+` for teams where rollout and operational continuity matter more than raw seat count.
|
|
56
|
-
|
|
57
|
-
| Plan | Price | Includes |
|
|
58
|
-
|------|-------|----------|
|
|
59
|
-
| Solo | $19/mo | 15 standard tools, AES-256-GCM encrypted storage, 5K requests/mo |
|
|
60
|
-
| Team | $49/mo | 15 standard + 3 AI compound tools, 3 workspaces, 25K requests/mo |
|
|
61
|
-
| Turnkey Team Launch | $2.5k+ | Deployment review, rollout sequencing, client setup guidance, first-production-use path |
|
|
62
|
-
| Managed Reliability | $800/mo+ | Ongoing operating review, token-health follow-up, workflow continuity support |
|
|
48
|
+
12 read-only, 4 write-path. All carry [MCP safety annotations](https://modelcontextprotocol.io/specification/2025-03-26/server/tools#annotations).
|
|
63
49
|
|
|
64
|
-
|
|
50
|
+
\* `slack_refresh_tokens` modifies local token file only.
|
|
65
51
|
|
|
66
|
-
|
|
52
|
+
## Install
|
|
67
53
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
## Install & Verify (Self-Hosted)
|
|
71
|
-
|
|
72
|
-
**Runtime:** Node.js 20+
|
|
54
|
+
**Node.js 20+**
|
|
73
55
|
|
|
74
56
|
```bash
|
|
75
57
|
npx -y @jtalk22/slack-mcp --setup
|
|
76
|
-
npx -y @jtalk22/slack-mcp@latest --version
|
|
77
|
-
npx -y @jtalk22/slack-mcp@latest --doctor
|
|
78
|
-
npx -y @jtalk22/slack-mcp@latest --status
|
|
79
58
|
```
|
|
80
59
|
|
|
81
|
-
The setup wizard handles token extraction and validation
|
|
60
|
+
The setup wizard handles token extraction and validation.
|
|
82
61
|
|
|
83
62
|
<details>
|
|
84
63
|
<summary><strong>Claude Desktop (macOS)</strong></summary>
|
|
@@ -123,7 +102,7 @@ Edit `%APPDATA%\Claude\claude_desktop_config.json`:
|
|
|
123
102
|
</details>
|
|
124
103
|
|
|
125
104
|
<details>
|
|
126
|
-
<summary><strong>Claude Code
|
|
105
|
+
<summary><strong>Claude Code</strong></summary>
|
|
127
106
|
|
|
128
107
|
Add to `~/.claude.json`:
|
|
129
108
|
|
|
@@ -141,6 +120,41 @@ Add to `~/.claude.json`:
|
|
|
141
120
|
|
|
142
121
|
</details>
|
|
143
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
|
+
|
|
144
158
|
<details>
|
|
145
159
|
<summary><strong>Docker</strong></summary>
|
|
146
160
|
|
|
@@ -163,7 +177,19 @@ docker pull ghcr.io/jtalk22/slack-mcp-server:latest
|
|
|
163
177
|
|
|
164
178
|
</details>
|
|
165
179
|
|
|
166
|
-
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.
|
|
167
193
|
|
|
168
194
|
## Hosted HTTP Mode
|
|
169
195
|
|
|
@@ -181,32 +207,31 @@ Details: [docs/DEPLOYMENT-MODES.md](docs/DEPLOYMENT-MODES.md)
|
|
|
181
207
|
|
|
182
208
|
## Troubleshooting
|
|
183
209
|
|
|
184
|
-
**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).
|
|
185
211
|
|
|
186
|
-
**DMs not showing:** Use `slack_list_conversations` with `discover_dms=true
|
|
212
|
+
**DMs not showing:** Use `slack_list_conversations` with `discover_dms=true`.
|
|
187
213
|
|
|
188
|
-
**
|
|
214
|
+
**Client not seeing tools:** Check JSON syntax in config, restart client fully.
|
|
189
215
|
|
|
190
216
|
More: [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md)
|
|
191
217
|
|
|
192
218
|
## Docs
|
|
193
219
|
|
|
194
|
-
- [Setup Guide](docs/SETUP.md)
|
|
195
|
-
- [API Reference](docs/API.md)
|
|
196
|
-
- [
|
|
197
|
-
- [
|
|
198
|
-
- [
|
|
199
|
-
- [
|
|
200
|
-
- [
|
|
201
|
-
- [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)
|
|
202
227
|
|
|
203
228
|
## Security
|
|
204
229
|
|
|
205
|
-
- Token files
|
|
206
|
-
- macOS Keychain
|
|
230
|
+
- Token files: `chmod 600` (owner-only)
|
|
231
|
+
- macOS Keychain encrypted backup
|
|
207
232
|
- Web server binds to localhost only
|
|
208
|
-
- API keys
|
|
209
|
-
- See [SECURITY.md](SECURITY.md)
|
|
233
|
+
- API keys: `crypto.randomBytes`
|
|
234
|
+
- See [SECURITY.md](SECURITY.md)
|
|
210
235
|
|
|
211
236
|
## Contributing
|
|
212
237
|
|
|
@@ -218,4 +243,8 @@ MIT — See [LICENSE](LICENSE)
|
|
|
218
243
|
|
|
219
244
|
## Disclaimer
|
|
220
245
|
|
|
221
|
-
|
|
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/lib/public-metadata.js
CHANGED
|
@@ -6,14 +6,6 @@ const packageJson = JSON.parse(
|
|
|
6
6
|
|
|
7
7
|
export const RELEASE_VERSION = packageJson.version;
|
|
8
8
|
|
|
9
|
-
function withTrackedUrl(url, medium) {
|
|
10
|
-
const tracked = new URL(url);
|
|
11
|
-
tracked.searchParams.set("utm_source", "github");
|
|
12
|
-
tracked.searchParams.set("utm_medium", medium);
|
|
13
|
-
tracked.searchParams.set("utm_campaign", "slack_mcp_cloud");
|
|
14
|
-
return tracked.toString();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
9
|
export const PUBLIC_METADATA = Object.freeze({
|
|
18
10
|
projectName: "slack-mcp-server",
|
|
19
11
|
packageName: packageJson.name,
|
|
@@ -21,67 +13,10 @@ export const PUBLIC_METADATA = Object.freeze({
|
|
|
21
13
|
canonicalRepoUrl: "https://github.com/jtalk22/slack-mcp-server",
|
|
22
14
|
canonicalSiteUrl: "https://mcp.revasserlabs.com",
|
|
23
15
|
cloudPricingUrl: "https://mcp.revasserlabs.com/pricing",
|
|
24
|
-
cloudWorkflowsUrl: "https://mcp.revasserlabs.com/workflows",
|
|
25
|
-
cloudGeminiCliUrl: "https://mcp.revasserlabs.com/gemini-cli",
|
|
26
|
-
cloudReadinessUrl: "https://mcp.revasserlabs.com/readiness",
|
|
27
16
|
cloudDocsUrl: "https://mcp.revasserlabs.com/docs",
|
|
28
17
|
cloudSecurityUrl: "https://mcp.revasserlabs.com/security",
|
|
29
|
-
cloudProcurementUrl: "https://mcp.revasserlabs.com/procurement",
|
|
30
18
|
cloudSupportUrl: "https://mcp.revasserlabs.com/support",
|
|
31
|
-
cloudDeploymentUrl: "https://mcp.revasserlabs.com/deployment",
|
|
32
|
-
cloudSelfHostUrl: "https://mcp.revasserlabs.com/self-host",
|
|
33
|
-
cloudAccountUrl: "https://mcp.revasserlabs.com/account",
|
|
34
|
-
cloudUseCasesRootUrl: "https://mcp.revasserlabs.com/use-cases",
|
|
35
19
|
cloudStatusUrl: "https://mcp.revasserlabs.com/status",
|
|
36
20
|
supportEmail: "support@revasserlabs.com",
|
|
37
|
-
privacyEmail: "privacy@revasserlabs.com",
|
|
38
|
-
primaryClient: "Claude",
|
|
39
|
-
secondaryClient: "Gemini CLI",
|
|
40
21
|
selfHostedToolCount: 16,
|
|
41
|
-
cloudManagedToolCount: 15,
|
|
42
|
-
teamAiWorkflowCount: 3,
|
|
43
|
-
cloudSoloPrice: "$19/mo",
|
|
44
|
-
cloudTeamPrice: "$49/mo",
|
|
45
|
-
cloudTurnkeyLaunchPrice: "$2.5k+",
|
|
46
|
-
cloudManagedReliabilityPrice: "$800/mo+",
|
|
47
|
-
tracked: Object.freeze({
|
|
48
|
-
pages: Object.freeze({
|
|
49
|
-
pricing: withTrackedUrl("https://mcp.revasserlabs.com/pricing", "pages"),
|
|
50
|
-
workflows: withTrackedUrl("https://mcp.revasserlabs.com/workflows", "pages"),
|
|
51
|
-
geminiCli: withTrackedUrl("https://mcp.revasserlabs.com/gemini-cli", "pages"),
|
|
52
|
-
readiness: withTrackedUrl("https://mcp.revasserlabs.com/readiness", "pages"),
|
|
53
|
-
docs: withTrackedUrl("https://mcp.revasserlabs.com/docs", "pages"),
|
|
54
|
-
security: withTrackedUrl("https://mcp.revasserlabs.com/security", "pages"),
|
|
55
|
-
procurement: withTrackedUrl("https://mcp.revasserlabs.com/procurement", "pages"),
|
|
56
|
-
deployment: withTrackedUrl("https://mcp.revasserlabs.com/deployment", "pages"),
|
|
57
|
-
support: withTrackedUrl("https://mcp.revasserlabs.com/support", "pages"),
|
|
58
|
-
account: withTrackedUrl("https://mcp.revasserlabs.com/account", "pages"),
|
|
59
|
-
privacy: withTrackedUrl("https://mcp.revasserlabs.com/privacy", "pages"),
|
|
60
|
-
}),
|
|
61
|
-
readme: Object.freeze({
|
|
62
|
-
pricing: withTrackedUrl("https://mcp.revasserlabs.com/pricing", "readme"),
|
|
63
|
-
workflows: withTrackedUrl("https://mcp.revasserlabs.com/workflows", "readme"),
|
|
64
|
-
geminiCli: withTrackedUrl("https://mcp.revasserlabs.com/gemini-cli", "readme"),
|
|
65
|
-
readiness: withTrackedUrl("https://mcp.revasserlabs.com/readiness", "readme"),
|
|
66
|
-
docs: withTrackedUrl("https://mcp.revasserlabs.com/docs", "readme"),
|
|
67
|
-
security: withTrackedUrl("https://mcp.revasserlabs.com/security", "readme"),
|
|
68
|
-
procurement: withTrackedUrl("https://mcp.revasserlabs.com/procurement", "readme"),
|
|
69
|
-
deployment: withTrackedUrl("https://mcp.revasserlabs.com/deployment", "readme"),
|
|
70
|
-
support: withTrackedUrl("https://mcp.revasserlabs.com/support", "readme"),
|
|
71
|
-
account: withTrackedUrl("https://mcp.revasserlabs.com/account", "readme"),
|
|
72
|
-
privacy: withTrackedUrl("https://mcp.revasserlabs.com/privacy", "readme"),
|
|
73
|
-
}),
|
|
74
|
-
docs: Object.freeze({
|
|
75
|
-
pricing: withTrackedUrl("https://mcp.revasserlabs.com/pricing", "docs"),
|
|
76
|
-
workflows: withTrackedUrl("https://mcp.revasserlabs.com/workflows", "docs"),
|
|
77
|
-
geminiCli: withTrackedUrl("https://mcp.revasserlabs.com/gemini-cli", "docs"),
|
|
78
|
-
readiness: withTrackedUrl("https://mcp.revasserlabs.com/readiness", "docs"),
|
|
79
|
-
security: withTrackedUrl("https://mcp.revasserlabs.com/security", "docs"),
|
|
80
|
-
procurement: withTrackedUrl("https://mcp.revasserlabs.com/procurement", "docs"),
|
|
81
|
-
deployment: withTrackedUrl("https://mcp.revasserlabs.com/deployment", "docs"),
|
|
82
|
-
support: withTrackedUrl("https://mcp.revasserlabs.com/support", "docs"),
|
|
83
|
-
account: withTrackedUrl("https://mcp.revasserlabs.com/account", "docs"),
|
|
84
|
-
privacy: withTrackedUrl("https://mcp.revasserlabs.com/privacy", "docs"),
|
|
85
|
-
}),
|
|
86
|
-
}),
|
|
87
22
|
});
|
package/lib/public-pages.js
CHANGED
|
@@ -15,9 +15,6 @@ const ICON_URL = `${GITHUB_PAGES_ROOT}/docs/assets/icon-512.png`;
|
|
|
15
15
|
const NPM_URL = "https://www.npmjs.com/package/@jtalk22/slack-mcp";
|
|
16
16
|
const RELEASES_URL = `${PUBLIC_METADATA.canonicalRepoUrl}/releases/latest`;
|
|
17
17
|
const SETUP_URL = `${PUBLIC_METADATA.canonicalRepoUrl}/blob/main/docs/SETUP.md`;
|
|
18
|
-
const RELEASE_HEALTH_URL = `${GITHUB_DOCS_ROOT}/release-health/latest.md`;
|
|
19
|
-
const VERSION_PARITY_URL = `${GITHUB_DOCS_ROOT}/release-health/version-parity.md`;
|
|
20
|
-
const RUNBOOK_URL = `${GITHUB_DOCS_ROOT}/LAUNCH-OPS.md`;
|
|
21
18
|
const DEMO_VIDEO_URL = `${GITHUB_PAGES_ROOT}/docs/videos/demo-claude-mobile-20s.mp4`;
|
|
22
19
|
|
|
23
20
|
function template(name) {
|
|
@@ -36,39 +33,17 @@ function replaceTokens(source, replacements) {
|
|
|
36
33
|
function rootDecisionPanel() {
|
|
37
34
|
return `
|
|
38
35
|
<section class="stage" style="padding-top:0">
|
|
39
|
-
<div class="decision-grid" aria-label="
|
|
36
|
+
<div class="decision-grid" aria-label="Self-host info">
|
|
40
37
|
<article class="decision-card">
|
|
41
38
|
<span class="decision-label">Self-host</span>
|
|
42
|
-
<h2
|
|
43
|
-
<p>
|
|
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>
|
|
44
41
|
<ul>
|
|
45
42
|
<li>stdio, web, and Docker paths stay fully under your control</li>
|
|
46
|
-
<li>
|
|
47
|
-
<li>
|
|
43
|
+
<li>No OAuth app registration or admin approval needed</li>
|
|
44
|
+
<li>Token persistence with automatic refresh on macOS</li>
|
|
48
45
|
</ul>
|
|
49
|
-
<p class="decision-links"><a href="${SETUP_URL}">Setup guide</a> · <a href="${
|
|
50
|
-
</article>
|
|
51
|
-
<article class="decision-card accent">
|
|
52
|
-
<span class="decision-label">Cloud</span>
|
|
53
|
-
<h2>${PUBLIC_METADATA.cloudManagedToolCount} managed tools, ${PUBLIC_METADATA.teamAiWorkflowCount} Team AI workflows.</h2>
|
|
54
|
-
<p>Choose Cloud if you want one remote endpoint, hosted credential handling, deployment review, and an operational support path instead of running the transport yourself. ${PUBLIC_METADATA.primaryClient} stays primary; ${PUBLIC_METADATA.secondaryClient} is supported as the second client path.</p>
|
|
55
|
-
<ul>
|
|
56
|
-
<li>Solo: ${PUBLIC_METADATA.cloudSoloPrice} for the managed endpoint and hosted credential handling</li>
|
|
57
|
-
<li>Team: ${PUBLIC_METADATA.cloudTeamPrice} and adds ${PUBLIC_METADATA.teamAiWorkflowCount} AI workflows</li>
|
|
58
|
-
<li>Turnkey Team Launch: from ${PUBLIC_METADATA.cloudTurnkeyLaunchPrice}; Managed Reliability: from ${PUBLIC_METADATA.cloudManagedReliabilityPrice}</li>
|
|
59
|
-
</ul>
|
|
60
|
-
<p class="decision-links"><a href="${PUBLIC_METADATA.tracked.pages.pricing}">Pricing</a> · <a href="${PUBLIC_METADATA.tracked.pages.workflows}">Workflows</a> · <a href="${PUBLIC_METADATA.tracked.pages.geminiCli}">Gemini CLI</a> · <a href="${PUBLIC_METADATA.tracked.pages.deployment}">Deployment review</a> · <a href="${PUBLIC_METADATA.tracked.pages.security}">Security</a></p>
|
|
61
|
-
</article>
|
|
62
|
-
<article class="decision-card">
|
|
63
|
-
<span class="decision-label">Buyer proof</span>
|
|
64
|
-
<h2>Technical trust surfaces stay public.</h2>
|
|
65
|
-
<p>The static Pages root shows npm, GitHub release, and hosted status together. The hosted site publishes <code>/status</code>, <code>/pricing</code>, <code>/docs</code>, <code>/security</code>, <code>/deployment</code>, <code>/support</code>, and <code>/account</code> as the operator-facing Cloud surface.</p>
|
|
66
|
-
<ul>
|
|
67
|
-
<li>GitHub Pages reads the hosted <code>/status</code> contract live</li>
|
|
68
|
-
<li>Registry, npm, runtime parity, and hosted funnel reporting are tracked in the public reports</li>
|
|
69
|
-
<li>Rollout and security questions route to hosted review surfaces instead of ad hoc GitHub issues</li>
|
|
70
|
-
</ul>
|
|
71
|
-
<p class="decision-links"><a href="${RUNBOOK_URL}">Runbook</a> · <a href="${PUBLIC_METADATA.cloudStatusUrl}">Raw status JSON</a> · <a href="${PUBLIC_METADATA.tracked.pages.procurement}">Procurement</a> · <a href="${PUBLIC_METADATA.tracked.pages.readiness}">Readiness</a> · <a href="${PUBLIC_METADATA.tracked.pages.pricing}">Plans & offers</a></p>
|
|
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>
|
|
72
47
|
</article>
|
|
73
48
|
</div>
|
|
74
49
|
</section>
|
|
@@ -80,15 +55,6 @@ function shareLinks() {
|
|
|
80
55
|
<a href="${SETUP_URL}" rel="noopener">Install (\`--setup\`)</a>
|
|
81
56
|
<a href="${SETUP_URL}" rel="noopener">Verify (\`--version/--doctor/--status\`)</a>
|
|
82
57
|
<a href="${RELEASES_URL}" rel="noopener">Latest Release</a>
|
|
83
|
-
<a href="${PUBLIC_METADATA.tracked.pages.pricing}" rel="noopener">Pricing</a>
|
|
84
|
-
<a href="${PUBLIC_METADATA.tracked.pages.workflows}" rel="noopener">Workflows</a>
|
|
85
|
-
<a href="${PUBLIC_METADATA.tracked.pages.geminiCli}" rel="noopener">Gemini CLI</a>
|
|
86
|
-
<a href="${PUBLIC_METADATA.tracked.pages.docs}" rel="noopener">Cloud Docs</a>
|
|
87
|
-
<a href="${PUBLIC_METADATA.tracked.pages.security}" rel="noopener">Security</a>
|
|
88
|
-
<a href="${PUBLIC_METADATA.tracked.pages.procurement}" rel="noopener">Procurement</a>
|
|
89
|
-
<a href="${PUBLIC_METADATA.tracked.pages.deployment}" rel="noopener">Deployment Review</a>
|
|
90
|
-
<a href="${PUBLIC_METADATA.tracked.pages.support}" rel="noopener">Cloud Support</a>
|
|
91
|
-
<a href="${PUBLIC_METADATA.cloudUseCasesRootUrl}/support-triage?utm_source=github&utm_medium=pages&utm_campaign=slack_mcp_cloud" rel="noopener">Support Triage Use Case</a>
|
|
92
58
|
<a href="${GITHUB_PAGES_ROOT}/" rel="noopener">Autoplay Demo Landing</a>
|
|
93
59
|
<a href="${DEMO_VIDEO_URL}" rel="noopener">20s Mobile Clip</a>
|
|
94
60
|
<a href="${NPM_URL}" rel="noopener">npm Package</a>
|
|
@@ -97,48 +63,42 @@ function shareLinks() {
|
|
|
97
63
|
}
|
|
98
64
|
|
|
99
65
|
function shareNote() {
|
|
100
|
-
return `<strong>Verify in 30 seconds:</strong> <code>--version</code>, <code>--doctor</code>, <code>--status</code>. Self-host gives ${PUBLIC_METADATA.selfHostedToolCount} tools
|
|
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>.`;
|
|
101
67
|
}
|
|
102
68
|
|
|
103
69
|
function demoLinks() {
|
|
104
70
|
return `
|
|
105
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>
|
|
106
72
|
<a href="${NPM_URL}" target="_blank" rel="noopener noreferrer">npm Install</a>
|
|
107
|
-
<a href="${PUBLIC_METADATA.tracked.pages.pricing}" target="_blank" rel="noopener noreferrer">Pricing</a>
|
|
108
|
-
<a href="${PUBLIC_METADATA.tracked.pages.workflows}" target="_blank" rel="noopener noreferrer">Workflows</a>
|
|
109
|
-
<a href="${PUBLIC_METADATA.tracked.pages.geminiCli}" target="_blank" rel="noopener noreferrer">Gemini CLI</a>
|
|
110
73
|
<a href="${SETUP_URL}" target="_blank" rel="noopener noreferrer">Setup Guide</a>
|
|
111
|
-
<a href="${PUBLIC_METADATA.tracked.pages.docs}" target="_blank" rel="noopener noreferrer">Cloud Docs</a>
|
|
112
|
-
<a href="${PUBLIC_METADATA.tracked.pages.security}" target="_blank" rel="noopener noreferrer">Security</a>
|
|
113
|
-
<a href="${PUBLIC_METADATA.tracked.pages.procurement}" target="_blank" rel="noopener noreferrer">Procurement</a>
|
|
114
|
-
<a href="${PUBLIC_METADATA.tracked.pages.deployment}" target="_blank" rel="noopener noreferrer">Deployment Review</a>
|
|
115
|
-
<a href="${PUBLIC_METADATA.tracked.pages.support}" target="_blank" rel="noopener noreferrer">Cloud Support</a>
|
|
116
74
|
`.trim();
|
|
117
75
|
}
|
|
118
76
|
|
|
119
77
|
function demoNote() {
|
|
120
|
-
return `Self-host free for ${PUBLIC_METADATA.selfHostedToolCount} tools
|
|
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>.`;
|
|
121
79
|
}
|
|
122
80
|
|
|
123
81
|
function demoFooterLinks() {
|
|
124
|
-
return `<a href="${PUBLIC_METADATA.canonicalRepoUrl}">GitHub</a> · <a href="${
|
|
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>`;
|
|
125
83
|
}
|
|
126
84
|
|
|
127
85
|
function commonTokens() {
|
|
128
86
|
return {
|
|
129
87
|
CANONICAL_SITE_URL: PUBLIC_METADATA.canonicalSiteUrl,
|
|
130
|
-
CLOUD_PRICING_URL: PUBLIC_METADATA.
|
|
131
|
-
CLOUD_WORKFLOWS_URL: PUBLIC_METADATA.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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",
|
|
139
99
|
CLOUD_STATUS_URL: PUBLIC_METADATA.cloudStatusUrl,
|
|
140
|
-
CLOUD_SELF_HOST_URL: PUBLIC_METADATA.
|
|
141
|
-
CLOUD_ACCOUNT_URL: PUBLIC_METADATA.
|
|
100
|
+
CLOUD_SELF_HOST_URL: PUBLIC_METADATA.canonicalSiteUrl + "/self-host",
|
|
101
|
+
CLOUD_ACCOUNT_URL: PUBLIC_METADATA.canonicalSiteUrl + "/account",
|
|
142
102
|
GITHUB_REPO_URL: PUBLIC_METADATA.canonicalRepoUrl,
|
|
143
103
|
GITHUB_PAGES_ROOT,
|
|
144
104
|
GITHUB_DOCS_ROOT,
|
|
@@ -147,16 +107,16 @@ function commonTokens() {
|
|
|
147
107
|
NPM_URL,
|
|
148
108
|
RELEASES_URL,
|
|
149
109
|
SETUP_URL,
|
|
150
|
-
RELEASE_HEALTH_URL,
|
|
151
|
-
VERSION_PARITY_URL,
|
|
152
|
-
RUNBOOK_URL,
|
|
110
|
+
RELEASE_HEALTH_URL: RELEASES_URL,
|
|
111
|
+
VERSION_PARITY_URL: RELEASES_URL,
|
|
112
|
+
RUNBOOK_URL: SETUP_URL,
|
|
153
113
|
SELF_HOSTED_TOOL_COUNT: String(PUBLIC_METADATA.selfHostedToolCount),
|
|
154
|
-
CLOUD_MANAGED_TOOL_COUNT:
|
|
155
|
-
TEAM_AI_WORKFLOW_COUNT:
|
|
156
|
-
CLOUD_SOLO_PRICE:
|
|
157
|
-
CLOUD_TEAM_PRICE:
|
|
158
|
-
CLOUD_TURNKEY_LAUNCH_PRICE:
|
|
159
|
-
CLOUD_MANAGED_RELIABILITY_PRICE:
|
|
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+",
|
|
160
120
|
SUPPORT_EMAIL: PUBLIC_METADATA.supportEmail,
|
|
161
121
|
ROOT_DECISION_PANEL: rootDecisionPanel(),
|
|
162
122
|
SHARE_LINKS: shareLinks(),
|
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": "
|
|
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": {
|
|
@@ -31,10 +31,6 @@
|
|
|
31
31
|
"record-demo": "node scripts/record-demo.js",
|
|
32
32
|
"social-preview:update": "node scripts/update-github-social-preview.js --headed",
|
|
33
33
|
"cf:browser": "node scripts/cloudflare-browser-tool.js",
|
|
34
|
-
"metrics:release-health": "node scripts/collect-release-health.js",
|
|
35
|
-
"metrics:release-health:delta": "node scripts/build-release-health-delta.js",
|
|
36
|
-
"impact:push:v3": "node scripts/impact-push-v3.js --dry-run",
|
|
37
|
-
"impact:push:v3:apply": "node scripts/impact-push-v3.js --apply",
|
|
38
34
|
"verify:attribution-guardrail": "node scripts/verify-attribution-guardrail.js",
|
|
39
35
|
"verify:public-pages": "node scripts/verify-generated-public-pages.js",
|
|
40
36
|
"verify:version-parity": "node scripts/check-version-parity.js",
|
package/public/share.html
CHANGED
|
@@ -117,22 +117,13 @@
|
|
|
117
117
|
<a href="https://github.com/jtalk22/slack-mcp-server/blob/main/docs/SETUP.md" rel="noopener">Install (`--setup`)</a>
|
|
118
118
|
<a href="https://github.com/jtalk22/slack-mcp-server/blob/main/docs/SETUP.md" rel="noopener">Verify (`--version/--doctor/--status`)</a>
|
|
119
119
|
<a href="https://github.com/jtalk22/slack-mcp-server/releases/latest" rel="noopener">Latest Release</a>
|
|
120
|
-
<a href="https://mcp.revasserlabs.com/pricing?utm_source=github&utm_medium=pages&utm_campaign=slack_mcp_cloud" rel="noopener">Pricing</a>
|
|
121
|
-
<a href="https://mcp.revasserlabs.com/workflows?utm_source=github&utm_medium=pages&utm_campaign=slack_mcp_cloud" rel="noopener">Workflows</a>
|
|
122
|
-
<a href="https://mcp.revasserlabs.com/gemini-cli?utm_source=github&utm_medium=pages&utm_campaign=slack_mcp_cloud" rel="noopener">Gemini CLI</a>
|
|
123
|
-
<a href="https://mcp.revasserlabs.com/docs?utm_source=github&utm_medium=pages&utm_campaign=slack_mcp_cloud" rel="noopener">Cloud Docs</a>
|
|
124
|
-
<a href="https://mcp.revasserlabs.com/security?utm_source=github&utm_medium=pages&utm_campaign=slack_mcp_cloud" rel="noopener">Security</a>
|
|
125
|
-
<a href="https://mcp.revasserlabs.com/procurement?utm_source=github&utm_medium=pages&utm_campaign=slack_mcp_cloud" rel="noopener">Procurement</a>
|
|
126
|
-
<a href="https://mcp.revasserlabs.com/deployment?utm_source=github&utm_medium=pages&utm_campaign=slack_mcp_cloud" rel="noopener">Deployment Review</a>
|
|
127
|
-
<a href="https://mcp.revasserlabs.com/support?utm_source=github&utm_medium=pages&utm_campaign=slack_mcp_cloud" rel="noopener">Cloud Support</a>
|
|
128
|
-
<a href="https://mcp.revasserlabs.com/use-cases/support-triage?utm_source=github&utm_medium=pages&utm_campaign=slack_mcp_cloud" rel="noopener">Support Triage Use Case</a>
|
|
129
120
|
<a href="https://jtalk22.github.io/slack-mcp-server/" rel="noopener">Autoplay Demo Landing</a>
|
|
130
121
|
<a href="https://jtalk22.github.io/slack-mcp-server/docs/videos/demo-claude-mobile-20s.mp4" rel="noopener">20s Mobile Clip</a>
|
|
131
122
|
<a href="https://www.npmjs.com/package/@jtalk22/slack-mcp" rel="noopener">npm Package</a>
|
|
132
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>
|
|
133
124
|
</div>
|
|
134
125
|
|
|
135
|
-
<p class="note"><strong>Verify in 30 seconds:</strong> <code>--version</code>, <code>--doctor</code>, <code>--status</code>. Self-host gives 16 tools
|
|
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>
|
|
136
127
|
</main>
|
|
137
128
|
</body>
|
|
138
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": "
|
|
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
|
});
|