Skip to content

[Bug]: OAuth Discovery Returns Non-Standard MCP URL Pattern Breaking Standard MCP Clients #17272

Description

@sreejith-warier

What happened?

LiteLLM Bug Report: OAuth Discovery Returns Non-Standard MCP URL Pattern

Bug Summary

LiteLLM's OAuth discovery endpoint returns a non-standard resource URL pattern for MCP servers, causing OAuth flow failures with standard MCP clients.

Environment

  • LiteLLM Version: v1.80.5.rc.2 (also confirmed in v1.80.0-stable.1)
  • Deployment: Kubernetes (AKS) with Istio service mesh
  • MCP Server Type: OpenAPI-based MCP server with OAuth2 authentication
  • MCP Clients Tested: mcp-inspector, VSCode Copilot

Problem Description

When configuring an MCP server with OAuth2 authentication, LiteLLM's OAuth discovery endpoint returns a resource URL using the pattern /{server_name}/mcp instead of the MCP standard pattern /mcp/{server_name}.

This causes MCP clients following the OAuth 2.0 Protected Resource Metadata specification to fail with a URL mismatch error.

Configuration

LiteLLM Config (config.yaml)

general_settings:
  store_model_in_db: true
  supported_db_objects: ["models"]

mcp_servers:
  my_service:
    alias: my_service
    auth_type: oauth2
    client_id: "oauth2_example_client_id_12345"
    client_secret: "example_secret_xyz789"
    authorization_url: "https://auth.example.com/oauth2/authorize"
    token_url: "https://auth.example.com/oauth2/token"
    spec_path: "/mnt/openapi-specs/my-service-openapi.json"
    url: "https://backend-api.example.com/api"
    transport: http
    timeout: 30.0

Expected Behavior

Standard MCP Pattern (RFC 8414 Compliant)

When a client requests:

GET /.well-known/oauth-protected-resource/mcp/my_service

The OAuth discovery response should return:

{
  "authorization_servers": ["https://litellm-host/my_service"],
  "resource": "https://litellm-host/mcp/my_service"
}

The resource URL should match the client's request URL pattern: /mcp/{server_name}

Actual Behavior

Current LiteLLM Response

When a client requests:

GET /.well-known/oauth-protected-resource/mcp/my_service

LiteLLM returns 404 Not Found because it only supports the endpoint:

GET /.well-known/oauth-protected-resource/my_service/mcp

When requesting the LiteLLM-specific endpoint:

GET /.well-known/oauth-protected-resource/my_service/mcp

The OAuth discovery response returns:

{
  "authorization_servers": ["https://litellm-host/my_service"],
  "resource": "https://litellm-host/my_service/mcp"
}

The resource URL uses LiteLLM's non-standard pattern: /{server_name}/mcp

Impact

This breaks OAuth authentication for MCP clients that follow the standard /mcp/{server_name} URL convention:

Error from mcp-inspector:

Failed to start OAuth flow: Protected resource https://litellm-host/my_service/mcp
does not match expected https://litellm-host/mcp/my_service (or origin)

OAuth Flow Breakdown:

  1. ✅ Client requests: https://litellm-host/mcp/my_service
  2. ✅ Client fetches OAuth discovery (after rewrite): /.well-known/oauth-protected-resource/my_service/mcp
  3. ❌ Discovery returns: resource: "https://litellm-host/my_service/mcp"
  4. ❌ Client validation fails: Expected /mcp/my_service, got /my_service/mcp
  5. ❌ OAuth flow aborted

Steps to Reproduce

  1. Configure MCP server with OAuth2:

    mcp_servers:
      test_server:
        auth_type: oauth2
        client_id: "test_client"
        client_secret: "test_secret"
        authorization_url: "https://auth-server.example.com/oauth2/authorize"
        token_url: "https://auth-server.example.com/oauth2/token"
        url: "https://backend-api.example.com"
  2. Start LiteLLM proxy

  3. Test OAuth discovery endpoint:

    # Standard MCP pattern - returns 404
    curl https://litellm-host/.well-known/oauth-protected-resource/mcp/test_server
    
    # LiteLLM pattern - returns response but with wrong resource URL
    curl https://litellm-host/.well-known/oauth-protected-resource/test_server/mcp
  4. Observe OAuth discovery response:

    {
      "resource": "https://litellm-host/test_server/mcp"  // Wrong pattern
    }
  5. Attempt OAuth flow with standard MCP client:

    mcp-inspector https://litellm-host/mcp/test_server
  6. Error occurs: URL mismatch validation failure

