motiondivision / motiondivision/ai-kit
Unauthenticated GET returns 200 without the MCP Accept header, hiding the 401 OAuth challenge
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 8
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
Summary
Since the fix for #1, both protected-resource metadata documents resolve correctly. A related gap remains one layer up: an unauthenticated GET https://mcp.motion.dev/plus sent without MCP accept types returns 200 and a JSON server description, with no WWW-Authenticate header. The 401 OAuth challenge is only reachable when the request carries Accept: application/json, text/event-stream (or is a POST).
Clients whose OAuth discovery probe is a plain GET therefore never see the challenge. Some of them parse that 200 body as RFC 9728 protected-resource metadata and fail confusingly, because the description document has no resource field.
Reproduction
$ curl -sS -o /dev/null -w '%{http_code}\n' https://mcp.motion.dev/plus
200
$ curl -sS -o /dev/null -w '%{http_code}\n' \
-H 'Accept: application/json, text/event-stream' https://mcp.motion.dev/plus
405
$ curl -sS https://mcp.motion.dev/plus | jq 'keys'
["description","docs","name","protocolVersion","tools","transport"]
No WWW-Authenticate header is present on the 200. The challenge does appear on a POST:
$ curl -sS -o /dev/null -D - -X POST https://mcp.motion.dev/plus \
-H 'Accept: application/json, text/event-stream' -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"1"}}}'
HTTP/2 401
www-authenticate: Bearer realm="motion", resource_metadata="https://mcp.motion.dev/.well-known/oauth-protected-resource/plus"
The base server behaves the same way (no-Accept=200, with-Accept=405), though it matters less there since it serves tools unauthenticated.
Impact
Codex CLI is a concrete case. codex mcp login motion-plus fails with:
Error: Metadata error: Protected resource metadata missing required resource field
Codex's discovery probe is a plain GET with no Accept header (openai/codex#37830), so it receives the 200 description document and parses it as protected-resource metadata. The error names a metadata document that was never fetched, which sent me a long way down the wrong path before I compared the two responses.
Forcing the accept types makes login succeed on the first attempt:
[mcp_servers.motion-plus]
url = "https://mcp.motion.dev/plus"
http_headers = { "Accept" = "application/json, text/event-stream" }
That is a client-side workaround for a specific client. Any other client that probes with a plain GET hits the same wall.
Expected
An unauthenticated request to a protected MCP endpoint should return 401 with WWW-Authenticate regardless of the Accept header, so auth discovery can find the challenge by the documented path.
If the descriptive JSON is worth keeping, serving it from a separate unprotected URL (or gating it behind an explicit Accept: application/json alone) would preserve it without masking the challenge.
Environment
- Codex CLI 0.149.1, macOS 26.5.1 arm64
- Signed-in Motion account without Motion+ (correcting an earlier version of this issue that said otherwise). The OAuth flow itself completes; entitlement is separate and does not affect anything above, since the reproduction is unauthenticated.
- Verified 2026-08-24, after #1 was closed. Both
/.well-known/oauth-protected-resourceand/.well-known/oauth-protected-resource/plusreturn 200 with a validresourcefield. - The 200/405 split reproduced 5 times out of 5.
Happy to test a fix.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the unauthenticated request handling for the /plus MCP endpoint and reproduce the no-Accept, MCP-Accept, and POST curl cases described here. Done means an unauthenticated GET receives 401 with the documented WWW-Authenticate challenge regardless of Accept, without masking the existing protected-resource metadata behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- api, authentication
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100