# OAuth setup for an existing Nettipoika site

Environment: `prod`. Resource: `https://sivusto.nettipoika.fi/mcp`.

1. Read `GET https://sivusto.nettipoika.fi/api/v1/oauth-clients`. Choose the exact
   client surface: `openai-codex` is Codex CLI; `openai-codex-desktop` is Codex
   desktop. An absent key is unavailable in this installation. The returned
   `client_id` is the registered public OAuth ID; the application key is not.
2. Create the access request using independent local proof challenges and only
   the operational scopes the task needs. A static Hello World needs
   `site:read`, `site:write`, `site:deploy`. Scope arrays are sets; compare their
   contents independently of order. Duplicate or unknown scopes are rejected.
3. Present the returned approval URL. The owner reviews the site, application
   and scopes, and explicitly confirms any replacement of an existing link.
4. Poll using the saved proofs and `interval_seconds`. `approved` records the
   human decision. Wait for `access.state=installed` and
   `access.next_action=start_oauth`. `installed` records link installation,
   not a completed OAuth login or a guarantee of continuing authorization.
   For `wait`, retain this request and poll; for `start_new_request`, obtain
   fresh human approval; for `contact_support`, stop. Never broaden scopes or
   start another request to bypass an unfinished delivery.

## Hosted chat apps

Claude (web, desktop and iOS through claude.ai) and ChatGPT on the web connect
with the MCP URL alone; the issuer advertises client ID metadata documents and
RFC 9207 issuer identification. Do not create an access request for them. The
person adds `https://sivusto.nettipoika.fi/mcp` in the app's own settings, signs in
again and approves the websites on Nettipoika's page. Setup guides:
`https://sivusto.nettipoika.fi/connect/claude` and `https://sivusto.nettipoika.fi/connect/chatgpt`.
Native ChatGPT mobile apps do not support custom MCP connections.

## Dynamic registration and Mistral web

When the authorization server advertises `registration_endpoint`, a compatible
client can register itself with RFC 7591 using only the MCP URL. Prefer client
ID metadata documents when supported; DCR is an additional compatibility path.
Registration creates no website access. Sign in and explicitly approve the
requested permissions for all current and future websites in the account.
Check the unverified application name, registered callback host and connection
identifier. Connections can be revoked independently in the owner's dashboard.

Registration is available in every Nettipoika environment. Mistral Vibe web
(Work → Context → Connectors, Free plan,
Orion 1.1.3 build 152, 2026-10-08) passed automatic registration, account consent,
two-site inspection, a static edit and publication, exact undo, automatic
refresh, owner revocation and reconnect on DEV with MCP `2025-11-25`.
Native Mistral mobile apps and other workflows are untested.

In Mistral, add a custom connector with the MCP URL
(`https://sivusto.nettipoika.fi/mcp`). Leave Advanced OAuth
Settings off: no manually issued client ID or secret is required. After owner
revocation, Mistral may show a generic 502 and retain its "Valid" label while
calls fail. Use the connection's **More actions → Reconnect**, sign in and
approve again. Check access with a fresh site read; a vendor's status label
alone does not establish access.

## Codex CLI and desktop

Use separate local server names, for example `nettipoika-cli-dev` and
`nettipoika-desktop-dev`. Configure only the intended client's entry. Preserve
unrelated configuration. Set the URL and `oauth.client_id` from discovery and
the exact approved scopes explicitly. The registered loopback callback is
`http://127.0.0.1/callback`; the OAuth client supplies its local listener port.

For a Hello World approval, the native configuration is:

```toml
# Top-level setting: require the operating-system credential store.
mcp_oauth_credentials_store = "keyring"

[mcp_servers.nettipoika-cli-dev]
url = "https://sivusto.nettipoika.fi/mcp"
oauth_resource = "https://sivusto.nettipoika.fi/mcp"
scopes = ["site:read", "site:write", "site:deploy", "offline_access"]

[mcp_servers.nettipoika-cli-dev.oauth]
client_id = "REPLACE_WITH_DISCOVERED_CLIENT_ID"
callback_url = "http://127.0.0.1/callback"
```

Use the desktop server name and its separately discovered client ID for desktop.
Use the installed client's supported configuration/import interface to save the
entry **before** login. Do not use `codex mcp add`'s immediate automatic OAuth
login for this workflow. Then explicitly request the approved scope set:

```sh
codex mcp login nettipoika-cli-dev --scopes site:read,site:write,site:deploy,offline_access
```

Run the command with the intended client's binary and configuration context.
For desktop, use its bundled CLI and the desktop entry. After scope replacement,
run `codex mcp logout nettipoika-cli-dev` for only that entry, then log in
again explicitly (use the desktop name for desktop). If protected credential
storage is unavailable, stop and fix it before login.

`offline_access` permits credential renewal; it adds no site operation scopes.
Logto 1.43.0 requires `prompt=consent` to retain it. Before opening the native
client's authorization URL, set that parameter locally while preserving state,
PKCE, resource, client ID and callback exactly. Do not put the URL, codes, proofs
or tokens into chat, logs or evidence. The owner completes sign-in and consent;
the native client receives and securely stores rotating credentials directly.

On `invalid_scope`, cancellation, unexpected scopes or client mismatch, stop.
Do not retry with all advertised scopes, accept an automatic broader fallback,
switch application identity or substitute operator credentials. Metadata's
`scopes_supported` lists server capabilities, not the user's approved scopes.
Nettipoika independently denies unapproved scopes at issuance and on every call.

Refresh must retain the original grant's scope ceiling. An expired/revoked link
requires fresh owner authorization. Replacing a link invalidates its old access
tokens; it does not claim to delete provider-owned refresh families.

## Compatibility

CLI 0.154.0 has dated earlier product-workflow evidence. This new minimal-scope
and replacement workflow requires its own acceptance. Desktop 26.915.31945 with
bundled CLI 0.155.0-alpha.9.2 is a separate acceptance target, not a certified
surface based on CLI evidence. A version that broadens an explicit scope
request fails this workflow. Consult `https://sivusto.nettipoika.fi/for-agents#compatibility`
for dated results; do not transfer compatibility between versions or surfaces.
