Custom MCP connector fails with 'did not return a client_secret' for RFC 7591-compliant public-client registrations

Bug: Adding a custom MCP connector that registers as a public OAuth client (per RFC 7591 / OAuth 2.1) fails with the error [API_CLIENTS_ERROR] Dynamic client registration did not return a client_secret.

Repro:

  1. Perplexity Pro account
  2. Settings → Connectors → Add custom MCP connector
  3. Server URL: https://app.onepagecrm.com/mcp (any OAuth 2.1 + DCR compliant server)
  4. Perplexity sends DCR registration with token_endpoint_auth_method: "none" (requesting public-client status)
  5. Server creates the OauthClient successfully and returns an RFC 7591 §3.2.1 compliant response — no client_secret field, because public clients are not issued secrets
  6. Perplexity’s consumer then errors with the message above

Expected: Either

  • (a) Perplexity registers as confidential (token_endpoint_auth_method: "client_secret_basic") so it actually gets a secret back, OR
  • (b) Perplexity handles the missing client_secret field correctly for public clients (PKCE-only)

Standards reference:

  • RFC 7591 §3.2.1 — client_secret is OPTIONAL in the registration response, not required for public clients
  • OAuth 2.1 §3.2.1 / draft-ietf-oauth-v2-1 — public clients don’t authenticate at the token endpoint and don’t have a secret

Impact: Blocks all MCP servers that correctly implement RFC 7591 (Anthropic-style DCR servers) from being used with Perplexity custom connectors. The OnePageCRM MCP server works with Claude.ai, Claude Code, ChatGPT, and Codex without issue.

Server-side observation: Perplexity’s registration request specifies token_endpoint_auth_method: "none" — so Perplexity is registering itself as a public client, then immediately requiring confidential-client semantics. Internally contradictory.

+1, ran into the same issue yesterday. Notably, this wasn’t even Perplexity’s behavior like a week ago.

Currently, there is not even a workaround for this issue, as statically creating client/secret pair requires, at least in Supabase, to provide a valid callback URL, which Perplexity doesn’t specify anywhere. The only docs page is woefully outdated as it doesn’t even mention custom connectors for MCP at all.
https://www.perplexity.ai/help-center/en/articles/11502712-local-and-remote-mcps-for-perplexity

@Kevin_Farrell can you retry and see if it works for you? somehow it started working for me again.

I have the exact same issue with Gmail.

I’m seeing what appears to be the same issue with a custom remote MCP server.

My server supports Streamable HTTP at:

https://tmc-brain-mcp-production.up.railway.app/mcp

Controls that work against the same MCP server:

Claude.ai: works
ChatGPT: works
Grok/xAI: works
MCP Inspector with Authorization: Bearer <server key>: works

Perplexity OAuth behavior:

Perplexity calls /oauth/register
Server returns HTTP 201 registration success
client_id = perplexity
token_endpoint_auth_method = none
no client_secret, because this is a public client

Then Perplexity stops. It never calls:

/oauth/authorize
/oauth/token

I also tried:

- returning client_secret_expires_at: 0
- omitting client_secret_expires_at
- configuring a static client_id/client_secret in Perplexity
- API Key mode

The public-client DCR path still stops after registration. API Key mode did not appear to hit my Railway MCP server at all, while MCP Inspector succeeds with the same server key.

This looks consistent with the issue described here: Perplexity appears to register with token_endpoint_auth_method=none, but then behaves as if client_secret is required.

Can Perplexity confirm the expected behavior for custom remote MCP connectors?

Specifically:

  1. Are RFC 7591 public-client registrations with token_endpoint_auth_method=none supported?

  2. If not, should the connector UI require a static confidential client instead of attempting public DCR?

  3. If a static client_id and client_secret are entered manually, should Perplexity skip DCR and proceed directly to /oauth/authorize?

  4. Is there any connector-side log/debug output available to see why the flow stops after DCR?

Happy to provide sanitized registration logs and response payloads if helpful.