|
| 1 | +--- |
| 2 | +description: One-time setup for the Slack bot token used by /slack-triage — create/scope the Slack app, store the credentials, and verify they work |
| 3 | +--- |
| 4 | + |
| 5 | +Set up (or repair) the Slack credentials that `/slack-triage` needs to read threads. This is a |
| 6 | +one-time concern; once it's working, run `/slack-triage` directly. |
| 7 | + |
| 8 | +The `slack` server reads `SLACK_BOT_TOKEN` and `SLACK_TEAM_ID` from the root `.env`, which |
| 9 | +`.mcp.json` sources when it launches the server. **That file is the single source of truth** for |
| 10 | +these secrets (gitignored via `.env`) and the same file the rest of the repo's tooling uses, so |
| 11 | +there's no second env file to keep in sync. See `.env.example` for the documented keys. The bot is |
| 12 | +**read-only** — it does not post — so it never needs `chat:write`. |
| 13 | + |
| 14 | +## Step 1 — Check what's already there |
| 15 | + |
| 16 | +Verify whether credentials are present **without printing their values** (source the env file first, |
| 17 | +since that's what the server uses — they won't be in the plain shell otherwise): |
| 18 | + |
| 19 | +```sh |
| 20 | +[ -f ./.env ] && . ./.env |
| 21 | +( [ -n "${SLACK_BOT_TOKEN:-}" ] && [ -n "${SLACK_TEAM_ID:-}" ] \ |
| 22 | + && ! printf '%s' "${SLACK_BOT_TOKEN:-}" | grep -q REPLACE ) && echo creds-present || echo creds-missing |
| 23 | +``` |
| 24 | + |
| 25 | +- If `creds-missing` → go to Step 2 (create/configure the app and store the token). |
| 26 | +- If `creds-present` → skip to Step 5 to verify scopes are actually sufficient. (A token can be set |
| 27 | + but lack scopes — e.g. name resolution fails — so verifying is worthwhile even when present.) |
| 28 | + |
| 29 | +## Step 2 — Create or open the Slack app and set scopes |
| 30 | + |
| 31 | +If the user doesn't have a bot token yet, walk them through it: |
| 32 | + |
| 33 | +- Go to https://api.slack.com/apps → *Create New App* → *From scratch*, pick the workspace (or open |
| 34 | + the existing app). |
| 35 | +- *OAuth & Permissions* → *Bot Token Scopes*. Add these **read-only** scopes: |
| 36 | + - `channels:history`, `channels:read` — read public channels |
| 37 | + - `groups:history`, `groups:read` — read private channels |
| 38 | + - `users:read`, `users.profile:read` — resolve reporter display names |
| 39 | + - Do **not** add `chat:write` — the user posts the reply themselves; the bot only reads. |
| 40 | +- `SLACK_TEAM_ID` is the workspace id (`T…`), e.g. from the URL `app.slack.com/client/T0XXXXXX/…`. |
| 41 | + |
| 42 | +## Step 3 — Install (or reinstall) to the workspace |
| 43 | + |
| 44 | +- *OAuth & Permissions* → *Install to Workspace* → *Allow*. Copy the **Bot User OAuth Token** |
| 45 | + (`xoxb-…`). |
| 46 | +- **Adding scopes later requires a *Reinstall to Workspace*** — Slack only grants newly-added scopes |
| 47 | + on (re)install, which mints a **new** token. Changing the scope list in the config alone does |
| 48 | + nothing until you reinstall. After reinstalling, copy the new `xoxb-…` token. |
| 49 | + |
| 50 | +## Step 4 — Invite the bot to the channel |
| 51 | + |
| 52 | +In the target Slack channel, run `/invite @<app-name>`. This is required to read a **private** |
| 53 | +channel even with the scopes above (and harmless for public channels). |
| 54 | + |
| 55 | +## Step 5 — Store the credentials |
| 56 | + |
| 57 | +Ask the user to paste their `SLACK_BOT_TOKEN` (`xoxb-…`) and `SLACK_TEAM_ID` (`T…`). **Never echo the |
| 58 | +token back** in your replies. Then write them into the root `.env` as `KEY=value` lines — this is the |
| 59 | +file `.mcp.json` sources for the slack server: |
| 60 | + |
| 61 | +``` |
| 62 | +SLACK_BOT_TOKEN=xoxb-… |
| 63 | +SLACK_TEAM_ID=T… |
| 64 | +``` |
| 65 | + |
| 66 | +- The `.env` almost always already exists with other secrets — **preserve every other line**, only |
| 67 | + set/replace the `SLACK_BOT_TOKEN` and `SLACK_TEAM_ID` lines (append them if absent). Edit it without |
| 68 | + printing the existing contents. |
| 69 | +- It's gitignored via `.env` — never commit it or write the token anywhere else. Keep `.env.example` |
| 70 | + in sync if you introduce a new key. |
| 71 | + |
| 72 | +Tell the user to **restart Claude Code** afterward — `.mcp.json` sources this file only when it |
| 73 | +launches the server at startup, so a new/changed token is picked up only after a restart. |
| 74 | + |
| 75 | +> Note: if the token string is unchanged and you only *reinstalled* to grant new scopes, Slack grants |
| 76 | +> the new scopes to the existing token server-side, so a restart isn't strictly required for scope |
| 77 | +> changes. A restart is required whenever the **token value** changes. |
| 78 | +
|
| 79 | +## Step 6 — Verify |
| 80 | + |
| 81 | +After the restart, confirm the credentials actually work and carry the right scopes: |
| 82 | + |
| 83 | +- Re-run the Step 1 check (expect `creds-present`). |
| 84 | +- Discover the read tools with `ToolSearch` `slack thread replies conversation history permalink`, |
| 85 | + then make one real read call — e.g. fetch a user profile or the users list. A successful response |
| 86 | + means scopes are sufficient. |
| 87 | +- If a call fails with `missing_scope`, the error names the scope it `needed` and lists what the token |
| 88 | + currently `provided`. Add the missing scope in Step 2, **reinstall** (Step 3), and re-verify. Common |
| 89 | + cases: `users.profile:read` (resolve a single user's name) and `users:read` (list users). |
| 90 | +- The `atlassian` server (used by `/slack-triage` for Jira) authenticates via OAuth, not a token — if |
| 91 | + Jira calls error with auth, run `/mcp` and finish the Atlassian login. No token to store here. |
| 92 | + |
| 93 | +When the read call succeeds, setup is done — run `/slack-triage <thread-link>`. |
0 commit comments