Evidence / Logs

OAuth Discovery Response (Actual):

$ kubectl exec -n litellm deployment/litellm -- curl -s http://localhost:4000/.well-known/oauth-protected-resource/my_service/mcp
{
  "authorization_servers": [
    "http://localhost:4000/my_service"
  ],
  "resource": "http://localhost:4000/my_service/mcp"
}

LiteLLM Logs:

INFO: 172.19.6.252:59208 - "GET /.well-known/oauth-protected-resource/mcp/my_service HTTP/1.1" 404 Not Found
INFO: 172.19.6.252:59208 - "GET /.well-known/oauth-protected-resource HTTP/1.1" 200 OK
INFO: 172.19.2.213:53160 - "GET /authorize?response_type=code&client_id=<redacted>&... HTTP/1.1" 404 Not Found

MCP Endpoint Behavior:

# Standard MCP pattern - WORKS
$ curl -X POST https://litellm-host/mcp/my_service
HTTP/1.1 200 OK

# LiteLLM pattern - FAILS
$ curl -X POST https://litellm-host/my_service/mcp
HTTP/1.1 500 Internal Server Error

Observation: The actual MCP endpoint responds to /mcp/{server_name} (standard pattern), but OAuth discovery advertises /my_service/mcp (non-standard pattern).

Root Cause Analysis

LiteLLM uses /{server_name}/mcp for OAuth discovery endpoints but the actual MCP server responds to /mcp/{server_name}. This inconsistency breaks OAuth clients that validate the resource URL matches the original request URL.

Code Reference

The OAuth discovery implementation likely constructs resource URLs as:

f"/{server_name}/mcp"

Instead of the standard MCP pattern:

f"/mcp/{server_name}"

Proposed Solutions

Option 1: Support Standard MCP URL Pattern (Recommended)

Add support for standard MCP OAuth discovery endpoints:

Request: GET /.well-known/oauth-protected-resource/mcp/{server_name}

Response:

{
  "authorization_servers": ["https://litellm-host/{server_name}"],
  "resource": "https://litellm-host/mcp/{server_name}"
}

This makes LiteLLM compliant with MCP specifications.

Option 2: Dual Pattern Support

Support both patterns:

  • Standard: /.well-known/oauth-protected-resource/mcp/{server_name} → returns /mcp/{server_name}
  • LiteLLM: /.well-known/oauth-protected-resource/{server_name}/mcp → returns /{server_name}/mcp

Option 3: Configuration Option

Add a configuration parameter to choose URL pattern:

mcp_servers:
  test_server:
    url_pattern: "standard"  # or "litellm"

Related Issues

Additional Context

This appears to be a design choice rather than a bug, but it breaks compatibility with:

  • MCP specification (if one exists)
  • Standard OAuth 2.0 Protected Resource Metadata (RFC 8414)
  • Standard MCP clients (mcp-inspector, VSCode Copilot MCP extension)

Request

Please either:

  1. Fix: Change LiteLLM to use the standard /mcp/{server_name} pattern for OAuth discovery
  2. Support: Add dual pattern support for backward compatibility
  3. Document: Clearly document that LiteLLM requires non-standard URL patterns and provide guidance for client configuration

Environment Details

LiteLLM Version: v1.80.5.rc.2
Python: 3.12
Deployment: Kubernetes (Azure AKS)
Ingress: Istio 1.23.x
MCP Clients: mcp-inspector, VSCode Copilot

Thank you for your work on LiteLLM! This is an excellent project and we appreciate the MCP integration. Looking forward to getting OAuth working with standard MCP clients.

Relevant log output

Are you a ML Ops Team?

No

What LiteLLM version are you on ?

v1.80.5.rc.2

Twitter / LinkedIn details

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions