@jtalk22/slack-mcp 1.0.4 → 1.1.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 CHANGED
@@ -1,88 +1,190 @@
1
1
  # Slack MCP Server
2
2
 
3
- [![CI](https://github.com/jtalk22/slack-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/jtalk22/slack-mcp-server/actions/workflows/ci.yml)
3
+ [![Live Demo](https://img.shields.io/badge/Demo-Try%20Simulator-blue?style=for-the-badge)](https://jtalk22.github.io/slack-mcp-server/public/demo.html)
4
+
5
+ [![npm](https://img.shields.io/npm/v/@jtalk22/slack-mcp?color=blue)](https://www.npmjs.com/package/@jtalk22/slack-mcp)
6
+ [![Docker](https://img.shields.io/badge/docker-ghcr.io-blue)](https://github.com/jtalk22/slack-mcp-server/pkgs/container/slack-mcp-server)
4
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
8
  [![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)
6
9
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/jtalk22/slack-mcp-server/pulls)
7
- [![GitHub Sponsors](https://img.shields.io/github/sponsors/jtalk22?style=social)](https://github.com/sponsors/jtalk22)
8
10
 
9
- A [Model Context Protocol](https://modelcontextprotocol.io/) server that gives Claude full access to your Slack workspace - including **DMs**, channels, and message history.
11
+ A [Model Context Protocol](https://modelcontextprotocol.io/) server that gives Claude **unrestricted access** to your Slack workspace - including DMs, private channels, and full message history. No OAuth. No app approval. No per-conversation authorization.
10
12
 
11
13
  <p align="center">
12
14
  <img src="docs/images/demo-main.png" alt="Slack MCP Server Web UI" width="800">
13
15
  </p>
14
16
 
15
- > **[Try the Interactive Demo](https://jtalk22.github.io/slack-mcp-server/public/demo.html)** - See the Web UI in action with mock data
17
+ > **[Try the Interactive Demo](https://jtalk22.github.io/slack-mcp-server/public/demo.html)** - See the Web UI in action
18
+
19
+ ---
20
+
21
+ ## How It Works: The Cookie Heist
22
+
23
+ This server bypasses Slack's OAuth entirely by extracting your browser session tokens. You already have access to everything in Slack's web interface - we just give that same access to Claude.
24
+
25
+ ```mermaid
26
+ sequenceDiagram
27
+ participant Chrome as Chrome Browser
28
+ participant Script as AppleScript
29
+ participant Store as Token Store
30
+ participant MCP as MCP Server
31
+ participant Slack as Slack API
16
32
 
17
- ## Why This Exists
33
+ Note over Chrome: You're logged into Slack
34
+ Script->>Chrome: Execute JavaScript in Slack tab
35
+ Chrome-->>Script: xoxc- token + xoxd- cookie
36
+ Script->>Store: Save to ~/.slack-mcp-tokens.json
37
+ Store->>Store: Encrypt in macOS Keychain
38
+
39
+ Note over MCP: Claude asks for DMs
40
+ MCP->>Store: Load credentials
41
+ Store-->>MCP: Token + Cookie
42
+ MCP->>Slack: GET conversations.history
43
+ Slack-->>MCP: Full message history
44
+ MCP-->>MCP: Return to Claude
45
+ ```
46
+
47
+ ### Why Not OAuth?
48
+
49
+ ```mermaid
50
+ flowchart LR
51
+ subgraph Traditional["Traditional Slack App (OAuth)"]
52
+ A[Create App] --> B[Request Scopes]
53
+ B --> C[Admin Approval]
54
+ C --> D[User Authorization]
55
+ D --> E[Limited Access]
56
+ E --> F["No DMs without<br/>per-conversation consent"]
57
+ end
58
+
59
+ subgraph ThisServer["This Server (Browser Tokens)"]
60
+ G[Open Slack in Chrome] --> H[Extract Session]
61
+ H --> I[Full Access]
62
+ I --> J["All DMs, Channels,<br/>Search, Everything"]
63
+ end
64
+
65
+ style Traditional fill:#ffcccc
66
+ style ThisServer fill:#ccffcc
67
+ ```
18
68
 
19
- Official Slack integrations require OAuth and can't access DMs without explicit per-conversation authorization. This server uses your browser session tokens to provide the same access you have in Slack's web interface.
69
+ **The trade-off:** Tokens expire every 1-2 weeks, but auto-refresh keeps things running seamlessly.
20
70
 
21
- **Works with:**
22
- - Claude Desktop (macOS/Windows)
23
- - Claude Code (CLI)
24
- - claude.ai (via Web UI)
71
+ ---
25
72
 
26
73
  ## Features
27
74
 
28
- - **Read Messages** - Fetch history from any DM or channel
29
- - **Full Export** - Export conversations with threads and resolved usernames
30
- - **Search** - Search messages across your workspace
31
- - **Send Messages** - Send to DMs or channels
32
- - **Auto Token Recovery** - Refreshes expired tokens from Chrome automatically
33
- - **Rate Limit Handling** - Automatic retry with exponential backoff
34
- - **Web UI** - Browser interface for use with claude.ai
75
+ ### Core Capabilities
76
+ - **Read Any Message** - DMs, private channels, public channels
77
+ - **Full Export** - Conversations with threads and resolved usernames
78
+ - **Search** - Query across your entire workspace
79
+ - **Send Messages** - DMs or channels, with thread support
80
+ - **User Directory** - List and search 500+ users with pagination
81
+
82
+ ### Stability (v1.0.6+)
83
+ - **Auto Token Refresh** - Extracts fresh tokens from Chrome automatically *(macOS only)*
84
+ - **Atomic Writes** - File operations use temp-file-then-rename to prevent corruption
85
+ - **Zombie Protection** - Background timers use `unref()` for clean process exit
86
+ - **Race Condition Safety** - Mutex locks prevent concurrent token extraction
87
+ - **Rate Limit Handling** - Exponential backoff with jitter
88
+
89
+ ### Tools
90
+ | Tool | Description |
91
+ |------|-------------|
92
+ | `slack_health_check` | Verify token validity and workspace info |
93
+ | `slack_token_status` | **New:** Detailed token age, health, and cache stats |
94
+ | `slack_refresh_tokens` | Auto-extract fresh tokens from Chrome |
95
+ | `slack_list_conversations` | List DMs/channels (with lazy discovery cache) |
96
+ | `slack_conversations_history` | Get messages from a channel or DM |
97
+ | `slack_get_full_conversation` | Export full history with threads |
98
+ | `slack_search_messages` | Search across workspace |
99
+ | `slack_send_message` | Send a message to any conversation |
100
+ | `slack_get_thread` | Get thread replies |
101
+ | `slack_users_info` | Get user details |
102
+ | `slack_list_users` | List workspace users (paginated, 500+ supported) |
103
+
104
+ ---
35
105
 
36
106
  ## Quick Start
37
107
 
38
- ### 1. Install
108
+ ### Option A: npm (Recommended)
109
+
110
+ ```bash
111
+ npm install -g @jtalk22/slack-mcp
112
+ ```
113
+
114
+ ### Option B: Clone Repository
39
115
 
40
116
  ```bash
41
- # Clone the repository
42
117
  git clone https://github.com/jtalk22/slack-mcp-server.git
43
118
  cd slack-mcp-server
44
-
45
- # Install dependencies
46
119
  npm install
47
120
  ```
48
121
 
122
+ ### Option C: Docker
123
+
124
+ ```bash
125
+ docker pull ghcr.io/jtalk22/slack-mcp-server:latest
49
126
  ```
50
127
 
51
- ### 2. Get Your Slack Tokens
128
+ ---
129
+
130
+ ## Configuration
52
131
 
53
- You need two tokens from your browser session:
132
+ ### Step 1: Get Your Tokens
54
133
 
55
- **Option A: Automatic (Recommended)**
134
+ #### macOS (Automatic)
56
135
  ```bash
57
- # Open Chrome with Slack (app.slack.com) logged in
58
- npm run tokens:auto
136
+ # Have Chrome open with Slack (app.slack.com) logged in
137
+ npx @jtalk22/slack-mcp tokens:auto
138
+ # Or if cloned: npm run tokens:auto
59
139
  ```
60
140
 
61
- **Option B: Manual**
141
+ #### Linux/Windows (Manual)
62
142
 
63
- 1. Open https://app.slack.com in Chrome
64
- 2. Press F12 → Application → Cookies → Find `d` cookie (starts with `xoxd-`)
65
- 3. Press F12 Console → Run:
143
+ Auto-refresh requires macOS + Chrome. On other platforms, extract tokens manually:
144
+
145
+ 1. Open https://app.slack.com in your browser
146
+ 2. Press F12 → Console → Run:
66
147
  ```javascript
148
+ // Get token
67
149
  JSON.parse(localStorage.localConfig_v2).teams[Object.keys(JSON.parse(localStorage.localConfig_v2).teams)[0]].token
68
150
  ```
69
- 4. Copy both values and run:
70
- ```bash
71
- npm run tokens:refresh
151
+ 3. Press F12 → Application → Cookies → Copy the `d` cookie value (starts with `xoxd-`)
152
+ 4. Create `~/.slack-mcp-tokens.json`:
153
+ ```json
154
+ {
155
+ "SLACK_TOKEN": "xoxc-your-token-here",
156
+ "SLACK_COOKIE": "xoxd-your-cookie-here",
157
+ "updated_at": "2024-01-01T00:00:00.000Z"
158
+ }
72
159
  ```
73
160
 
74
- ### 3. Configure Claude
161
+ ### Step 2: Configure Claude
75
162
 
76
- #### For Claude Desktop
163
+ #### Claude Desktop (macOS)
77
164
 
78
- Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
165
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
79
166
 
80
167
  ```json
81
168
  {
82
169
  "mcpServers": {
83
170
  "slack": {
84
- "command": "node",
85
- "args": ["/path/to/slack-mcp-server/src/server.js"],
171
+ "command": "npx",
172
+ "args": ["-y", "@jtalk22/slack-mcp"]
173
+ }
174
+ }
175
+ }
176
+ ```
177
+
178
+ #### Claude Desktop (Windows)
179
+
180
+ Edit `%APPDATA%\Claude\claude_desktop_config.json`:
181
+
182
+ ```json
183
+ {
184
+ "mcpServers": {
185
+ "slack": {
186
+ "command": "npx",
187
+ "args": ["-y", "@jtalk22/slack-mcp"],
86
188
  "env": {
87
189
  "SLACK_TOKEN": "xoxc-your-token",
88
190
  "SLACK_COOKIE": "xoxd-your-cookie"
@@ -92,7 +194,9 @@ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) o
92
194
  }
93
195
  ```
94
196
 
95
- #### For Claude Code
197
+ > **Note:** Windows/Linux users must provide tokens via `env` since auto-refresh is macOS-only.
198
+
199
+ #### Claude Code (CLI)
96
200
 
97
201
  Add to `~/.claude.json`:
98
202
 
@@ -101,8 +205,8 @@ Add to `~/.claude.json`:
101
205
  "mcpServers": {
102
206
  "slack": {
103
207
  "type": "stdio",
104
- "command": "node",
105
- "args": ["/path/to/slack-mcp-server/src/server.js"]
208
+ "command": "npx",
209
+ "args": ["-y", "@jtalk22/slack-mcp"]
106
210
  }
107
211
  }
108
212
  }
@@ -110,221 +214,200 @@ Add to `~/.claude.json`:
110
214
 
111
215
  Claude Code reads tokens from `~/.slack-mcp-tokens.json` automatically.
112
216
 
113
- ### 4. Restart Claude
114
-
115
- The Slack tools will now be available.
116
-
117
- ## Available Tools
118
-
119
- | Tool | Description |
120
- |------|-------------|
121
- | `slack_health_check` | Verify token validity and show workspace info |
122
- | `slack_refresh_tokens` | Auto-extract fresh tokens from Chrome |
123
- | `slack_list_conversations` | List DMs and channels with resolved names |
124
- | `slack_conversations_history` | Get messages from a channel or DM |
125
- | `slack_get_full_conversation` | Export full history with threads |
126
- | `slack_search_messages` | Search across workspace |
127
- | `slack_send_message` | Send a message |
128
- | `slack_get_thread` | Get thread replies |
129
- | `slack_users_info` | Get user details |
130
- | `slack_list_users` | List workspace users |
131
-
132
- ## Web UI (for claude.ai)
133
-
134
- Since claude.ai doesn't support MCP, you can use the web server:
217
+ #### Docker Configuration
135
218
 
136
- ```bash
137
- npm run web
219
+ ```json
220
+ {
221
+ "mcpServers": {
222
+ "slack": {
223
+ "command": "docker",
224
+ "args": ["run", "-i", "--rm",
225
+ "-v", "~/.slack-mcp-tokens.json:/root/.slack-mcp-tokens.json",
226
+ "ghcr.io/jtalk22/slack-mcp-server"]
227
+ }
228
+ }
229
+ }
138
230
  ```
139
231
 
140
- Open http://localhost:3000 in your browser. It auto-connects with the default API key (`slack-mcp-local`).
232
+ ### Step 3: Restart Claude
141
233
 
142
- <details>
143
- <summary><strong>View Web UI Screenshots</strong></summary>
234
+ Fully quit and reopen Claude. The Slack tools will appear.
144
235
 
145
- | DMs View | Channels View |
146
- |----------|---------------|
147
- | ![DMs](docs/images/demo-main.png) | ![Channels](docs/images/demo-channels.png) |
236
+ ---
148
237
 
149
- </details>
238
+ ## Architecture
150
239
 
151
- ### Auto-Start on Login (macOS)
240
+ ### Token Persistence (4 Layers)
152
241
 
153
- ```bash
154
- # Create LaunchAgent
155
- cat > ~/Library/LaunchAgents/com.slack-mcp-server.plist << 'EOF'
156
- <?xml version="1.0" encoding="UTF-8"?>
157
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
158
- <plist version="1.0">
159
- <dict>
160
- <key>Label</key>
161
- <string>com.slack-mcp-server</string>
162
- <key>ProgramArguments</key>
163
- <array>
164
- <string>/usr/local/bin/node</string>
165
- <string>/path/to/slack-mcp-server/src/web-server.js</string>
166
- </array>
167
- <key>WorkingDirectory</key>
168
- <string>/path/to/slack-mcp-server</string>
169
- <key>RunAtLoad</key>
170
- <true/>
171
- <key>KeepAlive</key>
172
- <true/>
173
- </dict>
174
- </plist>
175
- EOF
176
-
177
- launchctl load ~/Library/LaunchAgents/com.slack-mcp-server.plist
178
242
  ```
179
-
180
- ## Docker
181
-
182
- Run the server in a container:
183
-
184
- ```bash
185
- # Pull pre-built image
186
- docker pull ghcr.io/jtalk22/slack-mcp-server:latest
187
-
188
- # Or build locally
189
- docker build -t slack-mcp-server .
190
-
191
- # Run with environment variables
192
- docker run -e SLACK_TOKEN=xoxc-your-token -e SLACK_COOKIE=xoxd-your-cookie ghcr.io/jtalk22/slack-mcp-server
193
-
194
- # Or mount existing token file
195
- docker run -v ~/.slack-mcp-tokens.json:/root/.slack-mcp-tokens.json ghcr.io/jtalk22/slack-mcp-server
243
+ Priority 1: Environment Variables (SLACK_TOKEN, SLACK_COOKIE)
244
+ fallback
245
+ Priority 2: Token File (~/.slack-mcp-tokens.json)
246
+ fallback
247
+ Priority 3: macOS Keychain (encrypted)
248
+ ↓ fallback
249
+ Priority 4: Chrome Auto-Extraction (macOS only)
196
250
  ```
197
251
 
198
- For MCP configuration with Docker:
252
+ ### Stability Features
199
253
 
200
- ```json
201
- {
202
- "mcpServers": {
203
- "slack": {
204
- "command": "docker",
205
- "args": ["run", "-i", "--rm", "-e", "SLACK_TOKEN", "-e", "SLACK_COOKIE", "ghcr.io/jtalk22/slack-mcp-server"],
206
- "env": {
207
- "SLACK_TOKEN": "xoxc-your-token",
208
- "SLACK_COOKIE": "xoxd-your-cookie"
209
- }
210
- }
211
- }
212
- }
254
+ #### Atomic Writes
255
+ All file operations (tokens, DM cache) use atomic writes:
213
256
  ```
257
+ Write to temp file → chmod 600 → rename to target
258
+ ```
259
+ This prevents JSON corruption if the process is killed mid-write.
214
260
 
215
- ## Token Management
216
-
217
- Tokens are stored in multiple layers for reliability:
261
+ #### Zombie Process Protection
262
+ Background refresh timers use `unref()`:
263
+ ```javascript
264
+ const timer = setInterval(refreshTokens, 4 * 60 * 60 * 1000);
265
+ timer.unref(); // Process can exit even if timer is pending
266
+ ```
267
+ When Claude closes the MCP connection, the server exits cleanly.
268
+
269
+ #### Race Condition Prevention
270
+ A mutex lock prevents concurrent Chrome extractions:
271
+ ```javascript
272
+ if (refreshInProgress) return null; // Skip if already refreshing
273
+ refreshInProgress = true;
274
+ try { return extractFromChromeInternal(); }
275
+ finally { refreshInProgress = false; }
276
+ ```
218
277
 
219
- 1. **Environment variables** - From MCP config
220
- 2. **Token file** - `~/.slack-mcp-tokens.json` (chmod 600)
221
- 3. **macOS Keychain** - Encrypted persistent storage
222
- 4. **Chrome auto-extraction** - Fallback when tokens expire
278
+ ---
223
279
 
224
- ### When Tokens Expire
280
+ ## Web UI (for claude.ai)
225
281
 
226
- Tokens typically last 1-2 weeks. When they expire:
282
+ Since claude.ai doesn't support MCP, use the REST server:
227
283
 
228
284
  ```bash
229
- # Option 1: In Claude
230
- slack_refresh_tokens
231
-
232
- # Option 2: CLI
233
- npm run tokens:auto
285
+ npm run web
286
+ # Or: npx @jtalk22/slack-mcp web
234
287
  ```
235
288
 
236
- ## Troubleshooting
237
-
238
- ### DMs Not Showing
289
+ **Magic Link (v1.1.0+):** The console prints a one-click URL with the API key embedded:
239
290
 
240
- This is handled automatically. The server discovers DMs by calling `conversations.open` for each user (Slack's `conversations.list` doesn't return DMs with browser tokens).
291
+ ```
292
+ ════════════════════════════════════════════════════════════
293
+ Slack Web API Server v1.1.0
294
+ ════════════════════════════════════════════════════════════
241
295
 
242
- ### Rate Limiting
296
+ Dashboard: http://localhost:3000/?key=smcp_xxxxxxxxxxxx
297
+ ```
243
298
 
244
- The client implements automatic retry with exponential backoff. If you still hit limits, reduce batch sizes in your queries.
299
+ Just click the link - no copy-paste needed. The key is saved to your browser and stripped from the URL for security.
245
300
 
246
- ### Claude Desktop Not Seeing Tools
301
+ <details>
302
+ <summary><strong>Screenshots</strong></summary>
247
303
 
248
- 1. Verify JSON syntax in config
249
- 2. Check logs: `~/Library/Logs/Claude/mcp-server-slack.log`
250
- 3. Fully restart Claude Desktop (Cmd+Q, then reopen)
304
+ | DMs View | Channels View |
305
+ |----------|---------------|
306
+ | ![DMs](docs/images/demo-main.png) | ![Channels](docs/images/demo-channels.png) |
251
307
 
252
- ### Chrome Extraction Fails
308
+ </details>
253
309
 
254
- - Chrome must be running (not just in Dock)
255
- - Have a Slack tab open at `app.slack.com`
256
- - Be logged into Slack
310
+ ---
257
311
 
258
- ## How It Works
312
+ ## Troubleshooting
259
313
 
260
- This server uses Slack's internal Web API with browser session tokens (`xoxc-` token and `xoxd-` cookie). This provides the same access level as the Slack web interface.
314
+ ### Tokens Expired
315
+ ```bash
316
+ # macOS: Auto-refresh from Chrome
317
+ slack_refresh_tokens # In Claude
318
+ # Or: npm run tokens:auto
261
319
 
262
- **Why not a Slack App?**
320
+ # Linux/Windows: Manual update
321
+ # Edit ~/.slack-mcp-tokens.json with fresh values
322
+ ```
263
323
 
264
- Slack apps require OAuth and cannot access DMs without explicit per-conversation authorization from users. Browser tokens bypass this limitation.
324
+ ### DMs Not Showing
325
+ Use `discover_dms: true` to force discovery:
326
+ ```
327
+ slack_list_conversations with discover_dms=true
328
+ ```
329
+ This caches DM channel IDs for 24 hours.
265
330
 
266
- **Trade-offs:**
267
- - Full access to all conversations
268
- - No per-conversation authorization
269
- - Tokens expire every 1-2 weeks
270
- - ❌ Requires Chrome for token extraction
271
- - ❌ Not officially supported by Slack
331
+ ### Chrome Extraction Fails
332
+ - Chrome must be **running** (not minimized to Dock)
333
+ - Slack tab must be open at `app.slack.com`
334
+ - You must be logged in
272
335
 
273
- ## Security Notes
336
+ ### Claude Desktop Not Seeing Tools
337
+ 1. Verify JSON syntax in config file
338
+ 2. Check logs: `~/Library/Logs/Claude/mcp*.log`
339
+ 3. Fully restart Claude (Cmd+Q, then reopen)
274
340
 
275
- - Tokens are stored with `chmod 600` (owner read/write only)
276
- - macOS Keychain provides encrypted storage
277
- - Never commit tokens to version control
278
- - Web server only accessible on localhost by default
341
+ ---
279
342
 
280
343
  ## Project Structure
281
344
 
282
345
  ```
283
346
  slack-mcp-server/
284
347
  ├── src/
285
- │ ├── server.js # MCP server entry point
348
+ │ ├── server.js # MCP server (stdio transport)
286
349
  │ └── web-server.js # REST API + Web UI
287
350
  ├── lib/
288
- │ ├── token-store.js # 4-layer token persistence
289
- │ ├── slack-client.js # API client with retry logic
351
+ │ ├── token-store.js # 4-layer persistence + atomic writes
352
+ │ ├── slack-client.js # API client, LRU cache, retry logic
290
353
  │ ├── tools.js # MCP tool definitions
291
354
  │ └── handlers.js # Tool implementations
292
355
  ├── public/
293
356
  │ ├── index.html # Web UI
294
- │ └── demo.html # Interactive demo with mock data
295
- ├── scripts/
296
- └── token-cli.js # Token management CLI
297
- └── docs/
298
- ├── images/ # Screenshots
299
- ├── SETUP.md # Detailed setup guide
300
- ├── API.md # Tool reference
301
- ├── WEB-API.md # REST API reference
302
- └── TROUBLESHOOTING.md
357
+ │ └── demo.html # Interactive demo
358
+ └── scripts/
359
+ └── token-cli.js # Token management CLI
303
360
  ```
304
361
 
305
- ## Contributing
362
+ ---
363
+
364
+ ## Security
365
+
366
+ - Token files stored with `chmod 600` (owner-only)
367
+ - macOS Keychain provides encrypted backup
368
+ - Web server binds to localhost only
369
+ - Never commit tokens to version control
370
+ - API keys are cryptographically random (`crypto.randomBytes`)
371
+
372
+ ---
373
+
374
+ ## Platform Support
375
+
376
+ | Feature | macOS | Linux | Windows |
377
+ |---------|-------|-------|---------|
378
+ | MCP Server | Yes | Yes | Yes |
379
+ | Token File | Yes | Yes | Yes |
380
+ | Auto-Refresh from Chrome | Yes | No | No |
381
+ | Keychain Storage | Yes | No | No |
382
+ | Web UI | Yes | Yes | Yes |
306
383
 
307
- Contributions welcome! Please:
384
+ ---
385
+
386
+ ## Contributing
308
387
 
309
388
  1. Fork the repository
310
389
  2. Create a feature branch
311
390
  3. Make your changes
312
- 4. Submit a pull request
391
+ 4. Run `node --check` on modified files
392
+ 5. Submit a pull request
393
+
394
+ ---
313
395
 
314
396
  ## Support
315
397
 
316
- If you find this useful, consider supporting the project:
398
+ If this saved you from OAuth hell, consider:
317
399
 
318
400
  - [GitHub Sponsors](https://github.com/sponsors/jtalk22)
319
- - [Ko-fi](https://ko-fi.com/jtalk22)
320
- - [Buy Me a Coffee](https://www.buymeacoffee.com/jtalk22)
401
+ - Star the repo
321
402
 
322
- Star the repo if it helped you!
403
+ ---
323
404
 
324
405
  ## License
325
406
 
326
- MIT - See [LICENSE](LICENSE) for details.
407
+ MIT - See [LICENSE](LICENSE)
408
+
409
+ ---
327
410
 
328
411
  ## Disclaimer
329
412
 
330
- This project uses unofficial Slack APIs. Use at your own risk. The authors are not responsible for any account issues that may arise from using this software.
413
+ This project uses unofficial Slack APIs. Use at your own risk. Not affiliated with or endorsed by Slack Technologies.