[BUG] Plugin-bundled MCP servers with OAuth cannot be authenticated by any surface (/mcp, claude mcp login, desktop Connectors)

Open 💬 1 comment Opened Jul 9, 2026 by poojit-incoder

Environment

  • Claude Code 2.1.205, macOS (darwin), also reproduced against the desktop app
  • Plugin distributed via an org GitHub marketplace; servers declared in the plugin's .mcp.json

Server declaration (plugin .mcp.json)

{
  "mcpServers": {
    "incode-context": {
      "type": "http",
      "url": "https://<internal-host>/mcp/context",
      "oauth": { "clientId": "<public-okta-client-id>", "callbackPort": 51789 }
    }
  }
}

The endpoint is an OAuth 2.1 resource server (RFC 9728 metadata, 401 + WWW-Authenticate: Bearer resource_metadata=… challenge). The identical config registered manually via claude mcp add --transport http --client-id … --callback-port … authenticates flawlessly (browser opens, loopback callback, token cached, server connects).

What happens with the plugin-bundled declaration

The servers load into sessions: they appear namespaced as plugin:<plugin-name>:<server-name>, receive the 401 challenge, and the session correctly flags them as "require authentication before their tools can be used." But no surface can start the OAuth flow for them:

  1. claude mcp get <name> / claude mcp login <name>No MCP server named … for every naming scheme tried: bare incode-context, plugin:<plugin>:incode-context, <plugin>:incode-context.
  2. The /mcp panel does not list them (docs say plugin servers "appear in the list with indicators showing they come from plugins" — they don't).
  3. The desktop app's plugin detail page shows them in a "Connectors" section with per-server Install buttons that are greyed out / non-functional (previously reported for the button specifically in #45219, closed).

So a plugin that bundles OAuth-protected remote MCP servers ships servers that are permanently unauthenticatable — flagged as needing auth in every session, with no user action anywhere that can satisfy them.

Also tried: same-URL token piggyback (doesn't work, by design?)

OAuth tokens appear to be cached per server registration, not per URL: after successfully authenticating a manually-registered server, a second registration pointing at the identical URL still reports Needs authentication. So there is no workaround via authenticating a twin registration — the plugin-bundled entries can never acquire a token at all.

Expected

Any one of:

  • plugin-bundled servers appear in /mcp with the documented Authenticate action, or
  • claude mcp login plugin:<plugin>:<server> resolves plugin servers, or
  • the desktop Connectors "Install"/Connect button starts the OAuth flow.

Current workaround

A plugin skill that shells out to claude mcp add --scope user … to re-register each server outside the plugin, then drives claude mcp login wrapped in a PTY (script -q /dev/null …, since the tool-spawned login refuses non-TTY stdin). Works, but means the plugin cannot own its server definitions, uninstall leaves orphaned user-scope registrations, and config changes can't ship via plugin updates.

Repro

  1. Create a plugin whose .mcp.json declares an HTTP MCP server that returns 401 with a WWW-Authenticate resource-metadata challenge and includes an oauth block.
  2. Install + enable the plugin; start a new session → session reports the server requires authentication.
  3. Run /mcp → server not listed. Run claude mcp login <any naming> → not found.
  4. Register the same URL/oauth config via claude mcp add → appears in /mcp, authenticates fine.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