Remote vs local MCP servers: how OAuth sign-in works
Disclosure: I make thumbs, one of the options below. I'll say where each option fits, including where mine doesn't.
Adding an MCP server to Claude Code, Cursor or the Claude app takes one line. What happens next, when a browser window opens and asks you to sign in, is OAuth. This guide explains what is actually going on, in terms of what the MCP specification says, and then shows how thumbs, a remote server, fits into it. If you only want the iOS side of things, see iOS Simulator MCP: local or remote.
Local versus remote MCP servers
MCP has two standard transports (transports in the spec): stdio, where the client starts the server as a subprocess on your computer, and Streamable HTTP, where the server lives at a URL.
- A local server runs on your machine. The spec says stdio servers should not follow its authorization flow and should take credentials from the environment instead. That's why local servers are configured with API keys in a config file or environment variables.
- A remote server is a web service. Authorization is optional in the spec, but HTTP-based servers that support it should follow the specification's OAuth flow (authorization in the spec). The client never gets your password: you sign in on the provider's page, and the client receives a token.
What the spec asks for
In short, as the current spec text puts it:
- The MCP server acts as an OAuth 2.1 resource server and the MCP client as an OAuth 2.1 client.
- The server must publish Protected Resource Metadata (RFC 9728) so a client can find its authorization server, and the client must use it. The 401 response points at it with a
resource_metadatavalue in theWWW-Authenticateheader. - The authorization server publishes its own metadata (RFC 8414 or OpenID Connect discovery): the authorize, token and, if supported, registration endpoints.
- Client registration: the client needs a client ID. The spec lists three ways: Client ID Metadata Documents, pre-registration, and Dynamic Client Registration (RFC 7591). Dynamic Client Registration is marked deprecated in the current spec and kept for backwards compatibility; the spec now recommends Client ID Metadata Documents for clients and servers with no prior relationship (client registration). Many servers still use dynamic registration; thumbs is one (see below).
- PKCE: clients must use it with the
S256method when they can, and must check the authorization server's metadata listscode_challenge_methods_supportedbefore they go on. PKCE stops someone who intercepts the authorization code from exchanging it for a token (security considerations). - Resource indicators (RFC 8707): the client sends a
resourceparameter naming the MCP server, so the token is issued for that server, and the server must check that tokens were issued for it. - The token is sent in an
Authorization: Bearerheader on every request, never in the URL.
The flow, step by step
- The client sends a request with no token. The server answers 401 with a
WWW-Authenticateheader that includesresource_metadata. - The client fetches the protected resource metadata and learns the authorization server.
- It fetches the authorization server's metadata.
- It registers (dynamic registration: a
POSTto the/registerendpoint) and gets a client ID. - It creates a PKCE verifier and challenge, and opens your browser at the authorize URL, with the challenge and the
resource. - You approve and sign in on the provider's page. The browser returns to the client with an authorization code.
- The client exchanges the code, with the verifier, for an access token, and uses it from then on.
How thumbs does it
thumbs is a remote server at https://mcp.usethumbs.com/mcp. You can see the first steps yourself, no account needed:
curl -i -X POST https://mcp.usethumbs.com/mcp \
-H 'content-type: application/json' -d '{}'
When I ran that on 27 October 2026 it returned 401 with a WWW-Authenticate header carrying a resource_metadata URL, as step 1 describes. Fetching that URL, and then the authorization server metadata at https://mcp.usethumbs.com/.well-known/oauth-authorization-server, shows:
- authorize, token and registration endpoints (
/authorize,/token,/register) onmcp.usethumbs.com; code_challenge_methods_supportedlistingS256(it listsplaintoo);- the
authorization_codeandrefresh_tokengrants; client_id_metadata_document_supportedset tofalse: so a client uses dynamic registration, as above.
On sign-in, the page you see names the agent asking, shows where the browser will return to, and has a button labelled "Approve and sign in with Google". You sign in with a Google account; only accounts let in from the waitlist get a phone. If your account isn't on the list yet, you see a "Not on the list yet" page instead, with a link to join the waitlist.
In Claude Code the whole thing is:
claude mcp add --transport http thumbs https://mcp.usethumbs.com/mcp
followed by /mcp to sign in. In Cursor, add the URL to ~/.cursor/mcp.json; in the Claude app, add it as a custom connector.
What to check when sign-in fails
- Is the URL right? It should end in
/mcp. Acurllike the one above should return 401, not 404. - Does your client support remote servers with OAuth? Some clients only support stdio servers or API keys.
- Is the redirect reaching your client? Clients wait for the browser to return to a local address; a firewall, a different browser profile or a remote shell session can interrupt that.
- Is the account on the list? For thumbs, sign-in works for anyone's Google account, but a phone only for accounts let in from the waitlist.
- Stale registration. If a client keeps trying an old registration, remove the server from the client and add it again.
Limits and honesty notes
- The spec changes. Everything above quotes the current text of the pages linked; check them before you build against it, particularly on client registration.
- I haven't described how thumbs stores tokens or anything else I can't point at publicly. The privacy page covers what's kept about visitors and people on the waitlist.
- thumbs' early access is the iOS Simulator, shared between testers, and allowlist-only. A real iPhone of your own is planned; it isn't available yet and has no date or price.
FAQ
What is the difference between a local and a remote MCP server? A local (stdio) server runs as a subprocess on your computer and normally takes credentials from its environment. A remote server lives at a URL over Streamable HTTP and can use OAuth sign-in, so there is nothing to install.
What OAuth version does MCP use? The MCP specification builds on OAuth 2.1, with protected resource metadata (RFC 9728), authorization server metadata (RFC 8414), PKCE and resource indicators (RFC 8707). Authorization is optional, but HTTP servers that support it should follow the specification.
Is dynamic client registration still used? It is supported for backwards compatibility. The current MCP specification marks it deprecated and recommends Client ID Metadata Documents for new implementations. thumbs still advertises a registration endpoint.
How does thumbs sign me in? With Google, through the OAuth flow your MCP client starts: a consent page, then Google sign-in. Only accounts let in from the waitlist get a phone.
Keep reading
- iOS Simulator MCP: local or remote, and which to use: a Mac-based local setup against a remote one.
- How to give an AI agent an iPhone with MCP: how the phone side works under the hood.
- How to test an iOS app with Claude Code or Cursor: what works today for a native app and a web app.