# Slack

Sign in to [Slack's app settings](https://api.slack.com/apps) with permission
to create an internal app in the workspace you want to connect, or to manage
an existing one. Obtain any required workspace-admin approval before connecting.

For a new app, use the [JSON manifest](#create-app-from-manifest) below. For an
existing internal app, skip to [Enable MCP access](#enable-mcp-access) and
follow the manual steps.
Slack permits internal apps and apps published in the Slack Marketplace;
unlisted distributed apps cannot use its MCP server. This guide uses an
internal app, not a bot token or a personal API key. Each connecting user
authorizes access with their own Slack account.

If your app restricts allowed IP addresses, ask your network administrator to
include the Control Plane's outbound addresses before connecting. Do not
remove the restriction to work around a failed connection.

### Create an app from JSON
Use this option for a new internal app. The manifest enables MCP access and
sets the same user permissions and callback as the manual steps below.

1. Start creating an app in [Slack's app settings](https://api.slack.com/apps).
2. Select **From a manifest**.
3. Click **Continue**.
4. Replace the JSON manifest with the following:

```json
{
  "display_information": {
    "name": "Slack MCP Control Plane"
  },
  "oauth_config": {
    "redirect_urls": [
      "https://app.getgram.ai/mcp/remote_login_callback"
    ],
    "scopes": {
      "user": [
        "channels:read",
        "groups:read",
        "im:read",
        "mpim:read"
      ]
    }
  },
  "settings": {
    "is_mcp_enabled": true
  }
}
```

5. Select the workspace where the app will live.
6. Click **Next**.
7. Click **Create**.

These permissions allow listing the user's channels, not message search,
message history, or sending messages. Keep the app internal; creating it does
not bypass workspace approval or authorize access for other users.

Continue to [Copy the app credentials](#copy-client-credentials). You do not
need to repeat the next three manual configuration steps.

<!-- screenshot: Slack's manifest editor with the JSON configuration before app creation -->

### Enable MCP access
1. Open your internal app in [Slack's app settings](https://api.slack.com/apps).
2. Select **Agents** in the sidebar.
3. Toggle **Slack Model Context Protocol (MCP) Server** to **On**.

<!-- screenshot: the Agents section with Slack Model Context Protocol (MCP) Server enabled -->

### Set user permissions
1. Select **OAuth & Permissions** in the sidebar.
2. Scroll to **Scopes**.
3. Add `channels:read`, `groups:read`, `im:read`, and `mpim:read` to the
   user-token scopes, not the bot-token scopes.

These permissions let the server list the user's channels. They do not enable
message search, message history, or sending messages. If you need those tools,
ask your app owner to select their user-token scopes from
[Slack's tool-to-scope table](https://docs.slack.dev/ai/slack-mcp-server/#oauth-scopes-needed-on-user-token-for-different-tools).
Use the same selected scopes when configuring the Control Plane.

<!-- screenshot: OAuth & Permissions showing the selected user-token scopes -->

### Register the callback
1. On **OAuth & Permissions**, scroll to **Redirect URLs**.
2. Add `https://app.getgram.ai/mcp/remote_login_callback` as a redirect URL.
3. Save the redirect URL.

<!-- screenshot: Redirect URLs with the Control Plane callback registered -->

### Copy the app credentials
1. Open **Basic Information** in the app settings.
2. Copy the app's **Client ID** to your password manager.
3. Reveal and copy its **Client Secret** to your password manager.

Keep this app's identity fixed for the integration. Do not substitute its App ID,
a bot token, or a user access token for these credentials. Continue to
[Speakeasy setup](#add-server-in-speakeasy).

<!-- screenshot: Basic Information showing Client ID and Client Secret labels with all credential values redacted -->

### Add the server in Speakeasy
1. In the Speakeasy AI Control Plane sidebar, under **Connect**, select **Sources**.
2. Click **Add Source**.
3. Choose **Custom remote server**.
4. On **Add a custom remote MCP server**, paste `https://mcp.slack.com/mcp`
   into **Remote MCP server URL**.
5. Click **Add server**.

This creates the hosted MCP server and opens its **Overview** page.

<!-- screenshot: Add a custom remote MCP server with Slack's endpoint entered -->

### Connect your credentials
1. From **Overview**, open **Settings**.
2. Under **Authentication**, click **Configure Manually**, or **Use Discovered**
   when offered.
3. If the issuer is not already known, enter `https://mcp.slack.com` as the
   **Issuer URL**. Under **Endpoints**, click **Discover**.
4. In **Attach Remote Identity Provider**, set **Client Type** to **Manual**.
5. Paste the [Slack Client ID](#copy-client-credentials) into **Client ID**.
6. Paste the [Slack Client Secret](#copy-client-credentials) into
   **Client Secret (optional)**. Slack requires this secret.
7. Set the token-endpoint authentication method to `client_secret_post` using
   the authentication-method control. Do not use `client_secret_basic`.
8. Configure the scopes to match your [Slack user permissions](#set-user-permissions):
   `channels:read`, `groups:read`, `im:read`, and `mpim:read` for listing channels.
   If an issuer-level scope override is configured, make it match this selection.
9. Click **Attach Identity Provider**.
10. Confirm that the sheet's **Redirect URI** matches
    `https://app.getgram.ai/mcp/remote_login_callback`, registered under Slack's
    [Redirect URLs](#register-callback).

Slack's discovered authorization endpoint is
`https://slack.com/oauth/v2_user/authorize` and its token endpoint is
`https://slack.com/api/oauth.v2.user.access`. Use these user-token endpoints,
not the bot-token OAuth endpoints. Slack does not support Dynamic Client
Registration. Each user must complete Slack consent when connecting; attaching
the client credentials does not grant access to everyone's Slack data.

If your deployment does not expose the authentication-method or scope controls,
ask the Control Plane administrator to configure these values before connecting.
This configuration is based on Slack's documentation and the Control Plane's
OAuth implementation; it has not been tested end to end with a Slack workspace.

<!-- verify(operator): the template key substitutes this same Redirect URI value -->
<!-- screenshot: Attach Remote Identity Provider with Manual selected, user-token endpoints and client_secret_post configured, and credentials redacted -->

This guide covers setup only. For anything beyond it — billing, tool behavior, limits — see [Slack's MCP documentation](https://docs.slack.dev/ai/slack-mcp-server/).
