@jtalk22/slack-mcp 4.4.2 → 4.4.3

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
@@ -60,7 +60,7 @@ Six prebuilt templates ship with the package:
60
60
  npx -y @jtalk22/slack-mcp --apply-template oncall-handoff --channels C012345,C067890
61
61
  ```
62
62
 
63
- Available templates: `oncall-handoff`, `support-triage`, `exec-monday`, `sprint-tracker`, `customer-feedback`, `incident-room`. The structural primitives (`slack_workflow_save`, `slack_workflows`) are free forever in OSS; the hosted brain is `$0` to start (no card) and `$9/mo` Pro for unlimited AI tools (scheduled morning catch-up DM in development).
63
+ Available templates: `oncall-handoff`, `support-triage`, `exec-monday`, `sprint-tracker`, `customer-feedback`, `incident-room`. The structural primitives (`slack_workflow_save`, `slack_workflows`) are free forever in OSS; the hosted brain is `$0` to start (no card) and `$19/mo` Pro for unlimited AI tools.
64
64
 
65
65
  ## Quick Start per Client
66
66
 
@@ -268,10 +268,10 @@ Hosted tiers at [mcp.revasserlabs.com](https://mcp.revasserlabs.com):
268
268
  | Tier | Price | What it owns |
269
269
  |------|-------|-------------|
270
270
  | Self-host | Free (MIT) | Local stdio, all 21 tools (16 read/write Slack + 2 workflow profile primitives + 3 discoverable upgrade stubs to hosted brain) |
271
- | Hosted Free | $0 (no card) | Email signup, 1 workspace, 10 smart_search/mo + 3 catch_me_up/mo + 5 triage/day. All 5 workflow profile types. 7-day index retention. |
272
- | Pro | $9/mo | Unlimited AI tools, **scheduled morning catch-up DM** *(in development, 8am workspace tz)*, permanent OAuth, 90-day Vectorize, 2 workspaces |
273
- | Team | $49/mo flat | Pro + shared workflow profiles + audit log + 24h support + scheduled catch-up to channel + 5 workspaces |
274
- | Ops | from $199/mo (custom) | SLA, custom retention, SOC2 evidence path, multi-tenant isolation, 10+ workspaces, dedicated workflow tuning |
271
+ | Hosted Free | $0 (no card) | Email signup, 1 workspace, 2,000 requests/mo + 25 AI tool calls/mo. All 5 workflow profile types. 7-day index retention. |
272
+ | Pro | $19/mo or $190/yr | Unlimited requests (fair use), unlimited AI tool calls, permanent OAuth, email support, 2 workspaces |
273
+ | Team | $49/mo or $490/yr flat | Everything in Pro + shared workflow profiles, 5 workspaces, 24h support |
274
+ | Safeguard | $199/mo waitlist | Agent approval gates, scheduled catch-up DM, workspace memory all *(in development)*. Waitlist only. |
275
275
 
276
276
  </details>
277
277
 
@@ -324,6 +324,22 @@ Full release notes on [GitHub releases/latest](https://github.com/jtalk22/slack-
324
324
 
325
325
  </details>
326
326
 
327
+ ## Token expired? / OAuth Lifeboat
328
+
329
+ Session tokens (`xoxc-` + `xoxd-`) are extracted from your browser, and Slack rotates them roughly every 1-2 weeks. When they die, every tool call fails to authenticate. Instead of surfacing a raw Slack error, this server detects token death — `invalid_auth`, `not_authed`, `token_expired`, `token_revoked`, `account_inactive`, or an HTTP 401 — and returns a recovery message at the moment of pain.
330
+
331
+ **Self-fix — re-extract fresh tokens:**
332
+
333
+ ```bash
334
+ npx -y @jtalk22/slack-mcp --setup
335
+ ```
336
+
337
+ On macOS with a logged-in Slack tab open in Chrome, you can instead call the `slack_refresh_tokens` tool (or run `npm run tokens:auto`). To avoid silent expiration during long idle windows, set up the optional [token-refresh LaunchAgent](docs/SETUP.md#keep-tokens-fresh-while-claude-is-closed-macos-optional).
338
+
339
+ **Permanent fix — no rotation:** the [hosted version](https://mcp.revasserlabs.com/setup?utm_source=lifeboat&utm_medium=npm&utm_campaign=token_death) uses OAuth, which does not rotate every 1-2 weeks. Free tier available, no card.
340
+
341
+ The recovery message appears at most once per process per hour; repeat failures inside that window get a one-line reminder so agents in retry loops don't spam. Set `SLACK_MCP_NO_UPSELL=1` to drop the hosted-option line while keeping the self-fix guidance.
342
+
327
343
  ## Rich Message Fields
328
344
 
329
345
  Added in 4.4.0. The four read tools marked ‡ above accept `include_rich_message_fields: true`, which surfaces the parts of a message that live outside `text` — `attachments`, `blocks`, `files`, `reactions`, `metadata`, plus `subtype`/`bot_id`/`app_id` (automated/bot/app markers) and `team` (workspace id).
@@ -410,4 +426,4 @@ Not affiliated with Slack Technologies, Inc. Uses browser session credentials
410
426
 
411
427
  ---
412
428
 
413
- Hosted version live at [mcp.revasserlabs.com](https://mcp.revasserlabs.com): Free tier (no card), $9/mo Pro, $49/mo Team flat, Ops from $199/mo. Hosted owns the AI brain (smart_search, catch_me_up, triage), the scheduled morning catch-up DM at 8am workspace time *(in development)*, permanent OAuth (no 2-week token rotation), 90-day Vectorize retention, and shared workflow profiles. The OSS package owns local stdio + the 16 Slack tools (12 read, 4 write) + workflow profile primitives (slack_workflow_save, slack_workflows). The 3 paid stubs (slack_smart_search, slack_catch_me_up, slack_triage) appear in OSS as discoverable upgrade prompts.
429
+ Hosted version live at [mcp.revasserlabs.com](https://mcp.revasserlabs.com): Free tier (no card — 2,000 requests/mo + 25 AI tool calls/mo), $19/mo Pro (unlimited, permanent OAuth), $49/mo Team flat, and Safeguard $199/mo (waitlist). Hosted owns the AI brain (smart_search, catch_me_up, triage), permanent OAuth (no 2-week token rotation), and shared workflow profiles; the scheduled morning catch-up DM at 8am workspace time is a Safeguard feature *(in development)*. The OSS package owns local stdio + the 16 Slack tools (12 read, 4 write) + workflow profile primitives (slack_workflow_save, slack_workflows). The 3 paid stubs (slack_smart_search, slack_catch_me_up, slack_triage) appear in OSS as discoverable upgrade prompts.
@@ -8,7 +8,7 @@ Use this guide to choose the right operating mode before rollout.
8
8
  - Choose local `web` for browser workflows and manual Slack browsing.
9
9
  - Choose hosted HTTP only when you need remote execution and can handle token operations.
10
10
  - Choose Smithery/Worker only when your consumers require registry-hosted MCP transport.
11
- - A managed **Hosted** version is live at [mcp.revasserlabs.com](https://mcp.revasserlabs.com) — Free tier (no card), Pro $9/mo, Team $49/mo flat, Ops from $199/mo. See [pricing](https://mcp.revasserlabs.com/pricing).
11
+ - A managed **Hosted** version is live at [mcp.revasserlabs.com](https://mcp.revasserlabs.com) — Free tier (no card), Pro $19/mo, Team $49/mo flat, Safeguard $199/mo (waitlist). See [pricing](https://mcp.revasserlabs.com/pricing).
12
12
 
13
13
  ## Mode Matrix
14
14
 
@@ -31,7 +31,7 @@ If `--version` fails here, the issue is install/runtime path, not Slack credenti
31
31
 
32
32
  ## Hosted Version
33
33
 
34
- The hosted version is live at [mcp.revasserlabs.com](https://mcp.revasserlabs.com). Free tier (no card) ships 10 smart_search/mo + 3 catch_me_up/mo + 5 triage/day + all 5 workflow profile types. Pro at $9/mo unlocks unlimited AI tools, the scheduled morning catch-up DM at 8am workspace time *(in development)*, permanent OAuth (no 2-week token rotation), and 90-day Vectorize retention. Team at $49/mo flat covers 5 workspaces with shared workflow profiles and audit log. Ops engagement starts at $199/mo (custom) for 10+ workspace organizations with SLA, custom retention, SOC2 evidence, or multi-tenant isolation.
34
+ The hosted version is live at [mcp.revasserlabs.com](https://mcp.revasserlabs.com). Free tier (no card) ships 2,000 requests/mo + 25 AI tool calls/mo + all 5 workflow profile types. Pro at $19/mo (or $190/yr) unlocks unlimited requests and AI tool calls, permanent OAuth (no 2-week token rotation), email support, and 2 workspaces. Team at $49/mo flat (or $490/yr) covers 5 workspaces with shared workflow profiles and 24h support. Safeguard at $199/mo (waitlist only) adds agent approval gates, the scheduled morning catch-up DM at 8am workspace time, and workspace memory — all *(in development)*.
35
35
 
36
36
  The OSS package keeps the local-machine path. The hosted version adds the AI brain (smart_search, catch_me_up, triage) — these tools also appear in the OSS package as discoverable upgrade stubs that point at the hosted signup.
37
37
 
package/lib/handlers.js CHANGED
@@ -21,6 +21,7 @@ import {
21
21
  ALLOWED_WORKFLOW_KINDS_LIST,
22
22
  } from "./workflow-store.js";
23
23
  import { withRichMessageFields } from "./rich-message-fields.js";
24
+ import { isAuthDeath, buildLifeboatPayload } from "./lifeboat.js";
24
25
 
25
26
  // ============ Utilities ============
26
27
 
@@ -169,6 +170,11 @@ export async function handleHealthCheck() {
169
170
  token_updated: creds.updatedAt || null
170
171
  });
171
172
  } catch (e) {
173
+ // OAuth Lifeboat: a dead session token here is the most common first
174
+ // signal of token death — hand back recovery guidance, not a bare error.
175
+ if (isAuthDeath(e)) {
176
+ return asMcpJson(buildLifeboatPayload(e), true);
177
+ }
172
178
  return asMcpJson({
173
179
  status: "error",
174
180
  code: "auth_failed",
@@ -871,8 +877,8 @@ const HOSTED_UPGRADE_PAYLOAD = {
871
877
  message: "This tool needs hosted mode (Vectorize + Workers AI). Get free monthly credits at mcp.revasserlabs.com — no card required.",
872
878
  signup_url: "https://mcp.revasserlabs.com/signup",
873
879
  upgrade_url: "https://mcp.revasserlabs.com/pricing",
874
- free_tier_quota: "10 smart_search + 3 catch_me_up per month, 5 triage per day",
875
- pro_value_prop: "Pro $9/mo unlocks unlimited AI tools (scheduled morning catch-up DM at 8am workspace time in development).",
880
+ free_tier_quota: "2,000 requests/mo + 25 AI tool calls/mo (no card)",
881
+ pro_value_prop: "Pro $19/mo unlocks unlimited requests and AI tool calls, permanent OAuth (no token rotation).",
876
882
  };
877
883
 
878
884
  export async function handleSmartSearch(args) {
@@ -0,0 +1,171 @@
1
+ /**
2
+ * OAuth Lifeboat
3
+ *
4
+ * Detects Slack session-token death at the moment of pain and returns a
5
+ * genuinely helpful recovery message instead of a raw Slack API error.
6
+ *
7
+ * Session tokens (xoxc/xoxd) are extracted from the browser and Slack rotates
8
+ * them roughly every 1-2 weeks. When they die, every tool call fails with an
9
+ * auth error. This module classifies that failure and hands the user the
10
+ * self-fix first (re-extract) and the permanent fix second (hosted OAuth).
11
+ *
12
+ * Design rules:
13
+ * - Self-fix is always shown; the hosted option is shown second and is
14
+ * suppressed entirely by SLACK_MCP_NO_UPSELL=1.
15
+ * - The long-form message is emitted at most once per process per hour;
16
+ * subsequent failures inside that window get a one-line version so agents
17
+ * in retry loops do not spam.
18
+ * - Never reads or logs token values — it only inspects error codes.
19
+ */
20
+
21
+ // Slack API error codes (and the HTTP 401 case) that mean the session token
22
+ // is dead and cannot be auto-healed — the point where the Lifeboat fires.
23
+ export const AUTH_DEATH_SLACK_CODES = new Set([
24
+ "invalid_auth",
25
+ "not_authed",
26
+ "token_expired",
27
+ "token_revoked",
28
+ "account_inactive",
29
+ ]);
30
+
31
+ const THROTTLE_WINDOW_MS = 60 * 60 * 1000; // one long-form message per process per hour
32
+
33
+ const SETUP_CMD = "npx -y @jtalk22/slack-mcp --setup";
34
+ const README_ANCHOR_URL =
35
+ "https://github.com/jtalk22/slack-mcp-server#token-expired--oauth-lifeboat";
36
+ const HOSTED_SETUP_URL =
37
+ "https://mcp.revasserlabs.com/setup?utm_source=lifeboat&utm_medium=npm&utm_campaign=token_death";
38
+
39
+ // Module-level throttle state (shared across every transport in one process).
40
+ let lastLongFormAt = 0;
41
+
42
+ /**
43
+ * Reset the throttle. Intended for tests.
44
+ */
45
+ export function resetLifeboatThrottle() {
46
+ lastLongFormAt = 0;
47
+ }
48
+
49
+ function upsellEnabled() {
50
+ return process.env.SLACK_MCP_NO_UPSELL !== "1";
51
+ }
52
+
53
+ /**
54
+ * Pull the specific Slack auth-death code out of an error, if present.
55
+ * Returns the code string (e.g. "token_revoked") or null.
56
+ */
57
+ export function authDeathCode(err) {
58
+ if (!err) return null;
59
+
60
+ if (typeof err === "string") {
61
+ const s = err.trim().toLowerCase();
62
+ return AUTH_DEATH_SLACK_CODES.has(s) ? s : null;
63
+ }
64
+
65
+ const slackCode =
66
+ typeof err.slack_error === "string" ? err.slack_error.trim().toLowerCase() : null;
67
+ if (slackCode && AUTH_DEATH_SLACK_CODES.has(slackCode)) return slackCode;
68
+
69
+ const msg = typeof err.message === "string" ? err.message.trim().toLowerCase() : "";
70
+ if (AUTH_DEATH_SLACK_CODES.has(msg)) return msg;
71
+ for (const code of AUTH_DEATH_SLACK_CODES) {
72
+ if (msg.includes(code)) return code;
73
+ }
74
+
75
+ return null;
76
+ }
77
+
78
+ /**
79
+ * Classify an error as AUTH-DEATH.
80
+ * Accepts a thrown Error (optionally carrying `.slack_error`, `.code`,
81
+ * `.status`), a raw Slack error-code string, or an HTTP-401 signal.
82
+ */
83
+ export function isAuthDeath(err) {
84
+ if (!err) return false;
85
+
86
+ // The wrapped auth-failure lib/slack-client.js throws after a failed auto-heal.
87
+ if (typeof err === "object" && err.code === "token_auth_failed") return true;
88
+
89
+ if (authDeathCode(err)) return true;
90
+
91
+ // HTTP 401 (defensive — Slack normally returns HTTP 200 with ok:false).
92
+ if (typeof err === "string") {
93
+ const s = err.trim().toLowerCase();
94
+ return s === "401" || s.includes("http 401") || s.includes("status 401");
95
+ }
96
+ const status = err.status ?? err.statusCode ?? err.httpStatus ?? null;
97
+ if (status === 401) return true;
98
+ const msg = typeof err.message === "string" ? err.message.toLowerCase() : "";
99
+ return msg.includes("http 401") || msg.includes("status 401");
100
+ }
101
+
102
+ /**
103
+ * Build the structured recovery payload for an auth-death error.
104
+ * First call within the throttle window returns the long form; later calls
105
+ * return the one-line form. Honors SLACK_MCP_NO_UPSELL.
106
+ */
107
+ export function buildLifeboatPayload(err, options = {}) {
108
+ const now = options.now ?? Date.now();
109
+ const slackError = authDeathCode(err);
110
+ const upsell = upsellEnabled();
111
+
112
+ const throttled = lastLongFormAt > 0 && now - lastLongFormAt < THROTTLE_WINDOW_MS;
113
+
114
+ if (throttled) {
115
+ const message = upsell
116
+ ? `Slack session token is still expired or revoked. Re-extract with \`${SETUP_CMD}\`. Permanent fix (hosted OAuth, free tier): ${HOSTED_SETUP_URL}`
117
+ : `Slack session token is still expired or revoked. Re-extract with \`${SETUP_CMD}\`.`;
118
+ return {
119
+ status: "error",
120
+ code: "slack_auth_expired",
121
+ slack_error: slackError,
122
+ throttled: true,
123
+ message,
124
+ next_action: `Run \`${SETUP_CMD}\`.`,
125
+ };
126
+ }
127
+
128
+ lastLongFormAt = now;
129
+
130
+ const payload = {
131
+ status: "error",
132
+ code: "slack_auth_expired",
133
+ slack_error: slackError,
134
+ throttled: false,
135
+ message:
136
+ "Your Slack session token has expired or been revoked. Slack rotates browser session tokens (xoxc/xoxd) roughly every 1-2 weeks, so this is expected — the server can no longer authenticate until you supply fresh tokens.",
137
+ self_fix:
138
+ `Re-extract fresh tokens: run \`${SETUP_CMD}\`. On macOS with Slack open in Chrome you can instead call the slack_refresh_tokens tool. Full steps: ${README_ANCHOR_URL}`,
139
+ };
140
+
141
+ // Preserve the auto-heal diagnostic when the wrapped error carried one.
142
+ if (err && typeof err === "object" && err.extraction_error) {
143
+ payload.extraction_error = err.extraction_error;
144
+ }
145
+
146
+ if (upsell) {
147
+ payload.hosted_option =
148
+ `To stop re-extracting every 1-2 weeks, switch to hosted OAuth (it never rotates): ${HOSTED_SETUP_URL} — free tier available, no credit card.`;
149
+ payload.next_action = `Run \`${SETUP_CMD}\` to re-extract tokens, or switch to permanent hosted OAuth (see hosted_option).`;
150
+ } else {
151
+ payload.next_action = `Run \`${SETUP_CMD}\` to re-extract tokens (macOS: call the slack_refresh_tokens tool).`;
152
+ }
153
+
154
+ return payload;
155
+ }
156
+
157
+ /**
158
+ * Wrap the recovery payload as an MCP tool-error response.
159
+ * Used by both transports (stdio + HTTP) so the recovery surface is identical.
160
+ */
161
+ export function lifeboatResponse(err) {
162
+ return {
163
+ content: [
164
+ {
165
+ type: "text",
166
+ text: JSON.stringify(buildLifeboatPayload(err), null, 2),
167
+ },
168
+ ],
169
+ isError: true,
170
+ };
171
+ }
@@ -63,7 +63,7 @@ function shareLinks() {
63
63
  }
