# `ConduitMcp.Client.OAuth.TokenStore.ETS`
[🔗](https://github.com/nyo16/conduit_mcp/blob/v0.11.0/lib/conduit_mcp/client/oauth/token_store/ets.ex#L1)

The default `ConduitMcp.Client.OAuth.TokenStore`: an in-memory table,
lost when the store stops.

When a client's OAuth options name no `:store`, the client's supervisor
starts one of these for that client; a `ConduitMcp.Client.Hub` starts one
for all its servers instead (`ConduitMcp.Client.Hub.Config.token_store/1`).
To share one store between standalone clients (several servers behind
the same authorization server, one user), start it yourself and name it
in each client:

    children = [
      {ConduitMcp.Client.OAuth.TokenStore.ETS, name: :mcp_tokens},
      {ConduitMcp.Client, name: :docs, transport: {..., auth: {:oauth, store:
        {ConduitMcp.Client.OAuth.TokenStore.ETS, name: :mcp_tokens}, ...}}}
    ]

`:name` may be any term; it is registered in `ConduitMcp.Client.Registry`.

## A protected table (OA-9)

Unlike the library's other tables (see `ConduitMcp.EtsOwner`, which makes
`:public` tables any process may write), this one is `:protected`: any
process may read it, but only the store process writes it. Reads (every
request's bearer lookup) go straight to ETS; writes (a new token, a
rotated refresh token, a registered client) are a call to the store
process. A bug or a compromised dependency elsewhere in the node can
therefore read tokens it is handed the table for, but cannot plant or
swap them.

The store process implements `format_status/1`, so a crash report never
shows a message carrying tokens.

# `start_link`

```elixir
@spec start_link(keyword()) :: GenServer.on_start()
```

Starts a store registered under `:name` (required).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
