Skip to content

auth metadata URL comparison fails due to trailing slash #953

@gainsley

Description

@gainsley

Describe the bug

During authorization, we get an invalid error due to URL comparison off by a trailing slash:

call search_threads failed: calling "tools/call": sending "tools/call": rejected by transport: failed to get authorization server metadata: metadata issuer "https://accounts.google.com" does not match issuer URL "https://accounts.google.com/"

To Reproduce
Steps to reproduce the behavior:

  1. Apply the following patch, "patch -p1 < example.patch"
diff --git a/examples/auth/client/main.go b/examples/auth/client/main.go
index f514eba..d3641a7 100644
--- a/examples/auth/client/main.go
+++ b/examples/auth/client/main.go
@@ -15,6 +15,7 @@ import (

        "github.com/modelcontextprotocol/go-sdk/auth"
        "github.com/modelcontextprotocol/go-sdk/mcp"
+       "github.com/modelcontextprotocol/go-sdk/oauthex"
 )

 var (
@@ -84,13 +85,13 @@ func main() {
                RedirectURL:              fmt.Sprintf("http://localhost:%d", *callbackPort),
                AuthorizationCodeFetcher: receiver.getAuthorizationCode,
                // Uncomment the client configuration you want to use.
-               // PreregisteredClient: &oauthex.ClientCredentials{
-               //              ClientID:     "",
-               //              ClientSecretAuth: &oauthex.ClientSecretAuth{
-               //                      ClientSecret: "",
-               //              },
-               //      },
-               // },
+               PreregisteredClient: &oauthex.ClientCredentials{
+                               ClientID:     "foo",
+                               ClientSecretAuth: &oauthex.ClientSecretAuth{
+                                       ClientSecret: "bar",
+                               },
+                       },
+               //},
                // DynamicClientRegistrationConfig: &auth.DynamicClientRegistrationConfig{
                //      Metadata: &oauthex.ClientRegistrationMetadata{
                //              ClientName: "Dynamically registered MCP client",
@@ -128,4 +129,16 @@ func main() {
        for _, tool := range tools.Tools {
                log.Printf("- %q", tool.Name)
        }
+
+       // call search_threads tool
+       out, err := session.CallTool(context.Background(), &mcp.CallToolParams{
+               Name:      "search_threads",
+               Arguments: map[string]any{
+                       "pageSize": 3,
+               },
+       })
+       if err != nil {
+               fmt.Printf("call search_threads failed: %s\n", err)
+       }
+       fmt.Printf("Search result: %+v\n", out)
 }
  1. cd examples/auth/client
  2. go build .
  3. ./client --server_url https://gmailmcp.googleapis.com/mcp/v1
2026/05/12 09:24:25 Tools:
2026/05/12 09:24:25 - "create_draft"
2026/05/12 09:24:25 - "list_drafts"
2026/05/12 09:24:25 - "get_thread"
2026/05/12 09:24:25 - "search_threads"
2026/05/12 09:24:25 - "label_thread"
2026/05/12 09:24:25 - "unlabel_thread"
2026/05/12 09:24:25 - "list_labels"
2026/05/12 09:24:25 - "label_message"
2026/05/12 09:24:25 - "unlabel_message"
2026/05/12 09:24:25 - "create_label"
2026/05/12 09:24:25 - "update_label"
2026/05/12 09:24:25 - "delete_label"
call search_threads failed: calling "tools/call": sending "tools/call": rejected by transport: failed to get authorization server metadata: metadata issuer "https://accounts.google.com" does not match issuer URL "https://accounts.google.com/"
Search result: <nil>

Expected behavior

Expected it to fail with invalid client ID/secret ID.

Logs

Additional context

➜  client git log -n1 | more
commit 9f5e89fea2aca32dbebcf058fb1cb65e8cb36b7b
Author: Maciej Kisiel <mkisiel@google.com>
Date:   Fri May 8 14:29:01 2026 +0200

    mcp: refactor streamable handler control flow (#949)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions