Skip to content

Integrate Slack MCP with MoP#24

Merged
yosrixp merged 1 commit intomainfrom
slack
Apr 14, 2026
Merged

Integrate Slack MCP with MoP#24
yosrixp merged 1 commit intomainfrom
slack

Conversation

@yosrixp
Copy link
Copy Markdown
Collaborator

@yosrixp yosrixp commented Apr 14, 2026

Summary

This work integrates the Slack MCP surface with the MCP OAuth Proxy (MoP) using Slack's OAuth v2 authorization code flow with PKCE. The user authenticates directly with Slack's consent screen — scoped to a specific Yahoo workspace (team parameter) — and MoP stores the resulting access and refresh tokens as-is (pass-through). Token refresh against Slack's /api/oauth.v2.user.access endpoint is handled by a dedicated TokenExchangeServiceSlackImpl using the Nimbus OAuth 2.0 SDK. Resource mapping and as: slack follow the same patterns as other OAuth consent providers (e.g. GitHub, Google Workspace).

Architecture (high level)

flowchart LR
  subgraph Client_side
    MCP_Client[MCP client]
  end
  subgraph MoP
    Token_EP[MoP token endpoint]
    Authz[AuthorizerService]
    SlackRes[SlackResource /slack/authorize]
    SlackEx[TokenExchangeServiceSlackImpl]
  end
  subgraph Slack
    Consent[Slack OAuth v2 consent screen]
    TokenEP[Slack token endpoint /api/oauth.v2.user.access]
    AuthTest[Slack auth.test UserInfo]
    MCP_Srv[Slack MCP server]
  end

  MCP_Client -->|OAuth / token grant + resource URI| Token_EP
  Token_EP --> Authz
  Authz -->|No stored token for slack| SlackRes
  SlackRes -->|Redirect with user_scope + team + PKCE| Consent
  Consent -->|Authorization code callback| SlackRes
  SlackRes -->|Exchange code for tokens| TokenEP
  TokenEP -->|access_token + refresh_token| SlackRes
  SlackRes -->|Verify user identity| AuthTest
  SlackRes -->|Store tokens| Authz
  Authz -->|Pass-through: return stored token| MCP_Client
  MCP_Client -->|Slack access_token| MCP_Srv
  Authz -.->|Token expired| SlackEx
  SlackEx -->|Refresh grant + client credentials| TokenEP
  TokenEP -.->|New access_token + refresh_token| SlackEx
Loading

Key design decisions:

  • Pass-through pattern — MoP does not transform the Slack token. The provider's access_token is returned directly to the MCP client.
  • PKCE — Quarkus OIDC handles code_challenge / code_verifier automatically; no S256 plumbing in application code.
  • user_scope instead of scope — Slack's OAuth v2 uses a non-standard user_scope parameter for user-level permissions, passed as an extra-param in the OIDC tenant config.
  • Workspace targeting — The team extra-param restricts the consent screen to the configured Yahoo Slack workspace (OurOathTest for dev/staging, ouryahoo for production).
  • Refresh with NimbusTokenExchangeServiceSlackImpl.refreshWithUpstreamToken() builds a RefreshTokenGrant against Slack's token endpoint using ClientSecretBasic authentication.
  • UserInfo via auth.test — Slack has no standard OIDC UserInfo endpoint. The OIDC tenant is configured with user-info-path: https://slack.com/api/auth.test and id-token-required: false so Quarkus validates the user via Slack's bearer-authenticated API instead.

OAuth consent and token storage flow

sequenceDiagram
    participant Client
    participant MoP
    participant Slack as Slack OAuth v2

    Client->>MoP: Request token for Slack resource
    MoP->>MoP: No stored Slack token for user
    MoP->>Slack: Redirect to consent screen (user_scope + team + PKCE)
    Slack-->>MoP: Authorization code callback
    MoP->>Slack: Exchange code for tokens (/api/oauth.v2.user.access)
    Slack-->>MoP: access_token + refresh_token (12h TTL)
    MoP->>Slack: Verify user via /api/auth.test
    Slack-->>MoP: user_id, team, enterprise
    MoP->>MoP: Store tokens keyed by user_id
    MoP-->>Client: Return stored Slack access_token
Loading

Token refresh flow

sequenceDiagram
    participant MoP
    participant SlackEx as TokenExchangeServiceSlackImpl
    participant Slack as Slack /api/oauth.v2.user.access

    MoP->>SlackEx: Upstream refresh token expired access_token
    SlackEx->>Slack: POST refresh_token grant + client credentials
    Slack-->>SlackEx: New access_token + refresh_token
    SlackEx->>MoP: Updated TokenWrapper
    MoP->>MoP: Store refreshed tokens
Loading

Slack user scopes

Scope Purpose
users:read.email Read user email addresses
users:read Read user profile information
search:read.users Search for users
search:read.public Search public channels
search:read.private Search private channels
groups:history Read private channel message history
channels:history Read public channel message history
canvases:read Read canvases

Signed-off-by: yosrixp <yosrixp@yahoo.com>
@yosrixp yosrixp merged commit 0ad06f2 into main Apr 14, 2026
2 checks passed
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.

2 participants