Skip to content

MCP OAuth scope config is not applied to authorization flow #26301

Closed

Description

@joshuapbritz

In full transparency, this ticket was created using an AI agent. I am not sure if there is anything useful here, but I was hoping that I could at least get pointed in the correct direction. My debug session is here: https://opncd.ai/share/LeFwxgyK

I am happy to move or update the issue log. The issue I am having is that a specific MCP server I am trying to connect to is not working. The server is https://docs.medusajs.com/learn/introduction/build-with-llms-ai/mcp-server but when trying to connect I get an error message: OAuth Failure: Missing required state parameter - potential CSRF attack.

The below was output by my agent (Gpt 5.5 xhigh).

Summary

OpenCode exposes an MCP OAuth config option:

"oauth": {
  "scope": "openid email profile"
}

But the configured scope does not appear to be included in the OAuth client metadata used by the MCP TypeScript SDK. As a result, the generated authorization URL can omit scope, which prevents users from working around MCP servers that require explicit scopes.

Environment

  • OpenCode version observed in logs: 1.14.40
  • Current source checked: v1.14.41
  • OS: macOS
  • MCP server tested: https://docs.medusajs.com/mcp

Reproduction

Configure a remote MCP server with an explicit OAuth scope:

{
  "mcp": {
    "medusa": {
      "type": "remote",
      "enabled": true,
      "url": "https://docs.medusajs.com/mcp",
      "oauth": {
        "scope": "openid email profile"
      }
    }
  }
}

Run:

opencode mcp auth medusa

Inspect logs in:

~/.local/share/opencode/log/

Actual Behavior

The generated authorization URL does not include a scope parameter.

Example log shape:

https://cloud.medusajs.com/oauth/authorize
  ?response_type=code
  &client_id=medusa-mcp
  &code_challenge=<redacted>
  &code_challenge_method=S256
  &redirect_uri=http%3A%2F%2F127.0.0.1%3A19876%2Fmcp%2Foauth%2Fcallback
  &state=<redacted>
  &resource=https%3A%2F%2Fdocs.medusajs.com%2F

There is no:

scope=openid%20email%20profile

Expected Behavior

If mcp.<server>.oauth.scope is configured, OpenCode should pass it through so the authorization request includes that scope.

Likely Cause

packages/opencode/src/mcp/index.ts passes oauthConfig?.scope into McpOAuthProvider, but packages/opencode/src/mcp/oauth-provider.ts does not appear to expose that value through clientMetadata.

The MCP TypeScript SDK uses provider.clientMetadata.scope as a fallback when no scope is supplied by the WWW-Authenticate header or protected resource metadata.

Suggested Fix

In packages/opencode/src/mcp/oauth-provider.ts, include configured scope in clientMetadata:

get clientMetadata(): OAuthClientMetadata {
  return {
    redirect_uris: [this.redirectUrl],
    client_name: "OpenCode",
    client_uri: "https://opencode.ai",
    grant_types: ["authorization_code", "refresh_token"],
    response_types: ["code"],
    token_endpoint_auth_method: this.config.clientSecret ? "client_secret_post" : "none",
    ...(this.config.scope ? { scope: this.config.scope } : {}),
  }
}

Why This Matters

Some MCP OAuth servers require explicit scopes but may not advertise MCP protected-resource scopes_supported. OpenCode already has a config option that appears intended to handle this case, but it currently cannot be used as a workaround if it is not included in client metadata.

Activity

  1. mtraynham commented on May 8, 2026

    @mtraynham

    @joshuapbritz is this completed? I didn't see a PR or anything, and am encountering a similar issue.

  2. joshuapbritz commented on May 8, 2026

    @joshuapbritz
    Author

    My situation turned out to be not an issue with opencode but with the MCP provider. The provider said they were working on the issue, but suggested I rather use auth via a pat like this:

    "medusa": {
      "type": "remote",
      "url": "https://docs.medusajs.com/mcp",
      "headers": {
        "Authorization": "Bearer {token}"
      },
      "oauth": false
    }

    I don't know that there is an issue with opencode here. My apologies, I meant to leave a comment when closing the issue.

  3. mtraynham commented on May 8, 2026

    @mtraynham

    @joshuapbritz thanks - if you don't mind reopening, this is still an issue I believe. The configuration supports passing scope, but it's unused.

    Additionally, scope is not being determined from anywhere it seems,

    • Not a OAuth Protected Resource supported_scopes, /.well-known/oauth-protected-resource/<mcp-path>
    • Nor the OAuth Auth Server supported_scopes, /.well-known/oauth-authorization-server
  4. joshuapbritz commented on May 8, 2026

    @joshuapbritz
    Author

    Sure, I am happy to re-open in that case. Can you maybe include any information you have found on your side. Perhaps it is a small fix I can try to do.

  5. mtraynham commented on May 8, 2026

    @mtraynham

    Yes definitely, thank you!


    I'm hitting this same issue — my IdP rejects the authorization request because no scopes are passed on to the request.

    The config scope flows correctly into McpOAuthProvider here:
    packages/opencode/src/mcp/index.ts L191-L196 (https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/mcp/index.ts#L191-L196):

    {
      clientId: oauthConfig?.clientId,
      clientSecret: oauthConfig?.clientSecret,
      scope: oauthConfig?.scope,
      redirectUri: oauthConfig?.redirectUri,
    }

    But clientMetadata in packages/opencode/src/mcp/oauth-provider.ts L38-L47 (https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/mcp/oauth-provider.ts#L38-L47) never uses this.config.scope:

    get clientMetadata(): OAuthClientMetadata {
      return {
        redirect_uris: [this.redirectUrl],
        client_name: "OpenCode",
        client_uri: "https://opencode.ai",
        grant_types: ["authorization_code", "refresh_token"],
        response_types: ["code"],
        token_endpoint_auth_method: this.config.clientSecret ? "client_secret_post" : "none",
      }
    }

    The MCP SDK uses provider.clientMetadata.scope as a fallback when no scope comes from WWW-Authenticate or protected resource metadata. Adding one line fixes it:

    get clientMetadata(): OAuthClientMetadata {
      return {
        redirect_uris: [this.redirectUrl],
        client_name: "OpenCode",
        client_uri: "https://opencode.ai",
        grant_types: ["authorization_code", "refresh_token"],
        response_types: ["code"],
        token_endpoint_auth_method: this.config.clientSecret ? "client_secret_post" : "none",
        ...(this.config.scope ? { scope: this.config.scope } : {}),
      }
    }
  6. joshuapbritz commented on May 8, 2026

    @joshuapbritz
    Author

    Shot, I will definitely play around. I am not very familiar with the opencode codebase, but I have been playing around a little. I will at least take a crack at it and see if I can resolve anything.

    If not, hopefully I can at least find more information that could help someone who knows the code better 😄

  7. rekram1-node commented on Jun 24, 2026

    @rekram1-node
    Contributor

    Closing as fixed and duplicate of #28811. The requested scope propagation landed in #28810: configured oauth.scope is now included in MCP OAuth client metadata and consumed by the current SDK authorization flow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions