Fix connecting to Slack's MCP server
What does this MR do and why?
Fixes connecting AI Catalog agents to Slack's MCP server (https://mcp.slack.com/mcp). Both fixes are generic and help other MCP servers that behave the same way:
- Find resource metadata published at the root. GitLab only looked for protected resource metadata at the path-specific URL (
/.well-known/oauth-protected-resource/mcp). Slack only publishes it at the root, so GitLab requested no scopes and Slack rejected the request with "No scopes requested". GitLab now also tries the root URL, as the MCP authorization spec requires. It requests every scope the server lists, as it does for other servers. - Send client credentials in the request body when required.
OAuth2::Clientsends the client ID and secret as a basic auth header. Slack's token endpoint only accepts them in the request body (client_secret_post), so the token exchange and refresh failed. GitLab now uses the request body when the server listsclient_secret_postand notclient_secret_basic. Otherwise basic auth stays the default.
References
- #627432
- Split out of !259676 (merged)
Screenshots
| Before | After |
|---|---|
![]() |
![]() |
How to set up and validate locally
-
In Slack, go to Your Apps, select Create New App > From a manifest, choose your workspace, and paste this manifest. Replace
http://gdk.test:8080with your GDK URL:{ "display_information": { "name": "GitLab MCP test" }, "oauth_config": { "redirect_urls": [ "http://gdk.test:8080" ], "scopes": { "user": [ "canvases:read", "canvases:write", "channels:history", "channels:read", "channels:write", "chat:write", "emoji:read", "files:read", "files:write", "groups:history", "groups:read", "groups:write", "im:history", "im:read", "im:write", "lists:read", "lists:write", "mpim:history", "mpim:read", "mpim:write", "reactions:read", "reactions:write", "search:read.files", "search:read.im", "search:read.mpim", "search:read.private", "search:read.public", "search:read.users", "users:read", "users:read.email" ] } }, "settings": { "is_mcp_enabled": true, "org_deploy_enabled": false, "socket_mode_enabled": false, "token_rotation_enabled": false } } -
Go to Basic Information and copy the Client ID and Client Secret.
-
In a Rails console, enable the feature flags and turn on experiment and beta features:
Feature.enable(:ai_catalog_mcp_servers) Feature.enable(:mcp_client) ApplicationSetting.current.update!(instance_level_ai_beta_features_enabled: true) -
In a top-level group, go to Settings > GitLab Duo and turn on Allow external MCP tools.
-
Go to Explore > AI Catalog > MCP, select New MCP server, and enter:
- Server URL:
https://mcp.slack.com/mcp - Authentication method: OAuth
- OAuth Client ID and OAuth Client Secret: from step 3
- Server URL:
-
Go to Explore > AI Catalog > Agents, select New agent, and create an agent. Under MCP servers, select the Slack server.
-
Enable the agent in your group.
-
In the group, go to Automate > MCP servers, select Connect for the Slack server, and select Allow in Slack. You should return to GitLab with "Successfully connected to MCP server". On
master, Slack shows "No scopes requested" instead. -
Open GitLab Duo Chat in a project in the group, select your agent, and ask it to summarize the latest messages in a public channel. Approve the Slack tool call. The answer should include messages from that channel.

