Spike: Slack MCP Server Feasibility & Auth Model

Date: 2026-04-02 Author: Pranav Narahari Ticket: EDE3-6 Status: Go — all tests passed, MCP fully operational


1. Summary

Verdict: Go.

The Slack MCP server is fully operational. All blocking steps have been completed: App Assistant enabled, granular scopes added, MCP connection confirmed live. initialize handshake succeeds, 13 tools discovered, search and read channel tested end-to-end with real Eden data. Ticket 9b can proceed.


2. Auth Model

Confirmed: user token (xoxp) required. Bot token (xoxb) is rejected.

TokenMCP initialize resultNotes
xoxp (user token){"code": -32600, "message": "App is not enabled..."}Correct token type — blocked only by App Assistant config
xoxb (bot token){"code": -32001, "message": "invalid_token_type"}Permanently rejected for MCP

This confirms the architecture decision from EDE3-2: the xoxp token is the right token for MCP. The bot token (xoxb) cannot be used for MCP under any configuration.

Current scope gap

The xoxp token currently has: identify, search:read

MCP requires these granular user scopes (per Slack MCP docs):

MCP capabilityRequired scope
Search messages (public channels)search:read.public
Search messages (private channels)search:read.private
Search messages (group DMs)search:read.mpim
Search messages (DMs)search:read.im
Search filessearch:read.files
Read channel/thread historychannels:history, groups:history, mpim:history, im:history
User profilesusers:read, users:read.email

Action required: Add the search:read.* granular scopes to User Token Scopes in the Slack app, then reinstall to regenerate the xoxp token. The read history scopes are bot scopes already set up in EDE3-2.


3. MCP Setup Steps (Completed)

