Skip to content

Commit a6ca6f7

Browse files
committed
Fix MCP OAuth discovery failing for servers whose authorization_server URL has a trailing slash (e.g. Miro)
1 parent 64e58b5 commit a6ca6f7

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44

55
- Update the compact prompt to read the active eca__task list after compacting.
6+
- Fix MCP OAuth discovery failing for servers whose authorization_server URL has a trailing slash (e.g. Miro) due to malformed well-known endpoint URL.
67

78
## 0.120.0
89

src/eca/oauth.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@
188188
[^String auth-server]
189189
(let [uri (java.net.URI. auth-server)
190190
base (str (.getScheme uri) "://" (.getAuthority uri))
191-
path (.getPath uri)]
191+
path (.getPath uri)
192+
path (if (= "/" path) "" path)]
192193
(or (fetch-json (str base "/.well-known/oauth-authorization-server" path))
193194
(fetch-json (str base "/.well-known/openid-configuration")))))
194195

test/eca/oauth_test.clj

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,39 @@
262262
(is (some #(= "https://example.com/.well-known/openid-configuration" %) @get-urls)
263263
"should have tried OIDC last"))))))
264264

265+
(deftest oauth-info-trailing-slash-auth-server-test
266+
(testing "discovers auth server metadata when authorization_server URL has trailing slash"
267+
(with-redefs [http/head (fn [_ _] {:status 200})
268+
http/post (fn [url _]
269+
(if (string/includes? url "register")
270+
{:status 200 :body {:client_id "miro-client"}}
271+
(make-auth-response
272+
"Bearer resource_metadata=\"https://mcp.miro.com/.well-known/oauth-protected-resource\"")))
273+
http/get (fn [url _]
274+
(cond
275+
(= url "https://mcp.miro.com/.well-known/oauth-protected-resource")
276+
(make-json-response 200
277+
{:resource "https://mcp.miro.com/"
278+
:authorization_servers ["https://mcp.miro.com/"]
279+
:scopes_supported ["boards:read" "boards:write"]})
280+
281+
(= url "https://mcp.miro.com/.well-known/oauth-authorization-server")
282+
(make-json-response 200
283+
{:authorization_endpoint "https://mcp.miro.com/authorize"
284+
:token_endpoint "https://mcp.miro.com/token"
285+
:registration_endpoint "https://mcp.miro.com/register"})
286+
287+
;; The trailing-slash variant should NOT be hit
288+
(= url "https://mcp.miro.com/.well-known/oauth-authorization-server/")
289+
{:status 401}
290+
291+
:else
292+
{:status 404}))]
293+
(let [info (oauth/oauth-info "https://mcp.miro.com/")]
294+
(is (some? info) "should discover OAuth info for trailing-slash auth server")
295+
(is (= "https://mcp.miro.com/token" (:token-endpoint info)))
296+
(is (string/includes? (:authorization-endpoint info) "mcp.miro.com/authorize"))))))
297+
265298
(deftest oauth-info-returns-nil-when-no-auth-challenge-test
266299
(testing "returns nil when server does not return 401"
267300
(with-redefs [http/head (fn [_ _] {:status 200})

0 commit comments

Comments
 (0)