---
title: Device login
description: The RFC 8628 device-authorization flow behind the `login` command, endpoint by endpoint.
---

# Device login

`shebang-mcp login` runs an
[RFC 8628](https://www.rfc-editor.org/rfc/rfc8628) device-authorization
flow — no password ever touches your terminal or the CLI's config file.

## What you see

```
$ npx -y shebang-mcp login

  Confirm this code in your browser:

    x 7 w y 6 x 3 a

  https://dash.shebang.pro/authorize-agent?user_code=x7wy6x3a

Opening your browser… (if nothing opens, visit the URL above)
Waiting for approval....
Logged in. Key: shb_examplexxxxxxxx… (master)
```

Sign in on that page if you aren't already, check that the code and
device name match what your terminal printed, and click **Approve**. The
CLI has been polling in the background the whole time; once approved, it
writes the issued **master** key locally and you're done.

## The two endpoints

Both accept form-encoded or JSON bodies:

- `POST /api/agent-login/device_authorization` — body `{client_name}`
  (optional, defaults to `"agent"`). Returns `{device_code, user_code,
  verification_uri, verification_uri_complete, expires_in: 600,
  interval: 3}`.
- `POST /api/agent-login/token` — body `{grant_type:
  "urn:ietf:params:oauth:grant-type:device_code", device_code}`. Returns
  `200 {access_token, token_type: "shb", scope: "master", expires_in:
  null}` once approved, or a `400` with `{error}` — `authorization_pending`
  while waiting, `slow_down` (with a larger `interval`) if you poll too
  fast, `access_denied`, `expired_token`, or `invalid_grant` once the
  code has already been claimed.

The CLI honors the server's `interval` and backs off further on
`slow_down`, capped at 30 seconds between polls. The device code expires
after 10 minutes whether or not it's ever approved.

## Next

[Hosted MCP](/getting-started/hosted-mcp-oauth) — skip local
installation and call shebang over HTTPS instead.
