slack-mcp-server
CLAUDE.md33 starsChanged 39 days agoMITView on GitHub
This file provides maintainer-oriented context for automated edits in this repository. Session-based Slack MCP server. Works with any MCP client via stdio transport, or via hosted HTTP for browser-based clients. Slack reads (13): Slack writes (4): slack_send_message, slack_add_reaction, slack_remove_reaction, slack_conversations_mark — all carry MCP destructive safety annotation. Workflow primitives (2): slack_workflow_save, slack_workflows — bind a workflow_kind (incident_room, exec_brief, support_inbox, product_launch_watch, custom) to channels + priority people + retention + cadence. Stored locally at ~/.slack-mcp-workflows.json. Local catch-up (1): slack_catch_me_up — reads…
- Installs packages
In this repository3 other files it gives its agents.
- slack-catch-upSkill
- slack-send-safelySkill
- slack-workflow-profilesSkill
The file
We split this CLAUDE.md into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 135
Public pages are generated: Never edit root index.html or public/*.html directly — edit templates/public-pages/*.tpl + lib/public-pages.js, …
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CLAUDE.md
This file provides maintainer-oriented context for automated edits in this repository.
Project Scope
Session-based Slack MCP server. Works with any MCP client via stdio transport, or via hosted HTTP for browser-based clients.
Build and Run
npm install
npm start # MCP server on stdio
npm run web # REST API + Web UI (localhost:3000)
npm run tokens:auto # Auto-extract from Chrome (macOS)
npm run tokens:status # Check token healthInstallation Paths
npx -y @jtalk22/slack-mcp # package entrypoint
docker pull ghcr.io/jtalk22/slack-mcp-server:latestMCP Tools (20 total)
Slack reads (13):
| Tool | Purpose |
slack_health_check | Verify token validity and show workspace info |
slack_token_status | Token age, health, cache stats |
slack_refresh_tokens | Auto-extract fresh tokens from Chrome (macOS) |
slack_list_conversations | List DMs and channels with resolved names |
slack_conversations_history | Get messages from a channel or DM |
slack_get_full_conversation | Export full history with threads |
slack_search_messages | Search across workspace |
slack_get_thread | Get thread replies |
slack_users_info | Get user details |
slack_list_users | List workspace users (paginated, 500+) |
slack_users_search | Search by name, display name, or email |
slack_conversations_unreads | Channels/DMs with unread messages |
slack_session_report | What this process read, sent and held, as counts (reads no Slack data) |
Slack writes (4): slack_send_message, slack_add_reaction, slack_remove_reaction, slack_conversations_mark — all carry MCP destructive safety annotation.
Workflow primitives (2): slack_workflow_save, slack_workflows — bind a workflow_kind (incident_room, exec_brief, support_inbox, product_launch_watch, custom) to channels + priority people + retention + cadence. Stored locally at ~/.slack-mcp-workflows.json.
Local catch-up (1): slack_catch_me_up — reads a saved profile's scope and returns structured evidence (lib/catch-up.js). There are no hosted upgrade stubs in the package since 5.0.0; every advertised tool runs locally.
Skills (3) and prompts: skills/<name>/SKILL.md (slack-catch-up,
slack-workflow-profiles, slack-send-safely) go out through the MCP Skills
extension (SEP-2640), as skill:// resources, and as prompts of the same
name, from lib/skills.js. A skill is offered only when every tool in its
metadata.requires-tools is advertised. Every other tool it names must be in
metadata.optional-tools, and its text must say what to do without it; the
test checks this on every built-in surface. SLACK_MCP_SKILLS_DIR adds an
operator's folder of skills, and bundled names win a collision.
SLACK_MCP_SKILLS=off serves none.
Token Persistence Layers
- Environment variables
- Token file (
~/.slack-mcp-tokens.json) - macOS Keychain
- Chrome auto-extraction (macOS only)
Storage backend: auto (file + Keychain, default), keychain-only (Keychain
exclusively, no plaintext file, verified writes, legacy file migrated in and
removed after verification — a removal failure throws plaintext_removal_failed
rather than passing silently — bookkeeping in ~/.slack-mcp-meta.json), or
file (Keychain never touched). On macOS, --setup asks and persists the
choice in the meta file; the SLACK_MCP_TOKEN_STORAGE env var overrides.
Unrecognized values from either source fail closed at startup. Sidecar writes
are serialized across processes via an O_EXCL lock file; a failed persist
keeps fresh tokens in memory (storage.unpersisted_fresh_tokens) so the
auth-retry path never reuses stale credentials.
Architecture Notes
- Session-based access uses browser tokens (
xoxc-+xoxd-). - Token lifecycle is time-bounded and may require refresh.
- Reliability controls include atomic file writes, mutex locking, and cached lookups.
Structure
src/
server.js MCP server entry point (stdio, era-negotiated via serveStdio)
server-http.js Streamable HTTP entry (stateless per request, MCP 2026-07-28)
web-server.js REST API + Web UI
lib/
mcp-server.js shared protocol-server factory (McpServer) both transports build from
skills.js loads skills/ + SLACK_MCP_SKILLS_DIR, filters by advertised tools
token-store.js token persistence
slack-client.js Slack API client and retry logic
tools.js MCP tool definitions
handlers.js MCP tool handlers
skills/ bundled SKILL.md playbooks (shipped in the npm files list and the Docker image)Claude Code Integration
The repo includes .claude/settings.json for local MCP server registration.
Tokens load from ~/.slack-mcp-tokens.json or SLACK_TOKEN/SLACK_COOKIE env vars.
Gotchas
mainis branch-protected. Direct pushes are rejected (remote rejected ... protected branch hook declined) regardless of what a generic "push straight to main" doctrine says. Every change goes through a PR, including one-line doc fixes. Squash-merge means the feature branch is not an ancestor ofmainafterwards, sogit branch -drefuses it — use-Donce the PR is merged.- The protocol claim is CI-gated.
README.mdmay say "2026-07-28" only whiletest/mcp-era.test.jsexists and passes;src/server-http.jsmust not containsessionIdGenerator(there is no session to mint) and nothing undersrc/orlib/may import the retired@modelcontextprotocol/sdkv1 package. The SDK is v2 (@modelcontextprotocol/server+/node;/clientis a devDependency for the era test). - Tool profiles must agree with the README's counts.
SLACK_MCP_TOOLSselectsall(20) /read(13) /essentials(6) or a custom list.READ_TOOLSis an explicit list, deliberately NOT derived from thereadOnlyHintannotation — that annotation is a safety signal, and deriving the surface from it once shipped tools that made no Slack call to users who narrowed their surface to save schema cost.check-public-surface-integrity.jsgates counts, name rot, and the absence of any paid-tier tool;npm run measure:toolsprints the schema cost per profile. - Branch names must not contain "claude" (or other AI-tool markers). The
attribution guardrail scans commit messages;
gh pr update-branchwrites "Merge branch 'main' into<branch>", so a marker in the branch name fails CI on the merge commit. Rebase instead of merge-updating if it happens. - Public pages are generated. Never edit root
index.htmlorpublic/*.htmldirectly — edittemplates/public-pages/*.tpl+lib/public-pages.js, runnode scripts/generate-public-pages.js, commit templates and outputs together. - README claims are CI-gated.
check-public-surface-integrity.jsgreps for the counts inlib/public-metadata.js("20 tools", "13 read-only", "4 write-path");check-public-language.shbans hype words, inskills/too. Run both before pushing copy changes. - Skills are prose about real tools, and a test holds them to it.
test/skills.test.jsfails when aSKILL.mdnames a tool that does not exist, when its workflow-kind key table differs fromstructuredKeysFor(), or when its template table differs fromtemplates/workflow-profiles/. Renaming a tool or a key means editing the skills in the same change. - Demo video is reproducible.
scripts/record-demo.jsre-captures the whole demo deterministically (webm master → renditions). Chapterdata-tvalues indemo-video.html.tpland.vttcue times are hand-mapped to real scene boundaries — re-verify both against extracted frames after any re-capture. - Never
gh pr merge --delete-brancha PR whose branch is the BASE of a stacked PR. GitHub closes the child PR unrecoverably (a closed PR whose base branch died cannot be retargeted or reopened). Recover withgit rebase --onto origin/main <old-base-tip-sha> <child-branch>(use the old base's tip COMMIT SHA — the deleted branch name may no longer resolve; find it via the local branch, reflog, or the merged PR's head SHA), force-push-with-lease, and open a replacement PR. Merge stacked chains bottom-up without--delete-branch, or let the child auto-retarget first. - Glama builds are not our Dockerfile. The glama.ai listing generates its own
image (debian + Node,
git clone+pnpm install) from settings in the claimed admin panel — repo.dockerignore/Dockerfile changes don't affect it. Build failures there are usually their builder's infra; re-run via admin → Dockerfile → Build & Release. workers/browser-ops/is NOT dead code — do not delete it. It looks abandoned from inside this repo: no workflow references it, nothing runswrangler deploy, and the only commits since it was added are Dependabot bumps. It is nevertheless deployed as theslack-browser-opsWorker and consumed cross-repo byrevereveal/portfolio→grant-brief, which binds it as a service (BROWSER_OPS_KEY, headerx-browser-key) and budgets "5–20 browser-ops calls" per agent run for portal status checks. Deleting it breaks the grant pipeline. Its@cloudflare/puppeteer→extract-zipalert (#51, CVE-2026-56876) was dismissed asnot_used, not fixed:extract-ziponly loads via puppeteer's Node launcher classes, whileindex.jscallspuppeteer.launch(env.BROWSER)through the Workers entry point to remote Browser Rendering, andworkerdcannot spawn processes or unzip anyway.workers/is absent from the npmfileswhitelist, so it never ships to package consumers. Re-open the alert if this ever runs under Node. (scripts/cloudflare-browser-tool.jsis a separate path — it calls Cloudflare's REST Browser Rendering API directly and is unaffected.)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

