Reference
Authentication
Each person signs in with their own Nylon account. The Nylon MCP server is an OAuth 2.1 resource server, and Nylon’s sign-in at https://app.usenylon.com is the authorisation server. Clients discover everything from the first 401, so most users never see a setting.
This page uses the OAuth specifications’ own names for endpoints, fields and documents (such as “authorization server metadata”), and British spelling elsewhere.
The flow
Section titled “The flow”-
Challenge. The client calls
POST https://mcp.usenylon.com/mcpwithout a token and gets401with aWWW-Authenticateheader that points at the protected resource metadata. -
Resource metadata. The client fetches the protected resource metadata, which names
https://app.usenylon.comas the authorisation server. -
Server metadata. The client fetches
https://app.usenylon.com/.well-known/oauth-authorization-server. -
Registration. The client sends its redirect URL to
POST /oauth/registerand gets its pre-assignedclient_id. -
Sign-in. The client opens
/oauth/authorizein the user’s browser with a PKCES256challenge. The user signs in to Nylon and chooses Allow access, and Nylon redirects back with acode. -
Tokens. The client sends the
code, itscode_verifierandresourcetoPOST /oauth/token. It gets an access token (1 hour) and a refresh token (30 days). -
Calls. The client calls
POST /mcpwithAuthorization: Bearer <access_token>.
Client checklist
Section titled “Client checklist”1. The challenge
Section titled “1. The challenge”A request without a valid token gets a 401 that points at the protected resource metadata (RFC 9728):
HTTP/2 401www-authenticate: Bearer error="invalid_token", error_description="authentication required", resource_metadata="https://mcp.usenylon.com/.well-known/oauth-protected-resource"content-type: application/json
{"error":"invalid_token","error_description":"authentication required"}An expired or invalid token gets the same 401 with a short error_description, such as access token expired. Refresh and retry.
2. Protected resource metadata
Section titled “2. Protected resource metadata”GET https://mcp.usenylon.com/.well-known/oauth-protected-resource (also served at /.well-known/oauth-protected-resource/mcp):
{ "resource": "https://mcp.usenylon.com/mcp", "authorization_servers": ["https://app.usenylon.com"], "bearer_methods_supported": ["header"], "scopes_supported": ["openid", "profile", "email", "offline_access"], "resource_name": "Nylon MCP", "resource_documentation": "https://developers.usenylon.com/mcp/"}3. Authorization server metadata
Section titled “3. Authorization server metadata”GET https://app.usenylon.com/.well-known/oauth-authorization-server (RFC 8414). For clients that look on the resource’s own origin, the MCP server also serves a copy at https://mcp.usenylon.com/.well-known/oauth-authorization-server.
{ "issuer": "https://app.usenylon.com", "authorization_endpoint": "https://app.usenylon.com/oauth/authorize", "token_endpoint": "https://app.usenylon.com/oauth/token", "registration_endpoint": "https://app.usenylon.com/oauth/register", "jwks_uri": "https://app.usenylon.com/.well-known/jwks.json", "userinfo_endpoint": "https://app.usenylon.com/oauth/userinfo", "scopes_supported": ["openid", "profile", "email", "offline_access"], "response_types_supported": ["code"], "grant_types_supported": ["authorization_code", "refresh_token"], "code_challenge_methods_supported": ["S256"], "token_endpoint_auth_methods_supported": ["none"]}Use OAuth authorization server metadata, not OpenID Connect discovery: Nylon doesn’t publish an openid-configuration document. The userinfo_endpoint serves Nylon’s own sign-in integrations and doesn’t accept MCP access tokens.
4. Client registration
Section titled “4. Client registration”POST /oauth/register follows RFC 7591, but registration is config-backed. Nylon matches the request’s redirect_uris against the assistants it supports and returns that assistant’s pre-assigned client_id. Nobody types a client ID.
POST /oauth/register HTTP/1.1Host: app.usenylon.comContent-Type: application/json
{"client_name":"Claude","redirect_uris":["https://claude.ai/api/mcp/auth_callback"],"grant_types":["authorization_code","refresh_token"]}HTTP/1.1 201 CreatedCache-Control: no-store
{"client_id":"…","client_id_issued_at":1761004800,"redirect_uris":["…"],"token_endpoint_auth_method":"none","grant_types":["authorization_code","refresh_token"],"response_types":["code"],"client_name":"…","scope":"…"}- The response isn’t an echo of your request.
client_id,client_name,redirect_urisandscopeare the values Nylon holds for that assistant.grant_typesandresponse_typesecho your request; if you leavegrant_typesout, it defaults to["authorization_code"], so send it. - The body must be JSON, 4 kB at most. A larger body gets
413. - Redirect URLs must match exactly, with two exceptions. On
localhostand127.0.0.1, Nylon accepts any port when the registered URL has none (RFC 8252); the host itself must still match, solocalhostand127.0.0.1aren’t interchangeable. IPv6 loopback ([::1]) isn’t supported. The other exception covers the per-connector callbacks that ChatGPT and Copilot Studio generate. - A missing or empty
redirect_urisreturns400 invalid_redirect_uri. An unknown redirect URL returns400 invalid_client_metadata; to add a client, see Other MCP clients. - Clients are public: there’s no client secret. Nylon ignores any secret a public client sends.
5. Authorization request
Section titled “5. Authorization request”Open the authorization endpoint in the user’s browser:
https://app.usenylon.com/oauth/authorize ?response_type=code &client_id=<client_id> &redirect_uri=<registered redirect URL> &scope=openid%20profile%20email%20offline_access &state=<random> &code_challenge=<BASE64URL(SHA256(code_verifier))> &code_challenge_method=S256- Nylon requires PKCE with
S256. It rejectsplainand requests without a challenge. stateis optional, but send it and check it on return. The redirect back carriescodeandstateonly; it has noissparameter (RFC 9207).- You may send
resourcehere too. Nylon ignores it at this step and binds the audience at the token endpoint. - A user who isn’t signed in signs in first, then returns to the consent screen. The consent step expires after about 10 minutes.
- The consent screen names the assistant and lists what it can and can’t do. The user chooses Allow access or Cancel.
- Nylon checks the user’s seat and their organisation’s settings on the server before issuing a code. A user on a Starter seat sees Upgrade to Adviser; if an admin has turned connections off, the user is told to contact them. Either way, the request ends with
access_denied, and the user must connect again after the problem is fixed. - An unknown
client_idorredirect_urishows an error page and never redirects. Other errors redirect back witherrorandstate(RFC 6749 §4.1.2.1). See Errors. - The authorization code is single-use and expires after about 10 minutes.
6. Token request
Section titled “6. Token request”Send token requests form-encoded:
POST /oauth/token HTTP/1.1Host: app.usenylon.comContent-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=<code>&redirect_uri=<registered redirect URL>&client_id=<client_id>&code_verifier=<code_verifier>&resource=https%3A%2F%2Fmcp.usenylon.com%2Fmcp{ "access_token": "eyJ…", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "…", "scope": "openid profile email offline_access"}The response has no id_token, even when you request openid.
Resource indicators
Section titled “Resource indicators”Send resource=https://mcp.usenylon.com/mcp (RFC 8707) on the token and refresh requests. Nylon binds the access token’s audience to it there, and the MCP server rejects tokens issued for any other audience. A resource that Nylon doesn’t serve returns 400 invalid_target.
Tokens
Section titled “Tokens”| Token | Lifetime | Notes |
|---|---|---|
| Access token | 1 hour (expires_in: 3600) |
An RS256-signed JWT. The MCP server checks the signature against the issuer’s JWKS, plus issuer, audience and expiry, on every request. Treat it as opaque. |
| Refresh token | 30 days from issue | Issued when the client requests offline_access. |
| Authorization code | About 10 minutes | Single use. |
Refreshing
Section titled “Refreshing”POST /oauth/token HTTP/1.1Host: app.usenylon.comContent-Type: application/x-www-form-urlencoded
grant_type=refresh_token&refresh_token=<refresh_token>&client_id=<client_id>&resource=https%3A%2F%2Fmcp.usenylon.com%2Fmcp- Refresh tokens rotate on every use. The response carries a new refresh token with a fresh 30 days. Store it and discard the old one.
- Nylon detects reuse. If a client presents a refresh token that it has already used, Nylon revokes the whole token family and the user must sign in again. That includes retrying a refresh after a timeout with the same token, so don’t retry a refresh blindly.
- You can ask for a narrower
scopeon refresh. It applies to the new access token; the new refresh token keeps the original grant. You can’t widen the scope. - Nylon re-checks the user’s seat and their organisation’s settings on every refresh. If access has been removed, the refresh fails with
400 invalid_grant(“MCP access is no longer available for this account”), and Nylon doesn’t consume the refresh token. - The token endpoint is rate-limited per IP address. A
429withtemporarily_unavailableis temporary: back off and retry with the same refresh token. It isn’tinvalid_grant, so don’t send the user back through sign-in.
Scopes
Section titled “Scopes”| Scope | Purpose |
|---|---|
openid, profile, email |
Identify the user. |
offline_access |
Get a refresh token, so the user stays connected beyond an hour. |
There are no tool-level scopes today: every connected user can call both read-only tools.
Calling the server
Section titled “Calling the server”Send the access token as a bearer header on every request:
POST /mcp HTTP/1.1Host: mcp.usenylon.comAuthorization: Bearer <access_token>Content-Type: application/jsonAccept: application/json, text/event-streamSession handling is in Sessions and limits.