# auth.md

Use this guide to authenticate an agent with the Landingana MCP at https://www.landingana.com/mcp. Landingana supports the AuthMD user-claimed `service_auth` flow. It does not accept anonymous registration or provider identity assertions. No usable API credential or site is created until the user signs in to Landingana and confirms the claim.

## Step 1 — Discover

If https://www.landingana.com/mcp returns `401 Unauthorized`, read its `WWW-Authenticate` header. Its `resource_metadata` value points to the protected resource metadata:

- Protected resource metadata: https://www.landingana.com/.well-known/oauth-protected-resource
- Authorization server metadata: https://www.landingana.com/.well-known/oauth-authorization-server

The protected resource metadata names the authorization server. The authorization server metadata advertises this guide in `agent_auth.skill` and provides the registration, token, and revocation endpoints. Treat those JSON documents as the machine-readable source of truth.

## Step 2 — Pick a method

Use `service_auth`. Landingana does not support `anonymous` or incoming `identity_assertion` registration. Ask the user for the email address they use or want to use for Landingana, unless it is already available in the task context.

Scopes: `sites:read sites:write analytics:read`.

## Step 3 — Register

```http
POST https://www.landingana.com/agent/identity
Content-Type: application/json

{"type":"service_auth","login_hint":"user@example.com"}
```

Example response shape:

```json
{
  "registration_id": "REGISTRATION_ID",
  "registration_type": "service_auth",
  "claim_url": "https://www.landingana.com/agent/identity/claim",
  "claim_token": "CLAIM_TOKEN",
  "claim_token_expires": "ISO_8601_TIMESTAMP",
  "post_claim_scopes": ["sites:read", "sites:write", "analytics:read"],
  "claim": {
    "user_code": "123456",
    "verification_uri": "https://www.landingana.com/claim?claim_attempt_token=CLAIM_ATTEMPT_TOKEN",
    "expires_in": 600,
    "interval": 5
  }
}
```

Treat `claim_token` as private bearer material. Never log it, render it, or show it to the user: possession lets the agent poll and retrieve credentials after approval. Surface only `claim.verification_uri` and `claim.user_code` to the intended user.

## Step 4 — Claim ceremony

Use browser or computer control to open `verification_uri` when that capability is available. Pause whenever Landingana requires the user's credentials, passkey, magic link, one-time code, or explicit approval. Never ask the user to send account secrets through chat and never enter credentials on their behalf.

The agent already received `user_code` from Landingana; it is claim material, not an account credential. After the user has completed authentication, reviewed the Landingana claim screen, and explicitly approved continuing, the agent may enter that already-known six-digit code on Landingana. If browser control is unavailable, surface `verification_uri` and `user_code` together and let the user complete the claim on Landingana. Do not ask the user to send the code back through the agent.

Poll no faster than `claim.interval` seconds while the user completes that step:

```http
POST https://www.landingana.com/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=CLAIM_TOKEN
```

`authorization_pending` means the user has not confirmed. `slow_down` means back off. On a 429 response, honor `Retry-After` before polling again. If the ten-minute attempt expires while the outer claim is still active, POST JSON `{"claim_token":"...","email":"user@example.com"}` to `https://www.landingana.com/agent/identity/claim`. The success response returns a new `verification_uri` and `user_code` under `claim_attempt`. Discard the expired URL and code, surface the new pair, and repeat Step 4; continue polling with the private outer `claim_token`.

On success, keep the returned `access_token` and `identity_assertion` private. Send the access token as `Authorization: Bearer ACCESS_TOKEN` to https://www.landingana.com/mcp.

## Step 5 — Use and renew access

Connect to https://www.landingana.com/mcp with the bearer token. Use `setup_site` to create, recover, or reuse the target site and receive its exact installation snippet. Then return to the target repository and install the tracker with the privacy controls documented in `https://www.landingana.com/llms.txt`. If deployment and a live visit are authorized and in scope, trigger an intended event on the registered origin and use `list_sites` to confirm that `last_event_at` advanced. Treat that as integration evidence rather than proof of one specific event on a busy site. A rendered tag or HTTP `202` alone is not storage proof; report runtime verification as incomplete when a live check is unavailable. Use `read_analytics` for aggregate results.

Access tokens last one hour. Until the identity assertion expires, exchange it for another access token:

```http
POST https://www.landingana.com/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=IDENTITY_ASSERTION&resource=https://www.landingana.com/mcp
```

This renews access from the identity assertion. It is not a `refresh_token` flow, and Landingana does not issue a refresh token.

## Errors and recovery

- `authorization_pending`: keep polling at the advertised interval.
- `slow_down`: increase the delay before the next poll.
- HTTP 429 or `temporarily_unavailable`: honor `Retry-After` and retry later.
- Expired claim attempt: while the outer claim is active, POST the JSON body `{"claim_token":"...","email":"user@example.com"}` to https://www.landingana.com/agent/identity/claim. Discard the expired URL and code, then repeat Step 4 with the new `claim_attempt.verification_uri` and `claim_attempt.user_code`.
- `invalid_grant` or expired identity assertion: discard the expired credentials and restart at service-auth registration.

Landingana does not issue a `refresh_token`.

## Revocation

Revoke an access token with `POST https://www.landingana.com/oauth2/revoke` and form body `token=ACCESS_TOKEN&token_type_hint=access_token`. Revocation is idempotent. The user can revoke the entire claimed agent registration, including all of its tokens and identity assertions, from the Landingana dashboard.

For installation and analytics guidance, read https://www.landingana.com/llms.txt. Landingana does not expose documentation as an MCP tool. Pricing: https://www.landingana.com/#pricing.
