Connect a client
askrelay is a remote MCP server with an embedded OAuth 2.1 authorization server, so browser and terminal AI clients connect with no install beyond the relay URL. Authentication is your device credential (from enrollment); there are no passwords and no signup.
The flow, once
Section titled “The flow, once”Every client does the same dance:
-
You add the relay’s base URL as a custom MCP server / connector.
-
The client fetches the relay’s OAuth metadata from
/.well-known/oauth-authorization-server— issuer, authorization endpoint, token endpoint, JWKS, registration endpoint. The issuer is the relay’s base URL. -
The client registers itself: Dynamic Client Registration at
POST /oauth/register(RFC 7591), or a Client ID Metadata Document. -
The client opens the relay’s login page in a browser.
-
You paste your device credential. The relay verifies it and then — before minting anything — re-checks that the device is still active.
-
The client exchanges its PKCE-bound code for an access token and the askrelay tools appear.
What the relay advertises
Section titled “What the relay advertises”The metadata document is deliberately narrow:
response_types—code.grant_types—authorization_codeandrefresh_token.code_challenge_methods—S256only.plainis never offered; the downgrade is refused rather than advertised and ignored.token_endpoint_auth_methods—none. Clients are public, and PKCE is the client authentication.client_id_metadata_document_supported—true.
Protected-resource metadata (RFC 9728) is served separately at
/.well-known/oauth-protected-resource. It is what a client reads to find the
authorization server, and it is where a failed request points: a bad or missing
bearer token gets a 401 plus a WWW-Authenticate challenge naming the PRM
URL, so a client that guessed wrong can discover its way back.
Credentials, tokens, revocation
Section titled “Credentials, tokens, revocation”Three lifetimes, and they are not the same number:
- The device credential comes out of enrollment and is long-lived — 365 days. It is not the kill switch.
- The access token lives exactly 1h. It is an EdDSA-signed JWT bound to a single audience, the relay’s base URL.
- Revocation is immediate, because the login step re-reads the device from the store on every authorization. Revoke the device and the next code mint fails, whatever the credential’s expiry says.
A revoked device and a wrong credential are refused with the same opaque message — “that device credential is not valid” — so the login page is not an oracle for which devices exist.
After you connect
Section titled “After you connect”The MCP endpoint is POST /mcp: stateless Streamable HTTP with JSON
responses, protocol 2025-11-25, request bodies capped at 128 KiB. There is
no session to resume and no server-initiated stream — every call is
client-initiated.
Nine tools appear: check_inbox, get_thread, wait_for_activity,
approve_message, decline_message, set_thread_grant, send_message,
approve_reply, and discard_reply. They are the same nine for every client.
wait_for_activity is capped per client
Section titled “wait_for_activity is capped per client”wait_for_activity blocks until something needs you, or until its timeout
expires — and that timeout is clamped to a ceiling chosen from the client
type the authorization server stamped on your token. Ask for longer and you
get the cap.
| Client type on the token | Ceiling |
|---|---|
claude.ai, claude-desktop |
240s |
claude-code-remote |
25 min |
| anything else — including ChatGPT | 45s |
The last row is the default branch, not an oversight: an unrecognized client gets the safe 45s. It is the difference you will feel most between clients.
Unverified
The 240s and 45s figures are the shipped values. The 25-minute one is a placeholder the source itself flags — treat it as subject to change.
Could not verify: the 25-minute `claude-code-remote` ceiling is marked provisional in the source, pending spike S-02.
Per-client setup
Section titled “Per-client setup”Unverified
The OAuth server is implemented and unit-tested — the mechanism above is real. What is not confirmable from askrelay is the click path through each vendor’s product. The steps below are the current shape and a starting point; expect wording differences per vendor, and trust the flow, not the labels.
Could not verify: the CLI invocation and the per-vendor menu paths are vendor UI, not askrelay source; end-to-end validation against each live vendor connector is scheduled as spike S-04, which has not run.
Claude Code
Section titled “Claude Code”Claude Code connects to remote HTTP MCP servers and handles OAuth for you:
claude mcp add --transport http askrelay https://relay.example.com/mcpOn first use it opens the authorization page; paste your device credential. From then on the ten tools are available in the session.
claude.ai (and Claude Desktop)
Section titled “claude.ai (and Claude Desktop)”Settings → Connectors → Add custom connector → enter the relay URL
(https://relay.example.com/mcp). Claude walks the OAuth flow (Dynamic Client
Registration), shows the relay login page, and you paste your device credential.
Tools appear as a connected connector.
ChatGPT
Section titled “ChatGPT”Add the relay as a connector / MCP server in ChatGPT’s connector settings
(Streamable HTTP). ChatGPT authenticates via a Client ID Metadata Document.
Complete the OAuth login by pasting your device credential. Note the 45s
wait_for_activity ceiling above — it applies here.
Every client is pull, today
Section titled “Every client is pull, today”What each client can do converges on client-initiated tool calls. No client
gets server push right now — not even Claude Code. Every side polls
check_inbox, or parks on wait_for_activity until its cap expires.
Built, not yet wired · WP-10
Push is live as a desktop notification: run askrelay daemon and it holds a
socket to the relay, raising a notification the moment mail arrives. What is not
built is push into the session — channels and an in-terminal approval prompt
are WP-10, deferred until real use says they are needed. So today you are
notified outside your AI client, then approve inside it.
See Concepts for the delivery model and what the approval gate changes.
Verified against askrelay 2e019ea on . Anything newer than that commit is not reflected here.

