MCP plugin /register endpoint returns 200 response instead of 201 #1650

Closed
opened 2026-03-13 08:53:30 -05:00 by GiteaMirror · 9 comments
Owner

Originally created by @dkokotov on GitHub (Aug 6, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Follow documentation in https://www.better-auth.com/docs/plugins/mcp to set up the plugin.
  2. Test with an MCP client and observe the response when the client uses OAuth dynamic client registration to register itself

Current vs. Expected behavior

The /register endpoint used for dynamic client registration should, per spec, return a 201 response in the case of successful registration.

However, in actuality a 200 response is returned (see screenshot below from Vercel deployment log).

With some MCP clients that implement the spec very strictly, this causes the auth flow to fail. In particular I was testing with the Context Mac app (https://www.contextmcp.app).

What version of Better Auth are you using?

1.3.10

Provide environment information

- OS: Mac OS X
- Browser: Safari (or Chrome, doesn't matter)

Which area(s) are affected? (Select all that apply)

Backend

Auth config (if applicable)

const pool = new Pool({
    connectionString: process.env.POSTGRES_URL
});

export const auth = betterAuth({
    database: pool,
    baseURL: process.env.AUTH0_BASE_URL ?? `https://${process.env.VERCEL_URL}`,
    plugins: [
        mcp({
            loginPage: '/login',
            oidcConfig: {
                loginPage: '/login',
                requirePKCE: true,
                scopes: ['openid', 'profile', 'email', 'offline_access', 'claudeai']
            }
        }),
        genericOAuth({
            config: [
                {
                    providerId: 'auth0',
                    clientId: process.env.AUTH0_CLIENT_ID,
                    clientSecret: process.env.AUTH0_CLIENT_SECRET,
                    discoveryUrl: `https://${process.env.AUTH0_DOMAIN}/.well-known/openid-configuration`,
                    accessType: 'offline',
                    authorizationUrlParams: {
                        audience: process.env.AUTH0_AUDIENCE
                    }
                }
            ]
        })
    ]
});

Additional context

I can see in the code that it does try intend return a 201 response (https://github.com/better-auth/better-auth/blob/canary/packages/better-auth/src/plugins/mcp/index.ts#L857), however in actuality a 200 response is returned.

I think the error is somewhere in how the better-call library processes that response to turn it into a Response instance, but I don't have a good-enough understanding of it or the innards of better-auth to further trace it.

My current workaround is to copy the MCP plugin and do some monkey-patching via onResponse function in the plugin to fix the response for the /register endpoint to be a 201.

Originally created by @dkokotov on GitHub (Aug 6, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Follow documentation in https://www.better-auth.com/docs/plugins/mcp to set up the plugin. 2. Test with an MCP client and observe the response when the client uses OAuth dynamic client registration to register itself ### Current vs. Expected behavior The `/register` endpoint used for dynamic client registration should, per [spec](https://datatracker.ietf.org/doc/html/rfc7591#section-3.2), return a 201 response in the case of successful registration. However, in actuality a 200 response is returned (see screenshot below from Vercel deployment log). With some MCP clients that implement the spec very strictly, this causes the auth flow to fail. In particular I was testing with the Context Mac app (https://www.contextmcp.app). ### What version of Better Auth are you using? 1.3.10 ### Provide environment information ```bash - OS: Mac OS X - Browser: Safari (or Chrome, doesn't matter) ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript const pool = new Pool({ connectionString: process.env.POSTGRES_URL }); export const auth = betterAuth({ database: pool, baseURL: process.env.AUTH0_BASE_URL ?? `https://${process.env.VERCEL_URL}`, plugins: [ mcp({ loginPage: '/login', oidcConfig: { loginPage: '/login', requirePKCE: true, scopes: ['openid', 'profile', 'email', 'offline_access', 'claudeai'] } }), genericOAuth({ config: [ { providerId: 'auth0', clientId: process.env.AUTH0_CLIENT_ID, clientSecret: process.env.AUTH0_CLIENT_SECRET, discoveryUrl: `https://${process.env.AUTH0_DOMAIN}/.well-known/openid-configuration`, accessType: 'offline', authorizationUrlParams: { audience: process.env.AUTH0_AUDIENCE } } ] }) ] }); ``` ### Additional context I can see in the code that it does try intend return a 201 response (https://github.com/better-auth/better-auth/blob/canary/packages/better-auth/src/plugins/mcp/index.ts#L857), however in actuality a 200 response is returned. I think the error is somewhere in how the `better-call` library processes that response to turn it into a `Response` instance, but I don't have a good-enough understanding of it or the innards of `better-auth` to further trace it. My current workaround is to copy the MCP plugin and do some monkey-patching via `onResponse` function in the plugin to fix the response for the `/register` endpoint to be a 201.
GiteaMirror added the plugin label 2026-03-13 08:53:30 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Aug 6, 2025):

Hi @dkokotov! I'm Dosu and I’m helping the better-auth team.

You're correct: the MCP plugin's /register endpoint explicitly sets the response status to 201 in the code (source), which matches RFC 7591. However, the actual response returned is 200, which suggests that the status code is being lost or overridden by the response handling layer—likely in the core middleware or an internal utility, not in the MCP plugin itself. This is a known issue and has been discussed as part of making the endpoint fully RFC-compliant (issue #1731).

There isn't a config workaround in Better Auth itself; your monkey-patch approach is a reasonable temporary fix until the core response handler is updated to propagate the intended status code. No recent updates or pull requests address this in the latest versions. If strict client compatibility is critical, continue using your patch for now.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Aug 6, 2025): <!-- Greeting --> Hi @dkokotov! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> You're correct: the MCP plugin's `/register` endpoint explicitly sets the response status to 201 in the code ([source](https://github.com/better-auth/better-auth/blob/69d5239e8f759966e84309743e5c3a5d41bce4b2/packages/better-auth/src/plugins/mcp/index.ts)), which matches RFC 7591. However, the actual response returned is 200, which suggests that the status code is being lost or overridden by the response handling layer—likely in the core middleware or an internal utility, not in the MCP plugin itself. This is a known issue and has been discussed as part of making the endpoint fully RFC-compliant ([issue #1731](https://github.com/better-auth/better-auth/issues/1731)). There isn't a config workaround in Better Auth itself; your monkey-patch approach is a reasonable temporary fix until the core response handler is updated to propagate the intended status code. No recent updates or pull requests address this in the latest versions. If strict client compatibility is critical, continue using your patch for now. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/555adc96-26b8-471c-9c26-47e723540c23?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/555adc96-26b8-471c-9c26-47e723540c23?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/555adc96-26b8-471c-9c26-47e723540c23?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/555adc96-26b8-471c-9c26-47e723540c23?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/555adc96-26b8-471c-9c26-47e723540c23?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/555adc96-26b8-471c-9c26-47e723540c23?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/555adc96-26b8-471c-9c26-47e723540c23?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/3821)
Author
Owner

@himself65 commented on GitHub (Aug 6, 2025):

the code is indeed retunrs 201, so I think it's a bug in on better-call I think

@himself65 commented on GitHub (Aug 6, 2025): the code is indeed retunrs 201, so I think it's a bug in on better-call I think
Author
Owner

@himself65 commented on GitHub (Aug 6, 2025):

It still error. I realized it's a different bug

@himself65 commented on GitHub (Aug 6, 2025): It still error. I realized it's a different bug
Author
Owner

@himself65 commented on GitHub (Aug 6, 2025):

122b5c9d64/src/context.ts (L290-L292)

When asResponse: false, it will just return the object as is, so status and headers no longer exist.

@himself65 commented on GitHub (Aug 6, 2025): https://github.com/Bekacru/better-call/blob/122b5c9d64f7ada18df17a98a313b86acde8ad65/src/context.ts#L290-L292 When asResponse: false, it will just return the object as is, so status and headers no longer exist.
Author
Owner

@Bekacru commented on GitHub (Aug 6, 2025):

122b5c9d64/src/context.ts (L290-L292)

When asResponse: false, it will just return the object as is, so status and headers no longer exist.

Yeah but if a request is from the router that should be the case

@Bekacru commented on GitHub (Aug 6, 2025): > https://github.com/Bekacru/better-call/blob/122b5c9d64f7ada18df17a98a313b86acde8ad65/src/context.ts#L290-L292 > > When asResponse: false, it will just return the object as is, so status and headers no longer exist. > Yeah but if a request is from the router that should be the case
Author
Owner

@Bekacru commented on GitHub (Aug 6, 2025):

Meaning response should be set to true by the router

@Bekacru commented on GitHub (Aug 6, 2025): Meaning response should be set to true by the router
Author
Owner

@himself65 commented on GitHub (Aug 6, 2025):

make a API proposal at https://github.com/Bekacru/better-call/issues/31

@himself65 commented on GitHub (Aug 6, 2025): make a API proposal at https://github.com/Bekacru/better-call/issues/31
Author
Owner

@dkokotov commented on GitHub (Aug 6, 2025):

@Bekacru thanks for looking into this so quickly. However, it doesn't seem like the issue is fixed, I just tried updating to 1.3.5-beta.4, which from what I can tell includes bump to latest better-call with the fix in https://github.com/Bekacru/better-call/pull/30, and the /register endpoint is still returning a 200.

Maybe that's also what some @himself65 's comment above is saying, but just mentioning it again since this issue has been closed.

@dkokotov commented on GitHub (Aug 6, 2025): @Bekacru thanks for looking into this so quickly. However, it doesn't seem like the issue is fixed, I just tried updating to `1.3.5-beta.4`, which from what I can tell includes bump to latest `better-call` with the fix in https://github.com/Bekacru/better-call/pull/30, and the `/register` endpoint is still returning a 200. Maybe that's also what some @himself65 's comment above is saying, but just mentioning it again since this issue has been closed.
Author
Owner

@himself65 commented on GitHub (Aug 6, 2025):

Yeah, I'm still trying to fix this.

@himself65 commented on GitHub (Aug 6, 2025): Yeah, I'm still trying to fix this.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1650