MCP OAuth Compatibility Problems: Scope & Auth
Introduction: The OAuth Challenge in MCP Clients
Hey guys, let's dive into a critical issue affecting the integration of Model Context Protocol (MCP) clients with OAuth-enabled MCP servers. We're talking about compatibility problems, specifically around how these clients handle OAuth scopes and authentication when Dynamic Client Registration (DCR) is enabled. Major clients like Claude Code, Google Gemini CLI, and GitHub Copilot are experiencing difficulties. This limits the potential of Nextcloud MCP servers to work seamlessly with these tools in OAuth mode. It's a real headache for those of us trying to leverage OAuth for secure and efficient workflows.
Impact on Nextcloud MCP Server: Why This Matters
So, why should we care? Well, the Nextcloud MCP server's OAuth mode is currently experimental, as the README.md clearly states. This means it's not quite ready for prime time, and these compatibility issues are a major reason why. If you're trying to use OAuth with Claude Code, Gemini CLI, or Copilot, you might hit a wall with authentication failures. What's worse, if you're in an enterprise environment using providers like Azure AD/Entra ID, Okta, or others, you're facing additional hurdles. This is also independent of the upstream Nextcloud issues related to Bearer token support.
Diving Deep: The Root Causes of the Problems
Let's get into the nitty-gritty and look at the core issues:
1. The DCR Dilemma: Dynamic Client Registration Requirements
First off, Claude Code needs DCR to play nice, according to RFC 7591. But here's where things get tricky:
- Enterprise OAuth providers, such as Azure AD and Okta, often don't support DCR. Yikes.
- Even when DCR is supported, providers often want pre-provisioned API keys to access the registration endpoint. It's a catch-22.
- Clients, unfortunately, don't always give you a way to specify a client ID/secret manually as a fallback.
Example: If you try to integrate with Azure AD, you'll probably see this error message:
AADSTS70011: The provided request must include a 'scope' input parameter.
The provided value for the input parameter 'scope' is not valid.
2. The Scope Parameter Snafu: Scope Parameter Issues
Okay, next up is the scope parameter. MCP clients aren't always sending the right scopes when DCR is enabled:
- Sometimes, they skip the
scope
parameter altogether. Oops! - Other times, the
scope
values are just plain wrong. - There isn't a solid standard for MCP servers to tell clients what scopes they need.
Impact: Authorization servers reject requests because the scopes are missing or invalid.
3. The OAuth Discovery Failures: OAuth Discovery Failures
Clients have serious trouble figuring out the OAuth configuration:
- Gemini CLI: Can't pull
resource_metadata
from theWWW-Authenticate
header, and it tries the wrong discovery endpoint (.well-known/oauth-authorization-server
instead of following theresource_metadata
URL). - Claude Code: Immediately jumps to
/.well-known/oauth-authorization-server
and ignores theresource_metadata
header. - Inconsistent handling of RFC 8414 (OAuth Authorization Server Metadata) and RFC 9728 (OAuth Protected Resource Metadata).
4. Architectural Design Issues: Architectural Design Issues
Currently, the MCP auth setup treats MCP servers like OAuth authorization servers. This means that every MCP server has to implement a bunch of things:
- Discovery endpoints
- Registration endpoints
- Authorization endpoints
- Token endpoints
Proposed solution: Treat MCP servers as OAuth resource servers, using existing identity providers/authorization servers. This is outlined in modelcontextprotocol/modelcontextprotocol#205.
Upstream Issues: Where the Real Problems Lie
Let's look at the bigger picture and what the MCP specification and client repositories are saying:
MCP Specification Repository
- #695 - Incompatible DCR Flow When registration_endpoint Requires Credentials: DCR doesn't work well with providers like Okta that need API keys for registration.
- Impact: Can't use DCR with major enterprise OAuth providers.
- #205 - Treat the MCP server as an OAuth resource server: The current architecture makes every MCP server a full OAuth authorization server.
- Proposal: Use a resource server pattern to leverage existing identity providers.
- Would enable enterprise scenarios, token exchange flows, and reduce complexity.
Claude Code Repository
- #2527 - Claude OAuth requires DCR, making Azure AD/Entra ID integration complex: Azure AD doesn't support DCR. Claude uses random ports requiring constant Azure AD app updates. Missing
scope
parameter causes AADSTS70011 errors. - #2267 - Cannot connect Remote GitHub MCP Server: Claude Code can't authenticate with GitHub's MCP server due to OAuth discovery and DCR issues.
- #3515 - MCP OAuth Integration Fails on Production Deployments: OAuth flow fails immediately with
step=start_error
on production deployments. - #1178 - Claude Code MCP Server OAuth doesn't work in SSH remote sessions: No way to access the browser remotely for OAuth flow, limiting deployment scenarios.
Google Gemini CLI Repository
- #5011 - /mcp auth github fails to discover OAuth configuration: Gemini CLI can't extract
resource_metadata
from theWWW-Authenticate
header and tries the wrong discovery endpoint. - #5397 - Github MCP OAuth: Related OAuth issues with GitHub MCP server.
FastMCP Repository
- #972 - OAuth works with MCP Inspector but not with Claude/FastMCP Client: OAuth works with MCP Inspector but fails with Claude Desktop and FastMCP Client. Error:
invalid_client
.
Technical Deep Dive: More Details on the Problems
Let's get into some technical specifics:
OAuth Discovery Mechanisms
The MCP specification has multiple OAuth discovery methods, but clients mess up the implementation:
- RFC 9728 - OAuth 2.0 Protected Resource Metadata: The server sends a
WWW-Authenticate
header with aresource_metadata
URL. - RFC 8414 - OAuth Authorization Server Metadata: Discovery at
/.well-known/oauth-authorization-server
.
GitHub MCP Server example: The server might send this header:
WWW-Authenticate: Bearer error="invalid_request",
error_description="No access token was provided in this request",
resource_metadata="https://api.githubcopilot.com/.well-known/oauth-protected-resource/mcp"
Gemini CLI can't figure this out and tries the wrong endpoint.
Scope Communication Problem
- OAuth servers need to know which scopes to grant.
- The MCP spec doesn't define standard scopes.
- Clients don't have a way to find out which scopes are needed from the MCP server.
- Some clients don't send a
scope
parameter at all with DCR.
Provider Compatibility Matrix
Here's a quick look at how different providers stack up:
Provider | DCR Support | Status | Notes |
---|---|---|---|
Azure AD/Entra ID | ❌ No | Broken | Requires pre-registration, fixed redirect URIs |
Okta | ⚠️ Requires API Key | Broken | DCR endpoint needs admin credentials |
AWS Cognito | ❌ No | Broken | Requires custom implementation with Lambda/API Gateway |
Auth0 | ✅ Yes | May work | DCR supported (requires testing) |
Keycloak | ✅ Yes | May work | DCR supported (requires testing) |
GitHub | ❌ Special | Complex | Uses RFC 9728, but clients fail to discover properly |
Potential Solutions: Ideas from the Community
Here are some community-proposed solutions:
SEP-991: Client ID Metadata Documents
- Allow OAuth clients to use HTTPS URLs as client identifiers.
- The URL points to a JSON document with client metadata.
- Addresses scenarios where servers and clients don't have a pre-existing relationship.
- Enables servers to trust clients based on verified metadata.
SEP-1299: Simplified Flow
- Move OAuth flow management from MCP clients to MCP servers.
- Use HTTP Message Signatures for session binding.
- Resource servers could leverage existing authorization methods.
Resource Server Pattern
- Treat MCP servers as OAuth resource servers, not authorization servers.
- Use existing identity providers/authorization servers.
- The MCP server validates tokens but doesn't issue them.
- Supports token exchange flows for on-behalf-of scenarios.
Status and Recommendations: What You Should Do
Current State
- ⚠️ OAuth mode in this Nextcloud MCP server is EXPERIMENTAL.
- 🔴 Not recommended for production because of:
- Client compatibility issues (the problem we're discussing).
- Nextcloud upstream issues (#209).
- Limited enterprise OAuth provider support.
Short-term Workarounds
- ✅ Use Basic Auth mode (recommended) - it works reliably with all clients.
- ⚠️ For OAuth testing: Use providers with full DCR support (Auth0, Keycloak).
- ⚠️ Avoid enterprise providers (Azure AD, Okta) until client-side issues are fixed.
Long-term
- 🕒 Monitor upstream MCP client repositories for OAuth improvements.
- 🕒 Watch for SEP-991 and SEP-1299 standardization progress.
- 🕒 Track Nextcloud
user_oidc
Bearer token support (#209). - 🕒 Consider implementing the resource server pattern when clients support it.
References: Where to Learn More
Here are some resources to get you started:
Blog Posts & Documentation
- Evolving OAuth Client Registration in MCP
- Tips to Harden OAuth Dynamic Client Registration in MCP Servers
- Diving Into the MCP Authorization Specification
- Let's fix OAuth in MCP by Aaron Parecki
- MCP and OAuth Dynamic Client Registration
- Understanding OAuth2 and implementing identity-aware MCP servers
MCP Specification
This is a tracking issue. I'll add updates as upstream issues progress and client implementations improve. Stay tuned!"