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
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"
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
Parameter Required Description response_typeYes Must be code client_idYes Registered client identifier redirect_uriYes Must exactly match a registered URI code_challengeYes PKCE challenge (BASE64URL of SHA-256 of code_verifier) code_challenge_methodYes Must be S256 stateYes CSRF protection — returned verbatim scopeNo Default: neus:core neus:profile neus:secrets offline_access resourceYes Must 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:
Claim Value Description isshttps://neus.networkToken issuer audhttps://mcp.neus.network/mcpResource audience — MCP server validates this subProfile subject ID Unique user identifier diddid:pkh:...Decentralized identifier azpClient ID Client that requested the token scopeSpace-separated Granted scopes token_usemcp_accessToken type — MCP server rejects other values iatUnix seconds Issued at expUnix seconds Expires 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
Scope Description Default neus:corePublic protocol tools Yes neus:profileSigned-in profile context Yes neus:secretsPortable encrypted secrets Yes offline_accessRefresh token Yes
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
Property Enforcement PKCE required code_challenge_method=S256 is mandatoryExact redirect_uri match Prevents open redirect attacks State parameter preserved CSRF protection Resource indicator required Prevents token misuse across services Token audience validated MCP tokens cannot be used for other NEUS services Refresh token rotation Old refresh token invalidated on each use Tokens never in query strings Bearer header only Single-use auth codes Code invalidated after first exchange Access key fallback For servers and automation where browser is unavailable
Setup Install and configure.