Skip to content

[Bug]: OAuth 2.1 PKCE fails for servers with a path in their endpoint URL (RFC 8707 resource mismatch) #10271

@dblandin

Description

@dblandin

Bug Description

OAuth-authenticated MCP servers whose endpoint URL contains a path component
(e.g. https://mcp.granola.ai/mcp) fail to connect due to a resource
identifier mismatch introduced by MCP SDK 1.27.0's RFC 8707 validation.

Steps to Reproduce

  1. Install hermes-agent with the mcp extra (pip install "hermes-agent[mcp]")
  2. Add an OAuth MCP server whose endpoint URL has a path component:
    mcp_servers:
      granola:
        url: https://mcp.granola.ai/mcp
        auth: oauth
    

Expected Behavior

The OAuth discovery flow completes and the connection succeeds.

Actual Behavior

The connection fails immediately with a resource identifier mismatch error:

$ hermes mcp test granola

  Testing 'granola'...
  Transport: HTTP → https://mcp.granola.ai/mcp
  Auth: OAuth 2.1 PKCE
  ✗ Connection failed (9573ms): Protected resource https://mcp.granola.ai/mcp does not match expected https://mcp.granola.ai

Affected Component

Other: MCP Server Authorization (OAuth)

Messaging Platform (if gateway-related)

N/A – setup issue, gateway agnostic

Debug Report

--- Granola MCP Server Failures ---

2026-04-15 10:40:09,554 WARNING tools.mcp_tool: MCP server 'granola' initial connection failed (attempt 1/3), retrying in 1s: unhandled errors in a TaskGroup (1 sub-exception)
2026-04-15 10:40:09,554 ERROR mcp.client.auth.oauth2: OAuth flow error
mcp.client.auth.exceptions.OAuthFlowError: Protected resource https://mcp.granola.ai/mcp does not match expected https://mcp.granola.ai

2026-04-15 10:40:09,554 WARNING tools.mcp_tool: MCP server 'granola' initial connection failed (attempt 2/3), retrying in 2s: unhandled errors in a TaskGroup (1 sub-exception)
2026-04-15 10:40:12,009 ERROR mcp.client.auth.oauth2: OAuth flow error
mcp.client.auth.exceptions.OAuthFlowError: Protected resource https://mcp.granola.ai/mcp does not match expected https://mcp.granola.ai

2026-04-15 10:40:12,012 WARNING tools.mcp_tool: MCP server 'granola' initial connection failed (attempt 3/3), retrying in 4s: unhandled errors in a TaskGroup (1 sub-exception)
2026-04-15 10:40:16,485 ERROR mcp.client.auth.oauth2: OAuth flow error
mcp.client.auth.exceptions.OAuthFlowError: Protected resource https://mcp.granola.ai/mcp does not match expected https://mcp.granola.ai

2026-04-15 10:40:16,488 WARNING tools.mcp_tool: MCP server 'granola' failed initial connection after 3 attempts, giving up: unhandled errors in a TaskGroup (1 sub-exception)

2026-04-15 10:40:53,930 INFO run_agent: Loaded environment variables from /home/open/.hermes/.env
2026-04-15 10:40:55,711 ERROR mcp.client.auth.oauth2: OAuth flow error
mcp.client.auth.exceptions.OAuthFlowError: Protected resource https://mcp.granola.ai/mcp does not match expected https://mcp.granola.ai

2026-04-15 10:40:55,713 WARNING tools.mcp_tool: MCP server 'granola' initial connection failed (attempt 1/3), retrying in 1s: unhandled errors in a TaskGroup (1 sub-exception)
2026-04-15 10:40:55,773 INFO mcp.client.streamable_http: Received session ID: ec548429-6754-4dc7-8a99-11fb453bc6e5
2026-04-15 10:40:55,774 INFO mcp.client.streamable_http: Negotiated protocol version: 2025-11-25
2026-04-15 10:40:56,164 INFO mcp.client.streamable_http: Negotiated protocol version: 2025-11-25
2026-04-15 10:40:56,286 INFO mcp.client.streamable_http: GET stream disconnected, reconnecting in 1000ms...

2026-04-15 10:40:57,356 ERROR mcp.client.auth.oauth2: OAuth flow error
mcp.client.auth.exceptions.OAuthFlowError: Protected resource https://mcp.granola.ai/mcp does not match expected https://mcp.granola.ai

Operating System

Ubuntu 24.04

Python Version

3.11.15

Hermes Version

v0.9.0 (2026.4.13)

Root Cause Analysis

build_oauth_auth() in tools/mcp_oauth.py strips the path from the server URL before constructing OAuthClientProvider:

parsed = urlparse(server_url)
base_url = f"{parsed.scheme}://{parsed.netloc}"   # drops /mcp
provider = OAuthClientProvider(
    server_url=base_url,   # https://mcp.granola.ai, not https://mcp.granola.ai/mcp
    ...
)

MCP SDK 1.27.0 added RFC 8707 resource validation (python-sdk PR #2069) which checks that the resource field in the server's Protected Resource Metadata (RFC 9728) matches the server_url the client was initialized with. The server correctly advertises the full path URL as its resource identifier; the stripped base URL no longer matches.

The constraint mcp>=1.2.0,<2 allows 1.27.0 to be resolved, making this a silent regression for any user who upgrades.

Related: google-gemini/gemini-cli#20017 (same class of bug in a different MCP client)

Proposed Fix

Pass server_url.rstrip("/") directly to OAuthClientProvider (removing the path-stripping block).

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions