Skip to main content
NEUS MCP uses OAuth 2.0 Authorization Code with PKCE for MCP clients. The user signs in on NEUS (same passkey/wallet flow as the product).
Default install: neus setup. Use this page for custom MCP hosts, security review, standalone sign-in, or raw HTTP integration.

Flow overview

MCP client discovers NEUS MCP
  → GET /.well-known/oauth-protected-resource
  → GET /.well-known/oauth-authorization-server
  → GET /oauth/authorize (validates OAuth params; redirects to hosted login if needed)
  → User authenticates on neus.network (passkey, wallet, or Google/Microsoft)
  → Browser returns to /oauth/authorize with session; backend issues auth code
  → Redirect to client callback with code
  → POST /api/v1/auth/mcp/token (exchange code for access token)
  → Client uses Bearer token on MCP requests
/oauth/authorize validates OAuth parameters. Without a session it redirects to https://neus.network/verify?intent=login&returnTo=/oauth/authorize?.... After login it issues a single-use code (10-minute TTL) and redirects to redirect_uri. Token exchange and revocation are public OAuth endpoints on neus.network.

Discovery

Protected resource metadata

GET https://mcp.neus.network/.well-known/oauth-protected-resource
{
  "resource": "https://mcp.neus.network/mcp",
  "authorization_servers": ["https://neus.network"],
  "scopes_supported": [
    "neus:core",
    "neus:profile",
    "neus:secrets",
    "offline_access"
  ],
  "resource_documentation": "https://docs.neus.network/mcp/overview"
}
When the MCP server receives an unauthenticated request:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.neus.network/.well-known/oauth-protected-resource"

Authorization server metadata

GET https://neus.network/.well-known/oauth-authorization-server
{
  "issuer": "https://neus.network",
  "authorization_endpoint": "https://neus.network/oauth/authorize",
  "token_endpoint": "https://neus.network/api/v1/auth/mcp/token",
  "revocation_endpoint": "https://neus.network/api/v1/auth/mcp/revoke",
  "registration_endpoint": "https://neus.network/oauth/register",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "code_challenge_methods_supported": ["S256"],
  "token_endpoint_auth_methods_supported": ["none"],
  "scopes_supported": [
    "neus:core",
    "neus:profile",
    "neus:secrets",
    "offline_access"
  ]
}

Authorization

GET https://neus.network/oauth/authorize
  ?response_type=code
  &client_id=neus-cli
  &redirect_uri=http://127.0.0.1:PORT/callback
  &code_challenge=BASE64URL(SHA256(code_verifier))
  &code_challenge_method=S256
  &state=RANDOM_CSRF_VALUE
  &scope=neus:core neus:profile neus:secrets offline_access
  &resource=https://mcp.neus.network/mcp
ParameterRequiredDescription
response_typeYesMust be code
client_idYesRegistered client identifier
redirect_uriYesMust exactly match a registered URI
code_challengeYesPKCE challenge (BASE64URL of SHA-256 of code_verifier)
code_challenge_methodYesMust be S256
stateYesCSRF protection — returned verbatim
scopeNoDefault: neus:core neus:profile neus:secrets offline_access
resourceYesMust be https://mcp.neus.network/mcp

Token exchange

POST https://neus.network/api/v1/auth/mcp/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
code=AUTH_CODE
redirect_uri=http://127.0.0.1:PORT/callback
client_id=neus-cli
code_verifier=ORIGINAL_CODE_VERIFIER
resource=https://mcp.neus.network/mcp
Response:
{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "rt_...",
  "scope": "neus:core neus:profile neus:secrets"
}

Refresh tokens

POST https://neus.network/api/v1/auth/mcp/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
refresh_token=rt_...
client_id=neus-cli
resource=https://mcp.neus.network/mcp
Refresh tokens rotate on each use. Include offline_access in the initial scope to receive one.

Token claims

The MCP access token is a JWT:
ClaimValueDescription
isshttps://neus.networkToken issuer
audhttps://mcp.neus.network/mcpResource audience — MCP server validates this
subProfile subject IDUnique user identifier
diddid:pkh:...Decentralized identifier
azpClient IDClient that requested the token
scopeSpace-separatedGranted scopes
token_usemcp_accessToken type — MCP server rejects other values
iatUnix secondsIssued at
expUnix secondsExpires at
OAuth access tokens are valid only when aud is https://mcp.neus.network/mcp, iss is https://neus.network, token_use is mcp_access, and the token is not expired or revoked.

Scope model

ScopeDescriptionDefault
neus:corePublic protocol toolsYes
neus:profileSigned-in profile contextYes
neus:secretsPortable encrypted secretsYes
offline_accessRefresh tokenYes

Revocation

POST https://neus.network/api/v1/auth/mcp/revoke
Content-Type: application/x-www-form-urlencoded

token=eyJ...
token_type_hint=access_token
client_id=neus-cli
Revoking an access token also invalidates all associated refresh tokens.

Registered clients

client_idUse
neus-cliNEUS SDK CLI (neus auth) — loopback redirect on 127.0.0.1
Hosted MCP clients (Cursor, VS Code, Claude Code, OpenAI) should use a URL-only MCP config. The host discovers OAuth metadata at /.well-known/mcp.json and runs its own DCR + PKCE + silent refresh lifecycle. Use the NEUS SDK CLI (neus setup) to generate the correct config.

Security properties

PropertyEnforcement
PKCE requiredcode_challenge_method=S256 is mandatory
Exact redirect_uri matchPrevents open redirect attacks
State parameter preservedCSRF protection
Resource indicator requiredPrevents token misuse across services
Token audience validatedMCP tokens cannot be used for other NEUS services
Refresh token rotationOld refresh token invalidated on each use
Tokens never in query stringsBearer header only
Single-use auth codesCode invalidated after first exchange
Access key fallbackFor servers and automation where browser is unavailable

Auth

Keys and headers.

Setup

Install and configure.

Endpoints

Discovery URLs.
Last modified on July 9, 2026