Skip to content

Commit eeace35

Browse files
fix(oauth): use POST for resource auto-detection per MCP spec
MCP spec only requires POST support for the main endpoint. Use POST directly for the preflight request to get WWW-Authenticate header with resource_metadata URL. Updated all tests to use POST method in mock handlers.
1 parent 1f74ecc commit eeace35

2 files changed

Lines changed: 6 additions & 6 deletions

File tree

internal/oauth/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,8 @@ func CreateOAuthConfigWithExtraParams(serverConfig *config.ServerConfig, storage
357357
// autoDetectResource attempts to discover the RFC 8707 resource parameter.
358358
// Returns the detected resource URL, or server URL as fallback, or empty string on failure.
359359
func autoDetectResource(serverConfig *config.ServerConfig, logger *zap.Logger) string {
360-
// Make a preflight HEAD request to get WWW-Authenticate header
361-
resp, err := http.Head(serverConfig.URL)
360+
// POST is the only method guaranteed by MCP spec for the main endpoint
361+
resp, err := http.Post(serverConfig.URL, "application/json", strings.NewReader("{}"))
362362
if err != nil {
363363
logger.Debug("Failed to make preflight request for resource detection",
364364
zap.String("server", serverConfig.Name),

internal/oauth/config_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ func TestCreateOAuthConfig_AutoDetectsResource(t *testing.T) {
310310
return
311311
}
312312
// Return 401 with resource_metadata link in WWW-Authenticate header
313-
if r.Method == "HEAD" {
313+
if r.Method == "POST" {
314314
w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Bearer error="invalid_request", resource_metadata="%s/.well-known/oauth-protected-resource"`, serverURL))
315315
w.WriteHeader(http.StatusUnauthorized)
316316
return
@@ -359,7 +359,7 @@ func TestCreateOAuthConfig_ManualOverride(t *testing.T) {
359359
return
360360
}
361361
// Return 401 with resource_metadata link in WWW-Authenticate header
362-
if r.Method == "HEAD" {
362+
if r.Method == "POST" {
363363
w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Bearer error="invalid_request", resource_metadata="%s/.well-known/oauth-protected-resource"`, serverURL))
364364
w.WriteHeader(http.StatusUnauthorized)
365365
return
@@ -411,7 +411,7 @@ func TestCreateOAuthConfig_MergesExtraParams(t *testing.T) {
411411
}`))
412412
return
413413
}
414-
if r.Method == "HEAD" {
414+
if r.Method == "POST" {
415415
w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Bearer error="invalid_request", resource_metadata="%s/.well-known/oauth-protected-resource"`, serverURL))
416416
w.WriteHeader(http.StatusUnauthorized)
417417
return
@@ -469,7 +469,7 @@ func TestCreateOAuthConfig_FallsBackToServerURL(t *testing.T) {
469469
return
470470
}
471471
// Return 401 with resource_metadata link in WWW-Authenticate header
472-
if r.Method == "HEAD" {
472+
if r.Method == "POST" {
473473
w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Bearer error="invalid_request", resource_metadata="%s/.well-known/oauth-protected-resource"`, serverURL))
474474
w.WriteHeader(http.StatusUnauthorized)
475475
return

0 commit comments

Comments
 (0)