64
64
 
65
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. Hosted free tier (no card) live at <a href="${PUBLIC_METADATA.canonicalSiteUrl}">mcp.revasserlabs.com</a> — Pro $9/mo unlocks unlimited AI tools (scheduled morning catch-up DM in development).`;
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. Hosted free tier (no card) live at <a href="${PUBLIC_METADATA.canonicalSiteUrl}">mcp.revasserlabs.com</a> — Pro $19/mo unlocks unlimited AI tools and permanent OAuth.`;
67
67
  }
68
68
 
69
69
  function demoLinks() {
@@ -75,7 +75,7 @@ function demoLinks() {
75
75
  }
76
76
 
77
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. Hosted free tier (no card) live at <a href="${PUBLIC_METADATA.canonicalSiteUrl}" target="_blank" rel="noopener noreferrer">mcp.revasserlabs.com</a> — Pro $9/mo unlocks unlimited AI tools (scheduled morning catch-up DM in development).`;
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. Hosted free tier (no card) live at <a href="${PUBLIC_METADATA.canonicalSiteUrl}" target="_blank" rel="noopener noreferrer">mcp.revasserlabs.com</a> — Pro $19/mo unlocks unlimited AI tools and permanent OAuth.`;
79
79
  }
80
80
 
81
81
  function demoFooterLinks() {
@@ -113,7 +113,7 @@ function commonTokens() {
113
113
  SELF_HOSTED_TOOL_COUNT: String(PUBLIC_METADATA.selfHostedToolCount),
114
114
  CLOUD_MANAGED_TOOL_COUNT: "15",
115
115
  TEAM_AI_WORKFLOW_COUNT: "3",
116
- CLOUD_SOLO_PRICE: "$9/mo",
116
+ CLOUD_SOLO_PRICE: "$19/mo",
117
117
  CLOUD_TEAM_PRICE: "$49/mo",
118
118
  CLOUD_TURNKEY_LAUNCH_PRICE: "contact us",
119
119
  CLOUD_MANAGED_RELIABILITY_PRICE: "contact us",
package/lib/tools.js CHANGED
@@ -504,7 +504,7 @@ export const TOOLS = [
504
504
  // pointing at mcp.revasserlabs.com — the hosted worker actually runs them.
505
505
  {
506
506
  name: "slack_smart_search",
507
- description: "Semantic + lexical hybrid search across your indexed Slack history. Returns ranked results with relevance scores, channel context, thread context, and matched terms. Hosted-only (requires Vectorize + Workers AI). Free tier ships 10 calls/month; upgrade to Pro $9/mo for unlimited at mcp.revasserlabs.com/pricing.",
507
+ description: "Semantic + lexical hybrid search across your indexed Slack history. Returns ranked results with relevance scores, channel context, thread context, and matched terms. Hosted-only (requires Vectorize + Workers AI). Free tier ships 25 AI tool calls/month (shared across the hosted AI tools); upgrade to Pro $19/mo for unlimited at mcp.revasserlabs.com/pricing.",
508
508
  inputSchema: {
509
509
  type: "object",
510
510
  properties: {
@@ -537,7 +537,7 @@ export const TOOLS = [
537
537
  },
538
538
  {
539
539
  name: "slack_catch_me_up",
540
- description: "Run a structured catch-up against a saved workflow profile. Returns structured JSON per the profile's workflow_kind: support_inbox returns {open_threads, ack_lag, owner_gaps, escalations, next_actions}; incident_room returns {incident_summary, timeline, open_risks, owner_gaps, next_actions}; exec_brief returns {summary, decisions, risks, asks, action_items}; product_launch_watch returns {launch_signals, feedback_themes, blockers, metrics, next_actions}; custom returns {summary, highlights, open_questions, next_actions}. Hosted-only. Free tier ships 3 calls/month; Pro $9/mo unlocks unlimited (scheduled morning DM at 8am workspace tz in development).",
540
+ description: "Run a structured catch-up against a saved workflow profile. Returns structured JSON per the profile's workflow_kind: support_inbox returns {open_threads, ack_lag, owner_gaps, escalations, next_actions}; incident_room returns {incident_summary, timeline, open_risks, owner_gaps, next_actions}; exec_brief returns {summary, decisions, risks, asks, action_items}; product_launch_watch returns {launch_signals, feedback_themes, blockers, metrics, next_actions}; custom returns {summary, highlights, open_questions, next_actions}. Hosted-only. Free tier ships 25 AI tool calls/month (shared across the hosted AI tools); Pro $19/mo unlocks unlimited.",
541
541
  inputSchema: {
542
542
  type: "object",
543
543
  properties: {
@@ -561,7 +561,7 @@ export const TOOLS = [
561
561
  },
562
562
  {
563
563
  name: "slack_triage",
564
- description: "Classify and route Slack threads against a workflow profile. Returns triage decisions per thread: priority (low|medium|high|urgent), suggested owner, escalation flag, time-sensitivity, and a routing recommendation. Hosted-only. Free tier ships 5 triage runs per day; Pro $9/mo unlocks unlimited.",
564
+ description: "Classify and route Slack threads against a workflow profile. Returns triage decisions per thread: priority (low|medium|high|urgent), suggested owner, escalation flag, time-sensitivity, and a routing recommendation. Hosted-only. Free tier ships 25 AI tool calls/month (shared across the hosted AI tools); Pro $19/mo unlocks unlimited.",
565
565
  inputSchema: {
566
566
  type: "object",
567
567
  properties: {
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": "4.4.2",
5
- "description": "Slack MCP without OAuth — 21 tools, session-based, local-first. Free OSS + hosted tier from $9/mo.",
4
+ "version": "4.4.3",
5
+ "description": "Slack MCP without OAuth — 21 tools, session-based, local-first. Free OSS + hosted tier from $19/mo.",
6
6
  "type": "module",
7
7
  "main": "src/server.js",
8
8
  "bin": {
package/public/share.html CHANGED
@@ -124,7 +124,7 @@
124
124
  <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">Hosted</a>
125
125
  </div>
126
126
 
127
- <p class="note"><strong>Verify in 30 seconds:</strong> <code>--version</code>, <code>--doctor</code>, <code>--status</code>. Self-host gives 21 tools with session-based auth. Works with any MCP client — Claude, ChatGPT, Cursor, Copilot, Gemini, Windsurf. Hosted free tier (no card) live at <a href="https://mcp.revasserlabs.com">mcp.revasserlabs.com</a> — Pro $9/mo unlocks unlimited AI tools (scheduled morning catch-up DM in development).</p>
127
+ <p class="note"><strong>Verify in 30 seconds:</strong> <code>--version</code>, <code>--doctor</code>, <code>--status</code>. Self-host gives 21 tools with session-based auth. Works with any MCP client — Claude, ChatGPT, Cursor, Copilot, Gemini, Windsurf. Hosted free tier (no card) live at <a href="https://mcp.revasserlabs.com">mcp.revasserlabs.com</a> — Pro $19/mo unlocks unlimited AI tools and permanent OAuth.</p>
128
128
  </main>
129
129
  </body>
130
130
  </html>
@@ -43,7 +43,7 @@ function printUsage() {
43
43
  console.log(" slack-mcp --apply-template support-triage --channels C012345,C067890");
44
44
  console.log("");
45
45
  console.log("Templates write to ~/.slack-mcp-workflows.json. The hosted AI brain at");
46
- console.log("mcp.revasserlabs.com (free tier or Pro $9/mo) reads these profiles and");
46
+ console.log("mcp.revasserlabs.com (free tier or Pro $19/mo) reads these profiles and");
47
47
  console.log("returns structured JSON per the workflow_kind. The OSS package ships the");
48
48
  console.log("profile primitives + 3 discoverable upgrade stubs (slack_smart_search,");
49
49
  console.log("slack_catch_me_up, slack_triage). The brain is hosted-only.");
@@ -113,5 +113,5 @@ if (!profile.channels.length) {
113
113
  console.log("Or call slack_workflow_save from your MCP client to update.");
114
114
  } else {
115
115
  console.log("Profile is ready. Run slack_catch_me_up against it from your MCP client.");
116
- console.log(`(Free tier: 3 catch_me_up calls/month. Pro $9/mo unlocks unlimited; scheduled morning DM in development.)`);
116
+ console.log(`(Free tier: 25 AI tool calls/month. Pro $19/mo unlocks unlimited.)`);
117
117
  }
@@ -474,7 +474,7 @@ async function showHelp() {
474
474
  print(" https://github.com/jtalk22/slack-mcp-server");
475
475
  print();
476
476
  print(`${colors.bold}Hosted tier:${colors.reset}`);
477
- print(" https://mcp.revasserlabs.com — $9/mo Pro, permanent OAuth,");
477
+ print(" https://mcp.revasserlabs.com — $19/mo Pro, permanent OAuth,");
478
478
  print(" semantic search, workflow continuity across channels.");
479
479
  }
480
480
 
@@ -548,7 +548,7 @@ async function main() {
548
548
  print(" • Or add to Claude Desktop config");
549
549
  print();
550
550
  print(`${colors.dim}Want permanent tokens, semantic search, and workflow continuity?${colors.reset}`);
551
- print(`${colors.dim}Hosted tier: https://mcp.revasserlabs.com — $9/mo Pro, 10 free paid calls.${colors.reset}`);
551
+ print(`${colors.dim}Hosted tier: https://mcp.revasserlabs.com — $19/mo Pro, 25 free AI calls/mo.${colors.reset}`);
552
552
  } else {
553
553
  print(`${colors.red}Setup failed.${colors.reset} See errors above.`);
554
554
  process.exit(1);
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": "Slack MCP without OAuth \u2014 21 tools, session-based, local-first. Free OSS + hosted tier from $9/mo.",
5
+ "description": "Slack MCP without OAuth \u2014 21 tools, session-based, local-first. Free OSS + hosted tier from $19/mo.",
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": "4.4.2",
20
+ "version": "4.4.3",
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": "4.4.2",
31
+ "version": "4.4.3",
32
32
  "transport": {
33
33
  "type": "stdio"
34
34
  },
@@ -17,6 +17,7 @@ import {
17
17
  import { TOOLS } from "../lib/tools.js";
18
18
  import { TOOL_HANDLERS } from "../lib/handlers.js";
19
19
  import { RELEASE_VERSION } from "../lib/public-metadata.js";
20
+ import { isAuthDeath, lifeboatResponse } from "../lib/lifeboat.js";
20
21
 
21
22
  const SERVER_NAME = "slack-mcp-server";
22
23
  const SERVER_VERSION = RELEASE_VERSION;
@@ -100,6 +101,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
100
101
  }
101
102
  return await handler(args);
102
103
  } catch (error) {
104
+ // OAuth Lifeboat: dead session token → recovery guidance, not a raw error.
105
+ if (isAuthDeath(error)) {
106
+ return lifeboatResponse(error);
107
+ }
103
108
  return {
104
109
  content: [{
105
110
  type: "text",
package/src/server.js CHANGED
@@ -34,6 +34,7 @@ import {
34
34
  handleHealthCheck,
35
35
  handleListConversations,
36
36
  } from "../lib/handlers.js";
37
+ import { isAuthDeath, lifeboatResponse } from "../lib/lifeboat.js";
37
38
 
38
39
  // Background refresh interval (4 hours)
39
40
  const BACKGROUND_REFRESH_INTERVAL = 4 * 60 * 60 * 1000;
@@ -232,21 +233,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
232
233
  }
233
234
  return await handler(args);
234
235
  } catch (error) {
235
- if (error?.code === "token_auth_failed") {
236
- return {
237
- content: [{
238
- type: "text",
239
- text: JSON.stringify({
240
- status: "error",
241
- code: "token_auth_failed",
242
- message: String(error?.message || error),
243
- slack_error: error.slack_error || null,
244
- extraction_error: error.extraction_error || null,
245
- next_action: error.next_action || "Open http://localhost:3000 and click Refresh, OR run `npm run tokens:auto` with Slack open in Chrome, OR check Chrome > View > Developer > Allow JavaScript from Apple Events."
246
- }, null, 2)
247
- }],
248
- isError: true
249
- };
236
+ // OAuth Lifeboat: dead session token → recovery guidance, not a raw error.
237
+ if (isAuthDeath(error)) {
238
+ return lifeboatResponse(error);
250
239
  }
251
240
  return {
252
241
  content: [{