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: npx -y -p @neus/sdk neus setup and neus auth. Use this page for custom MCP hosts, security review, 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, renders HostedLoginFlow)
  → User authenticates on NEUS (passkey/wallet)
  → /oauth/authorize continuation: 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, runs Hosted Login when needed, issues a single-use code (10-minute TTL), and redirects to redirect_uri.

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"
  ],
  "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",
  "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 URL-only config when possible and let the host run OAuth discovery from /.well-known/mcp.json.

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 June 4, 2026