Sign in with Starlight
Your app can let a Starlight member sign in with their Starlight account, choose what to share with your app, and then read or change their Starlight data through the Starlight MCP server. This guide takes you from a new app to your first call.
Development apps only, for now
Every app starts in development. A development app signs in its owner and up to 10 test accounts that you list, and nobody else. Production client ids, which let any Starlight member sign in, are not available yet. Apps are public clients: they prove themselves with PKCE and hold no client secret.
1. Register your app
Open the console and register an app. You get a client id that starts with app_. You can change everything else later.
- The app name is what members see on the consent page, so use the name they know your app by.
- Redirect URIs are where Starlight sends the member back after they choose. List each one exactly, up to 10. Each must use https. For local development you can also use http with a loopback address: localhost, 127.0.0.1 or [::1]. A loopback redirect URI with no port, such as
http://localhost, accepts any port on the same path, so a command line app can listen on whichever port is free. - Test accounts are the GitHub accounts, besides your own, that may sign in to a development app. Enter each one's numeric id, up to 10.
- Turn on each permission your app will ask for. A sign-in can ask only for permissions the app has turned on.
2. Choose permissions
Each permission is one scope. Read only scopes let your app see data. Write scopes let it change data, and some write scopes can spend the member's Starlight credits. The member sees each one on the consent page, marked the same way, and can untick any of them.
| Scope | Kind | What it allows | Tools |
|---|---|---|---|
account:read | Read only | See your Starlight credits balance and whether new work can start. | get_account |
sluice:read | Read only | See your Sluice recordings and what each has cost. | list_recordings, get_recording, get_recording_costs, get_recording_timeline, get_recording_pictures |
scan:read | Read only | See your Scan items. | |
iris:read | Read only | See your Iris items and their pictures. | list_iris_items, get_iris_item, find_similar_iris_items, find_iris_words |
cadence:read | Read only | See your Cadence tasks, projects and plan. | get_plan, list_tasks, get_task, list_projects, list_events, list_repeating_tasks, get_cadence_settings |
cadence:write | Write | Add, change, complete and delete your Cadence tasks, projects, events and hours. Can spend Starlight credits. | save_task, update_tasks, complete_task, move_task, save_project, create_project_plan, save_event, save_repeating_task, save_schedule, update_cadence_settings, delete_cadence_item |
The console always includes openid. A sign-in from a registered app drops it today: your app gets an access token for the MCP server and no ID token.
3. Send the member to sign in
Sign-in is the OAuth 2.1 authorization code flow with PKCE. Make a random code verifier of 43 to 128 characters, hash it with SHA-256, encode the hash as base64url without padding, and send that as the code challenge. Keep the verifier and a random state value for the next step.
Open the authorization address in the member's browser. Replace each placeholder in capitals with your own value, and URL-encode each value:
https://account.starlightglobal.industries/api/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=YOUR_SCOPES&resource=https%3A%2F%2Fmcp.starlightglobal.industries%2Fmcp&state=STATE&code_challenge=CODE_CHALLENGE&code_challenge_method=S256
| Parameter | Value |
|---|---|
response_type | codeAlways code. |
client_id | YOUR_CLIENT_IDYour app's client id. |
redirect_uri | YOUR_REDIRECT_URIOne of your redirect URIs. For a loopback URI registered with no port, add the port you listen on. |
scope | YOUR_SCOPESThe scopes you want, separated by spaces. Leave it out to ask for every scope your app has turned on. |
resource | https://mcp.starlightglobal.industries/mcpThe MCP server's address, which the access token will be for. |
state | STATEA random value. Check that the same value comes back. |
code_challenge | CODE_CHALLENGEThe base64url SHA-256 hash of your code verifier. |
code_challenge_method | S256Always S256. |
If the member is signed out, they sign in first. Then they see your app's name, what it asks for, and how long to allow it: 30, 90 or 365 days.
4. Take the member back
Starlight sends the browser to your redirect URI with code, your state and iss. Check that the state is yours and that iss is the Starlight account site. If the member cancels, or the request was wrong, you get error and error_description instead of a code. The code lasts five minutes and works once.
5. Exchange the code for tokens
Post the code to the token endpoint as a form, with the same redirect URI you sent and the code verifier:
curl -X POST https://account.starlightglobal.industries/api/oauth/token \
-d grant_type=authorization_code \
-d code=CODE \
-d redirect_uri=YOUR_REDIRECT_URI \
-d code_verifier=CODE_VERIFIER \
-d client_id=YOUR_CLIENT_ID
The answer holds access_token, token_type (Bearer), expires_in in seconds, refresh_token and scope, the scopes the member actually allowed. That may be fewer than you asked for, so check it before you call a tool.
An access token lasts an hour, and never longer than the member's grant. Get a new one by posting grant_type=refresh_token, the refresh token and your client id to the same endpoint. Each refresh returns a new refresh token, so keep only the newest: sending one that was already used ends the member's grant, and they have to sign in again. A refresh token lasts 30 days if it is not used, and never longer than the grant.
To sign the member out of your app, post the refresh token and your client id to the revocation endpoint. The member can also disconnect your app at any time from their Starlight account.
6. Call the Starlight MCP server
Send the access token as a bearer token with each JSON-RPC request to the MCP server. The server keeps no session, so a single tools/call is enough:
curl -X POST https://mcp.starlightglobal.industries/mcp \
-H 'authorization: Bearer ACCESS_TOKEN' \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_tasks","arguments":{"status":"open"}}}'
The answer is plain JSON. A tool's result holds readable text in content, and many tools also return structuredContent. Each tool, and the scope it needs, is listed on the MCP server page.
Cadence tools work only for members who have turned on AI assistant access in Cadence (Account, AI assistants) on a device that syncs. Without it, the tool answers with a result that says so.
When something goes wrong
| What you see | Why |
|---|---|
| This app is still being built | The member is not the app's owner or one of its test accounts. |
| This app asked to send you somewhere it did not register | The redirect URI is not on the app's list. Starlight shows this page and never sends the member there. |
error=invalid_scope on your redirect URI | The app asked for a scope it has not turned on in the console. |
error=access_denied on your redirect URI | The member chose Cancel or unticked every permission. |
invalid_grant from the token endpoint | The code was already used, has expired, or the redirect URI or code verifier does not match. |
| HTTP 401 from the MCP server | The access token is missing, expired or not valid. Refresh it, or sign the member in again. |
HTTP 403 with insufficient_scope | The member did not allow the scope this tool needs. Ask for it in a new sign-in. |
A complete example
This command line app, in one file with no dependencies, does every step above with cadence:read and prints the member's open Cadence tasks. It needs Node 18 or later. Turn on cadence:read for your app and add http://localhost as a redirect URI, then run:
node cadence-read.mjs YOUR_CLIENT_ID
Endpoints
- Authorization:
https://account.starlightglobal.industries/api/oauth/authorize - Token:
https://account.starlightglobal.industries/api/oauth/token - Revocation:
https://account.starlightglobal.industries/api/oauth/revoke - Authorization server metadata:
https://account.starlightglobal.industries/.well-known/oauth-authorization-server - MCP server:
https://mcp.starlightglobal.industries/mcp