# MCP server authentication: OAuth, tokens, and safe remote access

> How MCP server authentication works for local and remote servers, where OAuth fits, and what to verify before an agent can use a protected tool.

Web version: https://claw-link.dev/learn/mcp-server-authentication

MCP server authentication answers one question: who is allowed to call this
server? The answer changes with the transport. A local server running over
standard input and output usually obtains credentials from its own environment.
A remote server reached over HTTP needs an authorization flow that lets the
client act for a user without handing the user password to the agent.

## Remote MCP authentication

For HTTP-based MCP, a protected server acts as an OAuth resource server. The
MCP client obtains an access token, then presents that token when it calls the
server. The authorization server may be operated with the MCP server or by a
separate identity service.

The current MCP authorization specification is based on OAuth 2.1. It requires
the client to request a token for the intended resource and requires the MCP
server to validate that the token was issued for that server. Passing an inbound
MCP token straight through to an unrelated downstream API is unsafe. The server
needs a separate, appropriate credential for each upstream API it calls.

Read the official [MCP authorization specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization)
before implementing a remote server. It contains the current requirements for
PKCE, metadata discovery, token audience validation, and refresh-token handling.

## Local MCP authentication

A local server using `stdio` does not use the HTTP authorization flow. The MCP
specification says that `stdio` implementations should obtain credentials from
the environment instead. That can be practical for a developer tool, but it
makes local configuration part of the security boundary. Do not put a long-lived
provider token in a repository, shell history, or a shared configuration file.

## Three credentials that people mix up

| Credential | What it authorizes | Typical holder |
| --- | --- | --- |
| MCP access token | The MCP client calling a protected remote MCP server | The MCP client or host |
| Provider token | The server calling Gmail, GitHub, or another app API | The integration service |
| OAuth client secret | The app registration proving which integration started the OAuth flow | The server-side OAuth application |

They are not interchangeable. A Gmail token does not prove that an MCP client
may call your MCP endpoint. An MCP token should not become a Gmail token.

## A practical checklist

1. Identify the transport. `stdio` and remote HTTP have different credential
   paths.
2. For a remote server, verify HTTPS, protected-resource metadata, OAuth client
   registration, PKCE, and token audience validation.
3. Give the downstream app only the scopes its tools require.
4. Keep provider credentials outside the model context and outside logs.
5. Make disconnect and revocation visible to the person who connected the app.
6. Test a denied request, an expired token, and a token intended for another
   server. Those cases reveal whether validation actually exists.

ClawLink uses a hosted connection model for supported apps. You approve the
provider consent screen, while the agent receives tools rather than a raw
provider credential. This does not remove the need to review scopes or write
actions.

## Keep reading
