codex mcp login fails for Slack official MCP with `Dynamic client registration not supported`

Open 💬 9 comments Opened Mar 2, 2026 by mkanetsuna

What version of Codex CLI is running?

codex-cli 0.105.0-alpha.8

What subscription do you have?

ChatGPT Enterprise

Which model were you using?

gpt-5.3-codex

What platform is your computer?

Darwin 24.2.0 arm64 arm

What terminal emulator and version are you using (if applicable)?

iTerm.app (zsh)

What issue are you seeing?

When configuring Slack MCP as the official remote endpoint (https://mcp.slack.com/mcp), codex mcp login slack fails immediately.

Config:

[mcp_servers.slack]
url = "https://mcp.slack.com/mcp"

Command:

codex mcp login slack

Output:

Error: Registration failed: Dynamic registration failed: Registration failed: Dynamic client registration not supported

What steps can reproduce the bug?

  1. Add this to config.toml:
[mcp_servers.slack]
url = "https://mcp.slack.com/mcp"
  1. Run:
codex mcp login slack
  1. Observe the error:

Dynamic client registration not supported

What is the expected behavior?

I expect Codex to let me authenticate against Slack’s official MCP server using Slack app credentials, without requiring Dynamic Client Registration.

Additional information

Slack official MCP docs state DCR is not supported and require pre-registered app identity.
https://docs.slack.dev/ai/slack-mcp-server/

View original on GitHub ↗

9 Comments

dannyparkk · 4 months ago

I can reproduce this on the current latest CLI as well, and there is one additional failure mode that may help narrow the bug.

Environment

  • Codex CLI: codex-cli 0.115.0
  • Subscription: ChatGPT Pro
  • Model in use: gpt-5.4
  • OS: macOS 15.6 (24G84)
  • Kernel: Darwin 24.6.0 arm64
  • Terminal: iTerm.app, zsh

Observed behavior

  1. codex mcp login slack still fails immediately with:
Error: Registration failed: Dynamic registration failed: Registration failed: Dynamic client registration not supported
  1. codex mcp add slack --url https://mcp.slack.com/mcp is also misleading / partially broken for the same reason. It first adds the server successfully, then auto-detects OAuth, then fails in the same DCR step:
Added global MCP server 'slack'.
Detected OAuth support. Starting OAuth flow…
Error: Registration failed: Dynamic registration failed: Registration failed: Dynamic client registration not supported
  1. After that failure, the server is actually present in config and listed by the CLI, but remains unusable because auth is still incomplete:
$ codex mcp get slack
slack
  enabled: true
  transport: streamable_http
  url: https://mcp.slack.com/mcp
  bearer_token_env_var: -
  http_headers: -
  env_http_headers: -
  remove: codex mcp remove slack
$ codex mcp list | rg '^slack\s'
slack       https://mcp.slack.com/mcp       -                     enabled  Not logged in

So there are really two user-visible problems here:

  • codex mcp login slack cannot authenticate against Slack's official MCP endpoint.
  • codex mcp add slack --url ... appears to succeed, but then falls into the same unsupported OAuth path and leaves the user in a partially-configured enabled / Not logged in state.

Reproduction steps on 0.115.0

  1. Ensure no prior Slack MCP auth/session state is active.
  2. Run:
codex mcp add slack --url https://mcp.slack.com/mcp
  1. Observe that the server is added, OAuth is auto-detected, and then login fails with Dynamic client registration not supported.
  2. Run:
codex mcp login slack
  1. Observe the same failure again.
  2. Optionally verify that the server was added but remains unauthenticated:
codex mcp get slack
codex mcp list

Expected behavior

  • Codex should be able to authenticate to Slack's official MCP endpoint without requiring Dynamic Client Registration when the server requires a pre-registered OAuth client.
  • If that flow is not yet supported, the CLI should fail with an explicit and actionable message, e.g. that this remote MCP server requires static/pre-registered OAuth client credentials and is not currently supported by Codex.
  • codex mcp add ... should also avoid leaving the user with a half-configured state after triggering a login flow that cannot succeed.

Why this looks like a Codex-side compatibility gap

  • The failing step happens before any successful browser login round-trip.
  • The error is specifically about Dynamic Client Registration, not a token exchange failure, expired token, workspace permission issue, or bad endpoint.
  • In the current CLI surface, I could not find a documented per-server way to provide a pre-registered OAuth client identity for a remote MCP server like Slack.

Potential fix directions

  • Add support for per-server static OAuth client configuration for remote MCP servers that do not support DCR.
  • Skip DCR when the server indicates that dynamic registration is unsupported and a static client configuration is present.
  • Improve the error message so users understand that the server was added but authentication is blocked by an unsupported OAuth registration mode.
SproutSeeds · 4 months ago

I dug through current origin/main plus the current rmcp OAuth flow, and this still looks like a real unsupported case rather than a config typo.

  • Slack's current MCP docs say https://mcp.slack.com/mcp does not support Dynamic Client Registration and instead requires a registered app with fixed client_id / client_secret
  • current origin/main exposes scopes, oauth_resource, and bearer_token_env_var for streamable HTTP MCP servers, but not client_id / client_secret in McpServerConfig
  • codex mcp login still always routes through the generic perform_oauth_login(...) path
  • under the current rmcp dependency, start_authorization(...) falls back to dynamic client registration unless the provider advertises URL-based client IDs; when no registration endpoint exists it returns Dynamic client registration not supported

So the narrow claim I can support is: Slack MCP currently hits a real Codex capability gap for providers that require pre-registered confidential OAuth clients.

I put up a small branch that only improves the CLI failure message so it explains the limitation directly instead of surfacing the raw DCR error:

I can support that narrow UX fix today.
I cannot yet support "Codex already has a way to pass Slack app credentials through codex mcp login," because I do not see a current config/API surface for that on origin/main.

mdthorpe-sc · 4 months ago

We did some follow up research into this and have confirmed that the codex client is not sending the newly minted client_id along to the /token endpoint, thus (in our case) the server refuses give a token because it's an "invalid or missing client_id"

We've validated that all other steps are working. (not to mention just about every other agent cli tool that supports rmcp)

Suggested fix: Send client_id to /token endpoints after dynamic client registration.

dziedrius · 3 months ago

Wondering if it would make sense to generalize this issue description from focused on Slack to generic support of pre-registered flow (to make it more visible and add some weight), or is it better to create separate issue?

MCP docs (https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#client-registration-approaches) say:

Clients supporting all options SHOULD follow the following priority order:
1. Use pre-registered client information for the server if the client has it available
2. Use Client ID Metadata Documents if the Authorization Server indicates if the server supports it (via client_id_metadata_document_supported in OAuth Authorization Server Metadata)
3. Use Dynamic Client Registration as a fallback if the Authorization Server supports it (via registration_endpoint in OAuth Authorization Server Metadata)
Prompt the user to enter the client information if no other option is available

Just in case mentioning claude does trigger anything, they support this just fine - you can pass client_id parameter when registering MCP server.

SproutSeeds · 3 months ago

I took a second pass on current origin/main, and this now looks narrower than
"Slack MCP needs something rmcp cannot do."

Exact results:

  • current rmcp 0.15.0 already has a configured-client path via

AuthorizationManager::configure_client(...)

  • the missing piece is Codex-side MCP config/login plumbing for

pre-registered OAuth clients

  • I put up a branch that adds oauth_client_id and

oauth_client_secret_env_var for streamable HTTP MCP servers and threads
them through:

  • codex mcp login
  • shared MCP dependency auth
  • app-server mcpServer/oauth/login
  • plugin MCP silent OAuth bootstrap
  • branch:

https://github.com/SproutSeeds/codex/tree/scratch/issue-13200-pre-registered-oauth

  • commit: 987ef9cc
  • local verification:
  • cargo check -p codex-core -p codex-cli -p codex-rmcp-client -p codex-app-server
  • cargo test -p codex-rmcp-client perform_oauth_login
  • cargo test -p codex-core --lib config::types::tests
  • cargo test -p codex-core --lib config::edit::tests
  • cargo test -p codex-core --lib mcp::skill_dependencies::tests
  • cargo test -p codex-core --lib config::schema::tests::config_schema_matches_fixture
  • cargo test -p codex-core streamable_http_with_oauth_round_trip

So the tighter conclusion I can support now is:

  • #13200 is a real Codex capability gap for providers that require a

pre-registered confidential OAuth client

  • the gap is not that rmcp lacks a configured-client mechanism
  • it is that Codex currently exposes no MCP config/login surface for that

mechanism on origin/main

One caveat: the nearest app-server integration test I tried
(suite::v2::plugin_install::plugin_install_returns_apps_needing_auth) timed
out twice during harness initialization before it reached the OAuth path, so I
would not overclaim app-server positive-path coverage from that test yet.

If this direction looks reasonable, the branch is ready for a closer review.

madeyexz · 2 months ago

Hit this same wall today. While we wait for upstream support for pre-registered OAuth clients, there's a working bearer-token workaround that gets Codex talking to mcp.slack.com:

TL;DR: Register your own Slack app, run the OAuth code-exchange manually to mint a user token (xoxp-…), then configure Codex with --bearer-token-env-var SLACK_MCP_TOKEN instead of codex mcp login. Bypasses the DCR step entirely. Slack's hosted MCP server accepts the user token as a bearer once the app has MCP server access enabled.

Full step-by-step (including the non-obvious "enable MCP server access on the app" toggle and a cleaned app manifest): https://ianhsiao.me/blog/enabling-slack-mcp-in-codex-and-claude-code-workaround

pavinduLakshan · 2 months ago
Hit this same wall today. While we wait for upstream support for pre-registered OAuth clients, there's a working bearer-token workaround that gets Codex talking to mcp.slack.com: TL;DR: Register your own Slack app, run the OAuth code-exchange manually to mint a user token (xoxp-…), then configure Codex with --bearer-token-env-var SLACK_MCP_TOKEN instead of codex mcp login. Bypasses the DCR step entirely. Slack's hosted MCP server accepts the user token as a bearer once the app has MCP server access enabled. Full step-by-step (including the non-obvious "enable MCP server access on the app" toggle and a cleaned app manifest): ianhsiao.me/blog/enabling-slack-mcp-in-codex-and-claude-code-workaround

This works, but the problem with this approach is that you have to renew the token time to time, plus its generally not a best practice to hardocde tokens in plain text in a config file.

komod0 · 22 days ago

This was solved in my case after #22575 was merged and shipped in 0.142.0.
That PR lets you set a pre-registered OAuth client_id for an MCP server. When it's set, Codex skips Dynamic Client Registration and uses that client for the PKCE flow, which is what Slack requires. With no client_id it still falls back to DCR, hence the error here. So first make sure you're on ≥ 0.142.0.
Slack also requires the redirect_uri to match one registered on the Slack app, so the default random loopback port won't work. You need two things.
First, the callback overrides. These are top-level keys, so put them at the very top of the config:

mcp_oauth_callback_port = <port registered on your app>
mcp_oauth_callback_url = "http://localhost:<port>/callback"

Then the server itself, with the pre-registered client_id:

[mcp_servers.slack]
url = "https://mcp.slack.com/mcp"

[mcp_servers.slack.oauth]
client_id = "<your-slack-app-client-id>"

The redirect has to match what's registered on your Slack app, then run codex mcp login slack.

@mzeng-openai (sorry for the ping) One thing I noticed: oauth.client_id isn't in the public docs, even though oauth_resource, scopes, and both callback keys are. Might be worth adding since it's what makes Slack's MCP work.

sshishigin · 21 days ago

I hit a related but narrower MCP OAuth compatibility issue with strict registered redirect URIs and opened #30460.

In short, even when mcp_oauth_callback_url is configured, Codex currently appends a server-derived callback id to it before sending it as redirect_uri. That means a provider/app registered for http://localhost:<port>/callback sees http://localhost:<port>/callback/<callback_id> instead.

This is separate from pre-registered client support/DCR, but it affects the same class of hosted MCPs once a static oauth.client_id is available. I put a small reference branch on #30460 that keeps the current callback-id behavior for generated local redirects, but uses explicit mcp_oauth_callback_url values verbatim.