Both steps were required and have been completed:

  1. Enable App Assistant (https://api.slack.com/apps/A0AQCJN54LB/app-assistant): Toggle “Model Context Protocol” to ON. The “Agent or Assistant” toggle does NOT need to be enabled.
  2. Add granular user scopes (User Token Scopes in OAuth & Permissions) and reinstall:
    • search:read.public, search:read.private, search:read.mpim, search:read.im, search:read.files, search:read.users
    • channels:history, groups:history, im:history, mpim:history
    • users:read, users:read.email, canvases:read, chat:write, canvases:write

Confirmed working initialize response:

{
  "result": {
    "serverInfo": {"name": "Slack MCP", "version": "1.0.0"},
    "protocolVersion": "2025-06-18",
    "capabilities": {"tools": {"listChanged": true}, "resources": {"listChanged": true}}
  }
}

4. Available Tools (Confirmed via tools/list)

13 tools returned. These are the actual tool names from the live Eden MCP connection:

ToolCapability
slack_search_publicKeyword search across public channels only
slack_search_public_and_privateKeyword search across all channels, DMs, group DMs
slack_search_channelsFind channels by name/description
slack_search_usersFind users by name, email, profile attributes
slack_read_channelRead channel messages (newest first, paginated via cursor)
slack_read_threadRead a specific thread and all replies
slack_read_canvasRetrieve canvas content and section ID map
slack_read_user_profileGet detailed user profile (contact, status, timezone)
slack_send_messagePost a message to a channel or DM
slack_send_message_draftCreate a draft (not sent) in a channel
slack_schedule_messageSchedule a message for future delivery
slack_create_canvasCreate a new Canvas document
slack_update_canvasUpdate an existing Canvas (append/prepend/replace)

Key observation: The tool set exactly mirrors the Brainforge Slack MCP tools the platform already has. This strongly suggests the MCP server is the same Slack-provided service — the integration path for EDE3-9b will be straightforward using existing Mastra MCP tool patterns.


5. Response Format & PII Surface

Confirmed via live MCP calls.

MCP responses are structured JSON strings containing both display names AND user IDs. Example from slack_search_public_and_private:

Channel: #eden-technologies-operations (ID: C0AMCTGHYLA)
From: Daniel Dietz (ID: U05TX3GBC1F)
Time: 2026-03-26 19:37:40 EDT
Message_ts: 1774568260.261399
Text: Ya that's clear with a couple other priorities...

Observed RTS API behavior (live test for comparison): RTS API also returns hydrated display names in results:

{
  "text": "Ya that's clear with a couple other priorities...",
  "username": "daniel",
  "channel": "eden-technologies-operations"
}

PII implication for EDE3-8 (updated): MCP responses include both display names AND user IDs in structured fields. This is actually better than pure markdown — the From: Daniel Dietz (ID: U05TX3GBC1F) pattern is regex-parseable. EDE3-8 should redact:

  • Structured From: fields (display name + ID)
  • Inline <@USERID|displayname> mentions in message text (also present in read_channel responses)
  • Names appearing in free-form message text (NER still needed for this case)
  • The context before/after snippets also contain names and must be scanned

6. Rate Limits

RTS API burst test (8 rapid calls, ~3 seconds total): All 8 returned ok: true. No throttling observed. This is consistent with Slack’s Tier 2/3 limits being generous (20–100+ req/min for non-Marketplace apps).

MCP rate limits (from docs, not directly observed):

  • Read channel/thread: Tier 3 (50+/min) — adequate for the agent’s use case
  • Search: Special limits (same as search.messages Web API) — historically generous for internal apps
  • Send message: chat.postMessage limits apply (Tier 3 for most workspaces)

Assessment: Rate limits are not a practical blocker for this use case. The agent will not be calling Slack at high frequency.


7. Bot Channel Memberships

Observed: The bot (xoxb token) is not a member of any channels. conversations.history returns not_in_channel for all tested channels.

Implication: For the read_channel MCP tool to work, the bot must be invited to every channel it needs to read. For the Command Center use case (broad workspace context), this means:

  • Option A: Invite the bot to all relevant channels (manual, channel-by-channel)
  • Option B: Use the xoxp user token for channel history reads instead — the user token sees all channels the authorizing user is in

The MCP server uses xoxp for all operations (confirmed above), so Option B is the path — the user token’s access level determines channel visibility.


RTS API test with natural language query: "what are our priorities this quarter" returned 2,536 results with keyword-matched content (individual words matched, not semantic meaning):

"sheryl" → general: "New quarters are all about growth and advancement..."
"caitlin" → product-launch-microdose: "So that's a quarterly plan for 696..."
"daniel" → eden-technologies-operations: "Ya that's clear with a couple other priorities..."

These are keyword matches, not semantic results. This indicates either:

  1. Eden is on Slack Pro (semantic search unavailable), or
  2. The RTS API never does semantic search (semantic is MCP-only via assistant.search.context)

Cannot confirm plan tier: The team.info call requires team:read scope (not currently on either token). Add team:read as a bot scope to confirm Eden’s plan.

Recommendation: Flag to CSO that semantic search availability is unconfirmed. If Eden is on Pro, MCP search will also be keyword-only. If Business+, MCP may offer semantic ranking. Either way, keyword search with 2,536+ results demonstrates sufficient data coverage.


9. Go/No-Go Recommendation

Verdict: Go — proceed with MCP path (Ticket 9b is unblocked).

Rationale

FactorFindingVerdict
Auth modelxoxp confirmed, workingGo
MCP connectivityLive — initialize succeeds, 13 tools availableGo
ToolsAll key tools present: search, read, send, canvasGo
Rate limitsGenerous, not a constraintGo
Response formatStructured JSON with both display names + IDs — parseableGo
Scope coverageAll required scopes added and confirmedGo
Semantic searchUnconfirmed, does not block initial integrationGo
Bot channel accessxoxp user token covers all user-visible channelsGo

What Ticket 9b needs from this spike

  1. xoxp token — store in Secret Manager / 1Password; rotate before production
  2. MCP endpoint: https://mcp.slack.com/mcp (JSON-RPC 2.0, POST, Authorization: Bearer <xoxp>)
  3. Key tools for the agent: slack_search_public_and_private, slack_read_channel, slack_read_thread, slack_read_user_profile
  4. Pagination: Both search and read_channel return cursors — agent must handle multi-page results

Constraints for downstream tickets

  • EDE3-8 (PII redaction): Must handle markdown text with inline display names, not just JSON user IDs. Named entity recognition or display-name lookup against the identity mapping table will be needed.
  • EDE3-9b (Mastra integration): MCP transport is JSON-RPC 2.0 over HTTP to https://mcp.slack.com/mcp, xoxp token in Authorization header. No SSE support.

10. Fallback Plan (if App Assistant is plan-gated and unavailable)

If enabling App Assistant requires Eden to upgrade their Slack plan and they decline, fall back to custom Slack tools using the Web API directly:

CapabilityWeb API methodToken
Search messagessearch.messages (RTS)xoxp
Channel historyconversations.historyxoxb (after bot invite)
User lookupusers.infoxoxb
Thread readconversations.repliesxoxb

Effort estimate: ~14 pts (per ticket notes). This path is already partially validated — both tokens work, RTS search is confirmed functional with 1,187+ results, and channel history works once the bot is invited.