Skip to content

Enable sending DM to user I have not chatted before#253

Open
jhutar wants to merge 7 commits intokorotovsky:masterfrom
jhutar:master
Open

Enable sending DM to user I have not chatted before#253
jhutar wants to merge 7 commits intokorotovsky:masterfrom
jhutar:master

Conversation

@jhutar
Copy link
Copy Markdown

@jhutar jhutar commented Mar 25, 2026

For my use-case, I created this fork with 2 applied PRs and one new commit by Gemini.

This PR includes rebased changes from PRs #225 and #249 to improve cache warm-up if server is configured with stdio transport. Then because I needed to be able to send DM to user I have not chatted before (as discussed in issue #221), added implementation of conversations_open tool.

Mine config:

SLACK_MCP_XOXC_TOKEN=xoxc-
SLACK_MCP_XOXD_TOKEN=xoxd-
# Quirks needed for login to enterprise Slack account to work
# Without this, all my Slack sessions got logged-out and got email "Subject: [Security Notice] You've been signed out of Slack"
SLACK_MCP_USER_AGENT=Mozilla/5.0 ...
SLACK_MCP_CUSTOM_TLS=1
SLACK_MCP_ADD_MESSAGE_TOOL=true
SLACK_MCP_ADD_MESSAGE_MARK=false
SLACK_MCP_ADD_MESSAGE_UNFURLING=
SLACK_MCP_USERS_CACHE=/cache/.users_cache.json
SLACK_MCP_CHANNELS_CACHE=/cache/.channels_cache_v2.json
SLACK_MCP_LOG_LEVEL=debug

And Gemini CLI is configured with:

{
  "mcpServers": {
    "slack-mcp": {
      "command": "podman",
      "args": [
        "run",
        "--rm",
        "-i",
        "--env-file",
        "/home/jhutar/.config/korotovsky_slack-mcp-server/.env",
        "-v",
        "/home/jhutar/.config/korotovsky_slack-mcp-server/cache/:/cache:z",
        "ghcr.io/korotovsky/slack-mcp-server:latest",
        "--transport",
        "stdio"
      ]
    },
[...]

With all the fixes, when I rebuild the container with podman build -f Dockerfile . -t ghcr.io/korotovsky/slack-mcp-server:latest I was able to send a DM to a user I nave not talked to before.

flacoste and others added 7 commits March 5, 2026 21:53
On large workspaces (41K+ users), the server blocks for ~90 seconds
during startup while fetching all users/channels from the Slack API,
exceeding MCP client connection timeouts.

Changes:
- Load expired cache files immediately, mark server ready, then refresh
  in background via goroutine (stale-while-revalidate pattern)
- Convert usersReady/channelsReady to atomic.Bool for race-free reads
- Add refreshingUsers/refreshingChannels atomic.Bool to coalesce
  concurrent background refreshes via CompareAndSwap
- Remove stdio IsReady() polling loop (no longer needed)
- Increase default cache TTL from 1h to 24h
- Document SLACK_MCP_CACHE_TTL and SLACK_MCP_MIN_REFRESH_INTERVAL
  env vars in docs/03-configuration-and-usage.md

Fixes startup timeout on large workspaces. Server now starts in under
1 second regardless of workspace size when a cache file exists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Restore IsReady() polling loop before ServeStdio() to fix cold-start
  regression where tool calls fail for 60-90s on first run (no cache)
- Add fetchUsersMu/fetchChannelsMu mutexes to serialize fetchAndStore*
  calls, preventing race between ForceRefresh and background refresh
- Use atomic file writes (temp + os.Rename) to prevent corrupt cache
  files on crash
- Guard against empty API results overwriting valid cache
- Guard against empty cache files being treated as valid data
- Fix typo: TestRefreshingFlagPreventsConucrrentRefreshes → Concurrent

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix infinite loop on cold start when API returns zero results: return
  error instead of nil when no existing cache is available, so the
  watcher calls Fatal rather than spinning IsReady() forever
- Secure temp file handling: use os.CreateTemp for unpredictable names
  (prevents symlink attacks) and clean up temp files on any failure
- Restrict cache file permissions from 0644 to 0600 and cache directory
  from 0755 to 0700 (cache contains user PII)
- Extract atomicWriteFile helper to deduplicate temp+rename pattern
- Fix stale docstring: getCacheTTL default is 24h not 1h

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The stdio transport blocks on IsReady() which requires both the users
and channels caches to be fully populated before serving. On large
workspaces (200k+ members like Kubernetes Slack), the user cache takes
several seconds to load, causing MCP clients with tight startup timeouts
to fail the connection.

This brings stdio in line with the SSE and HTTP transports, which already
serve immediately while caches warm in the background. Tools that depend
on the user cache gracefully degrade (showing user IDs instead of display
names) until the cache is ready.

Signed-off-by: Mark Liu <mark@prove.com.au>
# Conflicts:
#	pkg/provider/api.go
# Conflicts:
#	cmd/slack-mcp-server/main.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants