Getting started
Signing in
Three ways to give an agent, editor or script access to Slurry. The first two need no key copying: you approve a sign-in in the browser and the tool gets its own credential.
| Method | Best for | What the tool gets |
|---|---|---|
| OAuth for MCP clients | Claude Code, Cursor, VS Code, Claude.ai connectors | Access token (1 hour) and a rotating refresh token (60 days) |
| Device login | Agents, CLIs, CI set-up scripts, headless machines | Tokens, or one named account key for a single environment variable |
| Account keys | Anything that takes a static header | slurry_acct_live_... created on the API keys page |
Whichever you use, the credential acts as you in the organisation you pick, with the access you choose at consent: read only, or read and write. It never exceeds your role: viewers can only grant read, and if your role drops or you leave the organisation, the credential stops working at once. Everything you connect is listed under Connected apps on the API keys page, where you (or an owner or admin) can disconnect it.
OAuth for MCP clients
The Slurry MCP server implements the MCP authorization specification (2025-06-18). Give your client the URL https://api.slurry.io/mcp and nothing else: it discovers Slurry's authorization server, registers itself, opens a browser tab for you to approve, and handles tokens from then on.
Claude Code
claude mcp add --transport http slurry https://api.slurry.io/mcp
# then run /mcp in Claude Code and choose "Authenticate"Cursor
{
"mcpServers": {
"slurry": { "url": "https://api.slurry.io/mcp" }
}
}VS Code
{
"servers": {
"slurry": { "type": "http", "url": "https://api.slurry.io/mcp" }
}
}In Claude.ai, add a custom connector with the same URL. The consent screen shows the app's name (as the app reports it), where it will send you back to, and the access it asks for.
What happens underneath
For people writing their own client. Each step follows the RFC named.
# 1. an unauthenticated call is refused with a pointer to the metadata
curl -si https://api.slurry.io/mcp -X POST -H "content-type: application/json" -d '{}' | grep -i www-authenticate
# WWW-Authenticate: Bearer resource_metadata="https://api.slurry.io/.well-known/oauth-protected-resource"
# 2. protected resource metadata (RFC 9728) names the authorization server
curl -s https://api.slurry.io/.well-known/oauth-protected-resource
# 3. authorization server metadata (RFC 8414)
curl -s https://api.slurry.io/.well-known/oauth-authorization-server
# 4. dynamic client registration (RFC 7591): public clients only
curl -s https://api.slurry.io/oauth/register -H "content-type: application/json" \
-d '{"client_name":"My MCP client","redirect_uris":["http://127.0.0.1:33418/callback"]}'Then send the user to the authorization endpoint with PKCE (S256 only; plain is refused). The redirect URI must exactly match one you registered: https, http on localhost, 127.0.0.1 or [::1], or a desktop app scheme.
https://slurry.io/oauth/authorize?response_type=code
&client_id=slc_...
&redirect_uri=http://127.0.0.1:33418/callback
&code_challenge=<base64url(sha256(code_verifier))>
&code_challenge_method=S256
&state=<random>
&scope=simulations:read%20simulations:write
&resource=https%3A%2F%2Fapi.slurry.io%2FmcpSlurry redirects back with code, your state and iss. Codes are single use and expire after 60 seconds. Exchange the code:
curl -s https://api.slurry.io/oauth/token \
-d grant_type=authorization_code \
-d client_id=slc_... \
-d code="$CODE" \
-d redirect_uri=http://127.0.0.1:33418/callback \
-d code_verifier="$CODE_VERIFIER" \
-d resource=https://api.slurry.io/mcp- Access tokens (
slurry_oat_...) last one hour and work on the MCP server and the management API. - Refresh tokens (
slurry_ort_...) last 60 days and rotate on every use. Presenting a used refresh token again revokes the whole sign-in: treat that as a leak. - The
resourceparameter (RFC 8707) must behttps://api.slurry.io/mcpwhen you send it. - Registrations that never complete a sign-in are deleted after a day.
Device login for agents and scripts
The OAuth device authorization grant (RFC 8628) works anywhere a program can make HTTP requests and show you a short code, including headless machines. Use the public client id slurry-cli (no registration needed) and give it a client_name you will recognise on the consent screen.
curl -s https://api.slurry.io/oauth/device_authorization \
-d client_id=slurry-cli \
-d client_name="Nightly test runner" \
-d scope="simulations:read simulations:write"{
"device_code": "Jc5Wq...",
"user_code": "WDJB-MJHT",
"verification_uri": "https://slurry.io/device",
"verification_uri_complete": "https://slurry.io/device?user_code=WDJB-MJHT",
"expires_in": 600,
"interval": 5
}Open verification_uri_complete (or go to slurry.io/device and type the code), check the code matches, pick the organisation and access, and approve. Codes expire after ten minutes. Meanwhile, poll the token endpoint no faster than interval seconds:
curl -s https://api.slurry.io/oauth/token \
-d grant_type=urn:ietf:params:oauth:grant-type:device_code \
-d client_id=slurry-cli \
-d device_code="$DEVICE_CODE"| error | Meaning |
|---|---|
authorization_pending | Not approved yet: wait interval seconds and poll again. |
slow_down | Too fast: add 5 seconds to the interval for every later poll. |
access_denied | You pressed Deny. Stop polling. |
expired_token | Ten minutes passed. Start again. |
{
"access_token": "slurry_oat_...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "slurry_ort_...",
"scope": "simulations:read simulations:write"
}Ask for an account key instead
Many agents want one environment variable rather than tokens to refresh. Add account_key to the scope and the approved device receives a named, long-lived account key, exactly once. It appears in your key list and under Connected apps with the name the device gave, and you can revoke it there. Viewers cannot receive account keys.
curl -s https://api.slurry.io/oauth/device_authorization \
-d client_id=slurry-cli \
-d client_name="Codex on build box" \
-d scope="account_key simulations:read simulations:write"
# after approval, polling returns the key once:
# { "access_token": "slurry_acct_live_...", "account_key": "slurry_acct_live_...",
# "token_type": "Bearer", "scope": "account_key simulations:read simulations:write",
# "key_id": "...", "key_prefix": "slurry_acct_live_ab" }#!/usr/bin/env bash
# Sign in once, then keep the key in your secret store.
set -euo pipefail
start=$(curl -s https://api.slurry.io/oauth/device_authorization \
-d client_id=slurry-cli -d client_name="$(hostname) script" \
-d scope="account_key simulations:read simulations:write")
echo "Open $(echo "$start" | jq -r .verification_uri_complete) and approve code $(echo "$start" | jq -r .user_code)"
device=$(echo "$start" | jq -r .device_code); wait=$(echo "$start" | jq -r .interval)
while true; do
sleep "$wait"
out=$(curl -s https://api.slurry.io/oauth/token -d client_id=slurry-cli \
-d grant_type=urn:ietf:params:oauth:grant-type:device_code -d device_code="$device")
case $(echo "$out" | jq -r '.error // "ok"') in
ok) echo "$out" | jq -r .account_key; break ;;
authorization_pending) ;;
slow_down) wait=$((wait + 5)) ;;
*) echo "$out" >&2; exit 1 ;;
esac
doneUsing, refreshing and revoking tokens
curl https://api.slurry.io/v1/usage -H "Authorization: Bearer $ACCESS_TOKEN"curl -s https://api.slurry.io/oauth/token \
-d grant_type=refresh_token \
-d client_id=slurry-cli \
-d refresh_token="$REFRESH_TOKEN"curl -s https://api.slurry.io/oauth/revoke \
-d client_id=slurry-cli \
-d token="$REFRESH_TOKEN"Revoking a refresh token signs the app out completely; revoking an access token ends only that token. Disconnecting on the API keys page does the same as revoking the refresh token.
Account keys
Create a key on the API keys page and send it as Authorization: Bearer slurry_acct_live_.... Keys can be read only or read and write, can be locked to IP addresses and can expire. Use them for tools that only take a static header. See the management API and MCP server references.
Security notes
- Every code and token is stored as a SHA-256 hash; Slurry cannot show one again.
- Only public clients with PKCE are supported; Slurry never issues client secrets.
- The consent form is bound to your session and the exact request, and Slurry only ever redirects to a URI the app registered.
- Consents, token issue, refresh token reuse, device approvals and every disconnect are written to your audit log.
- Endpoints are rate limited per address. Never approve a code or consent screen you did not start yourself.