diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a915e8c..001eb2c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.1" + ".": "0.1.2" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b61b84..b4191d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [0.1.2](https://github.com/hyprmcp/mcp-gateway/compare/0.1.1...0.1.2) (2025-08-26) + + +### Bug Fixes + +* add request path to metadata and protected resource path ([#31](https://github.com/hyprmcp/mcp-gateway/issues/31)) ([cf4b2c0](https://github.com/hyprmcp/mcp-gateway/commit/cf4b2c04d7913c6ac66bfd4211b5983e33f3324c)) + + +### Docs + +* improve github link in example docs ([8fe53f6](https://github.com/hyprmcp/mcp-gateway/commit/8fe53f6b71072b36fd3d26e0974fee193bba8ab9)) + ## [0.1.1](https://github.com/hyprmcp/mcp-gateway/compare/0.1.0...0.1.1) (2025-08-26) diff --git a/examples/who-am-i/README.md b/examples/who-am-i/README.md index ea93d87..e861b5b 100644 --- a/examples/who-am-i/README.md +++ b/examples/who-am-i/README.md @@ -3,7 +3,8 @@ This demo showcases a complete and functional setup of the MCP Gateway including an instance of the Dex IdP used as authorization server, as well as an upstream MCP server that returns information about the JWT that was used for authentication. -The upstream MCP server is called "MCP, Who am I?" and can be found on GitHub: http://github.com/hyprmcp/mcp-who-am-i/ +The upstream MCP server is called "MCP, Who am I?" and can be found on GitHub: +[`hyprmcp/mcp-who-am-i`](http://github.com/hyprmcp/mcp-who-am-i/) ## Setup diff --git a/examples/who-am-i/docker-compose.yaml b/examples/who-am-i/docker-compose.yaml index bcab6f9..810dded 100644 --- a/examples/who-am-i/docker-compose.yaml +++ b/examples/who-am-i/docker-compose.yaml @@ -18,7 +18,7 @@ services: - .dex.secret.env gateway: - image: ghcr.io/hyprmcp/mcp-gateway:0.1.1 # x-release-please-version + image: ghcr.io/hyprmcp/mcp-gateway:0.1.2 # x-release-please-version command: [ "serve", diff --git a/oauth/oauth.go b/oauth/oauth.go index 04e2597..f2d2340 100644 --- a/oauth/oauth.go +++ b/oauth/oauth.go @@ -67,6 +67,7 @@ func (mgr *Manager) Handler(next http.Handler) http.Handler { if err != nil { metadataURL, _ := url.Parse(mgr.config.Host.String()) metadataURL.Path = ProtectedResourcePath + metadataURL = metadataURL.JoinPath(r.URL.Path) w.Header().Set( "WWW-Authenticate", fmt.Sprintf(`Bearer resource_metadata="%s"`, metadataURL.String()), diff --git a/oauth/protected_resource.go b/oauth/protected_resource.go index 1f2f0cc..e4fbeb8 100644 --- a/oauth/protected_resource.go +++ b/oauth/protected_resource.go @@ -3,12 +3,13 @@ package oauth import ( "encoding/json" "net/http" + "net/url" "github.com/hyprmcp/mcp-gateway/config" "github.com/hyprmcp/mcp-gateway/log" ) -const ProtectedResourcePath = "/.well-known/oauth-protected-resource" +const ProtectedResourcePath = "/.well-known/oauth-protected-resource/" type ProtectedResourceMetadata struct { Resource string `json:"resource"` @@ -20,23 +21,28 @@ type ProtectedResourceMetadata struct { // // Should be used to create a handler for the /.well-known/oauth-protected-resource endpoint. func NewProtectedResourceHandler(config *config.Config) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodGet { - w.Header().Set("Content-Type", "application/json") - - response := ProtectedResourceMetadata{Resource: config.Host.String()} - - if config.Authorization.ServerMetadataProxyEnabled { - response.AuthorizationServers = []string{config.Host.String()} - } else { - response.AuthorizationServers = []string{config.Authorization.Server} - } - - log.Get(r.Context()).Info("Protected resource metadata", "response", response) - - if err := json.NewEncoder(w).Encode(response); err != nil { - log.Get(r.Context()).Error(err, "failed to encode protected resource response") + return http.StripPrefix( + ProtectedResourcePath, + http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodGet { + w.Header().Set("Content-Type", "application/json") + + resourceURL, _ := url.Parse(config.Host.String()) + resourceURL = resourceURL.JoinPath(r.URL.Path) + response := ProtectedResourceMetadata{Resource: resourceURL.String()} + + if config.Authorization.ServerMetadataProxyEnabled { + response.AuthorizationServers = []string{config.Host.String()} + } else { + response.AuthorizationServers = []string{config.Authorization.Server} + } + + log.Get(r.Context()).Info("Protected resource metadata", "response", response) + + if err := json.NewEncoder(w).Encode(response); err != nil { + log.Get(r.Context()).Error(err, "failed to encode protected resource response") + } } - } - }) + }), + ) }