claude.ai's custom connector flow now sends discovery requests to /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server before attempting the MCP initialize handshake. Both currently return 404, causing the connector to fail with "Couldn't reach the MCP server" before any MCP traffic is sent.
This is a claude.ai-side behaviour change — the connector was working previously without these endpoints. oauth2-proxy is not the fix; it was deliberately removed because Anthropic's backend performs server-to-server calls that cannot follow browser OAuth redirects.
The correct fix is to implement the OAuth protected resource metadata endpoint (RFC 9728 / MCP spec 2025-06-18) returning an empty authorization_servers array, which signals to claude.ai that the resource exists but requires no OAuth.
The empty authorization_servers array in the protected-resource response is the signal to clients that this resource requires no OAuth. The authorization-server endpoint returning 404 is consistent with that — there is no AS.
2. internal/mcp/server.go — add HEAD handler
claude.ai also sends HEAD /mcp to discover the protocol version before initialize. Currently returns 405. Add to ServeHTTP:
# Should return 200 with JSON body
curl -si https://git-mcp.d-ma.be/.well-known/oauth-protected-resource
# Should return 200 with MCP-Protocol-Version header
curl -I https://git-mcp.d-ma.be/mcp
# Full initialize handshake should still work
curl -s -X POST https://git-mcp.d-ma.be/mcp \
-H "Content-Type: application/json"\
-H "Accept: application/json, text/event-stream"\
-d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"claude.ai","version":"1.0"}}}'| jq .
Acceptance criteria
GET /.well-known/oauth-protected-resource returns 200 with valid JSON containing authorization_servers: []
HEAD /mcp returns 200 with MCP-Protocol-Version: 2025-06-18 header
POST /mcp initialize handshake continues to work as before
claude.ai custom connector reconnects successfully after deploy
Branch
fix/oauth-discovery-endpoints from main
Notes
Do not add oauth2-proxy back. It breaks server-to-server MCP calls.
The resource field in the protected-resource response must match the public URL exactly.
No new dependencies needed — stdlib only.
Created via git-mcp on behalf of @mathiasbq
## Context
claude.ai's custom connector flow now sends discovery requests to `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server` before attempting the MCP `initialize` handshake. Both currently return 404, causing the connector to fail with "Couldn't reach the MCP server" before any MCP traffic is sent.
This is a claude.ai-side behaviour change — the connector was working previously without these endpoints. oauth2-proxy is **not** the fix; it was deliberately removed because Anthropic's backend performs server-to-server calls that cannot follow browser OAuth redirects.
The correct fix is to implement the OAuth protected resource metadata endpoint (RFC 9728 / MCP spec 2025-06-18) returning an empty `authorization_servers` array, which signals to claude.ai that the resource exists but requires no OAuth.
Verified via:
```bash
curl -si https://git-mcp.d-ma.be/.well-known/oauth-protected-resource
# → 404 (broken)
curl -si https://git-mcp.d-ma.be/.well-known/oauth-authorization-server
# → 404 (broken)
```
## Task
Add two well-known discovery endpoint handlers to `main.go` and add a `HEAD` handler to `server.go` that returns the required `MCP-Protocol-Version` header.
## Implementation
### 1. `main.go` — add well-known routes
Register before the MCP handler:
```go
mux.HandleFunc("/.well-known/oauth-protected-resource", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(`{"resource":"https://git-mcp.d-ma.be","bearer_methods_supported":[],"authorization_servers":[]}`))
})
mux.HandleFunc("/.well-known/oauth-authorization-server", func(w http.ResponseWriter, r *http.Request) {
http.NotFound(w, r)
})
```
The empty `authorization_servers` array in the protected-resource response is the signal to clients that this resource requires no OAuth. The authorization-server endpoint returning 404 is consistent with that — there is no AS.
### 2. `internal/mcp/server.go` — add HEAD handler
claude.ai also sends `HEAD /mcp` to discover the protocol version before `initialize`. Currently returns 405. Add to `ServeHTTP`:
```go
case http.MethodHead:
w.Header().Set("MCP-Protocol-Version", ProtocolVersion)
w.WriteHeader(http.StatusOK)
```
### 3. Verify after deploy
```bash
# Should return 200 with JSON body
curl -si https://git-mcp.d-ma.be/.well-known/oauth-protected-resource
# Should return 200 with MCP-Protocol-Version header
curl -I https://git-mcp.d-ma.be/mcp
# Full initialize handshake should still work
curl -s -X POST https://git-mcp.d-ma.be/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"claude.ai","version":"1.0"}}}' | jq .
```
## Acceptance criteria
- `GET /.well-known/oauth-protected-resource` returns 200 with valid JSON containing `authorization_servers: []`
- `HEAD /mcp` returns 200 with `MCP-Protocol-Version: 2025-06-18` header
- `POST /mcp` initialize handshake continues to work as before
- claude.ai custom connector reconnects successfully after deploy
## Branch
`fix/oauth-discovery-endpoints` from `main`
## Notes
- Do **not** add oauth2-proxy back. It breaks server-to-server MCP calls.
- The `resource` field in the protected-resource response must match the public URL exactly.
- No new dependencies needed — stdlib only.
---
_Created via git-mcp on behalf of @mathiasbq_
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Context
claude.ai's custom connector flow now sends discovery requests to
/.well-known/oauth-protected-resourceand/.well-known/oauth-authorization-serverbefore attempting the MCPinitializehandshake. Both currently return 404, causing the connector to fail with "Couldn't reach the MCP server" before any MCP traffic is sent.This is a claude.ai-side behaviour change — the connector was working previously without these endpoints. oauth2-proxy is not the fix; it was deliberately removed because Anthropic's backend performs server-to-server calls that cannot follow browser OAuth redirects.
The correct fix is to implement the OAuth protected resource metadata endpoint (RFC 9728 / MCP spec 2025-06-18) returning an empty
authorization_serversarray, which signals to claude.ai that the resource exists but requires no OAuth.Verified via:
Task
Add two well-known discovery endpoint handlers to
main.goand add aHEADhandler toserver.gothat returns the requiredMCP-Protocol-Versionheader.Implementation
1.
main.go— add well-known routesRegister before the MCP handler:
The empty
authorization_serversarray in the protected-resource response is the signal to clients that this resource requires no OAuth. The authorization-server endpoint returning 404 is consistent with that — there is no AS.2.
internal/mcp/server.go— add HEAD handlerclaude.ai also sends
HEAD /mcpto discover the protocol version beforeinitialize. Currently returns 405. Add toServeHTTP:3. Verify after deploy
Acceptance criteria
GET /.well-known/oauth-protected-resourcereturns 200 with valid JSON containingauthorization_servers: []HEAD /mcpreturns 200 withMCP-Protocol-Version: 2025-06-18headerPOST /mcpinitialize handshake continues to work as beforeBranch
fix/oauth-discovery-endpointsfrommainNotes
resourcefield in the protected-resource response must match the public URL exactly.Created via git-mcp on behalf of @mathiasbq