OAuth for AI assistants
This page is for developers building an MCP client. To connect an assistant you already use, see Trade from an AI assistant (MCP).
The Neurobot MCP server follows the MCP authorization specification : OAuth 2.1 with PKCE, dynamic client registration and resource indicators. A client that implements it connects without any Neurobot-specific code.
| Authorization server (issuer) | Protected resource |
|---|---|
https://api.neurotrading.io | https://api.neurotrading.io/mcp |
Discovery
A request to /mcp without a token answers 401 with a WWW-Authenticate header that points at the protected resource metadata:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="neurobot", resource_metadata="https://api.neurotrading.io/.well-known/oauth-protected-resource/mcp"| Document | URL |
|---|---|
| Protected resource metadata (RFC 9728) | /.well-known/oauth-protected-resource/mcp (also served at /.well-known/oauth-protected-resource) |
| Authorization server metadata (RFC 8414) | /.well-known/oauth-authorization-server |
The authorization server metadata lists the endpoints, all on the issuer’s origin:
| Endpoint | Path |
|---|---|
| Authorization | /authorize |
| Token | /token |
| Dynamic client registration (RFC 7591) | /register |
| Revocation (RFC 7009) | /revoke |
The flow
- Register the client:
POST /registerwith yourclient_nameandredirect_uris. Public clients send"token_endpoint_auth_method": "none"; confidential clients get aclient_secretand may send it in the body (client_secret_post) or as HTTP Basic (client_secret_basic). Redirect URIs must behttps,httponlocalhost/127.0.0.1(any port), or your app’s own scheme such ascursor://…. Show a realclient_name: it’s what the user sees. - Authorize: send the user’s browser to
/authorizewithresponse_type=code,client_id,redirect_uri,state, a PKCEcode_challengewithcode_challenge_method=S256, andresource=https://api.neurotrading.io/mcp. Neurobot opens its consent screen on the web dashboard, where the user signs in, chooses Paper Trading only or live trading, and allows or denies. - Callback: the browser comes back to your
redirect_uriwithcode, yourstateandiss(the issuer). A denial comes back witherror=access_denied. The user has 10 minutes to answer; the code is good for 5 minutes and one exchange. - Exchange the code at
/token(grant_type=authorization_code,code,code_verifier,client_id,redirect_uri,resource). - Call
/mcpwithAuthorization: Bearer <access_token>. - Refresh at
/tokenwithgrant_type=refresh_token. Every refresh returns a new refresh token and spends the old one, so store the new one.
{
"access_token": "nmcp_at_…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "nmcp_rt_…",
"scope": "trading:paper"
}Scopes
The user picks the access level on the consent screen; the token’s scope says which one they chose.
| Scope | Meaning |
|---|---|
trading:paper | Paper Trading only. Every wallet, balance and trade the connection sees is Paper Trading, whatever mode the account is in elsewhere, and it can’t switch the account’s mode. |
trading:live | Acts in the account’s current mode, real funds included. |
Request trading:paper trading:live (or no scope) to let the user choose. Request trading:paper alone and the consent screen offers Paper Trading only. A refresh can’t widen the scope: to change it, the user connects again.
Tokens
- Access tokens last 1 hour and are good for
/mcponly. They aren’t API session tokens, and the REST API refuses them. - Refresh tokens last 30 days from their last use.
- A
401witherror="invalid_token"from/mcpmeans the token expired or the connection was ended: refresh, or send the user through the flow again. POST /revokewith either token ends the whole connection. The user can also end it from Settings → AI connections on the dashboard.
The token endpoint, registration and revocation accept requests from any origin (CORS), so a browser-based client works too. /mcp never accepts the dashboard’s session cookie, only the Authorization header.