Fix MCP OAuth Protected Resource Metadata resource field to return string instead of array

What does this MR do and why?

Fix the resource field in the OAuth Protected Resource Metadata endpoint to return a single string instead of an array, per RFC 9728.

The /.well-known/oauth-protected-resource/api/v4/mcp endpoint was returning:

{
  "resource": ["https://gitlab.com/api/v4/mcp"],
  "authorization_servers": ["https://gitlab.com"],
  "scopes_supported": ["mcp"]
}

But RFC 9728 requires resource to be a single URI string:

{
  "resource": "https://gitlab.com/api/v4/mcp",
  "authorization_servers": ["https://gitlab.com"],
  "scopes_supported": ["mcp"]
}

This caused authentication failures in strict OAuth clients (e.g. Gemini CLI, Windsurf) that unmarshal the field as a string type:

failed to decode protected resource response: json: cannot unmarshal array into Go struct field OAuthProtectedResource.resource of type string

Changes:

  • resource_metadata_for: return resource as a plain string (not a single-element array)
  • resource_metadata (generic /.well-known/oauth-protected-resource endpoint): return the primary MCP resource URI as a string
  • Update specs to assert resource is a String, not an Array

References

Screenshots or screen recordings

N/A - server-side JSON response fix.

How to set up and validate locally

curl -s https://gitlab.com/.well-known/oauth-protected-resource/api/v4/mcp | jq .

Expected after fix:

{
  "resource": "https://gitlab.com/api/v4/mcp",
  "authorization_servers": ["https://gitlab.com"],
  "scopes_supported": ["mcp"]
}

MCP Client tests with GitLab and Orbit MCP in !250085 (comment 3707389827) and !250085 (comment 3712994846)

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Michael Friedrich

Merge request reports

Loading
Loading