package pier import ( "net/http" "net/url" "git.golem15.com/golem15/summercms/modules/pact" "github.com/modelcontextprotocol/go-sdk/auth" "github.com/modelcontextprotocol/go-sdk/oauthex" ) // PRMScopes is the scopes_supported list of the protected resource // metadata: the OAuth server's MCP scopes plus backend (D-21). var PRMScopes = []string{"read", "write", "ai", "offline_access", "backend"} // mountPRM serves the RFC 9728 protected resource metadata at // /.well-known/oauth-protected-resource and at // /.well-known/oauth-protected-resource, through the host's // plain GET route kind. The authorization // server is the published verifier's resource origin when a verifier is // published, else app.url. A mcp.resource that differs from the verifier's // resource is logged as a warning at boot (Pitfall 8). func (p *Pier) mountPRM() error { issuer := p.cfg.AppURL if verifier, ok := p.app.Lookup[pact.MCPTokenVerifier](); ok && verifier != nil { if res := verifier.MCPResource(); res != "" { if u, err := url.Parse(res); err == nil && u.Scheme != "" && u.Host != "" { issuer = u.Scheme + "://" + u.Host } if res != p.cfg.Resource { logger().Warn("pier: mcp.resource differs from the verifier's resource; clients that send the verifier's resource will be refused", "mcp_resource", p.cfg.Resource, "verifier_resource", res) } } } meta := &oauthex.ProtectedResourceMetadata{ Resource: p.cfg.Resource, ScopesSupported: append([]string(nil), PRMScopes...), BearerMethodsSupported: []string{"header"}, } if issuer != "" { meta.AuthorizationServers = []string{issuer} } h := nosniff(auth.ProtectedResourceMetadataHandler(meta)) for _, path := range []string{wellKnownPRM, wellKnownPRM + p.cfg.Path} { if err := p.host.MountJSON(http.MethodGet, path, h); err != nil { return err } } return nil } // nosniff adds X-Content-Type-Options to a JSON document route. func nosniff(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Content-Type-Options", "nosniff") next.ServeHTTP(w, r) }) }