# MCP bridge lifecycle -- enable, disable, revoke

Fetch this doctrine when the user mentions MCP bridge / bridge token /
bridge revoked / enable bridge / disable bridge / mcp credentials.

## Bridge state

A bridge can be:
- `discovered + enabled + auth_loaded` -- ready, brain may call.
- `discovered + enabled + auth_missing` -- brain must point user
  at `yf keys set <slot>` first.
- `discovered + disabled` -- F101 slice 5 toggle, brain must NOT
  call. If user asks, explain it is off + offer
  `yf mcp enable <id>`.
- `unreachable` -- transient; brain must NOT loop retry.

## Enable / disable

```
yf mcp ls               list known bridges + state
yf mcp enable <id>      flip enabled=true (per-user persistent)
yf mcp disable <id>     flip enabled=false
yf mcp inspect <id>     full state dump (endpoint, token slot, last-error)
```

The flip is per-user, persists across `yf chat` restarts. Disabled
bridges are FILTERED OUT of the manifest stub completely -- the
brain physically cannot see their `yujin.mcp.*` verbs (Invariant 1
extended).

## Credentials

Bridges that require auth declare a Vault slot (e.g. `mcp_crm_token`).
The brain NEVER receives the token in chat -- it lives in
CredentialVault, fetched + injected as `Authorization: Bearer <token>`
at invoke time.

If the brain calls `yujin.mcp.invoke-tool` and gets back
`http_status` with HTTP 401, the token was rotated or revoked:

1. **Do NOT retry.** A second call with the same headers will fail
   the same way + waste tokens.
2. **Tell the user** to refresh the credential:
   `yf keys set <slot_name>`.
3. **Wait** for the user to confirm before retrying.

## Token revocation (user-initiated)

When the user wants to revoke a bridge token:
```
yf keys delete <slot>
```
The Vault drops the encrypted blob. The next invoke will surface
the auth-missing state, not 401.

## Multi-bridge auth

Each bridge has its own slot. `yf keys ls` shows all slots; the
brain MAY suggest revoking unused ones during cleanup.

## When to suggest disabling vs revoking

- **Disable** when the bridge is a known good but temporarily
  unwanted (e.g. user wants to pause CRM access for a week).
- **Revoke (delete creds)** when the token is leaked or stale.
- **Both** when the bridge is being retired entirely.

## What not to do

- Don't try to call a disabled bridge's tools -- they are
  filtered from the manifest, the call will fail with
  `unknown verb`.
- Don't paste tokens into chat. Ever. Even for "convenience".
- Don't suggest hardcoding a token into the app source as a
  fallback. Vault is the only correct location.
