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

The canonical resource URI of an MCP server: the value sent as the RFC 8707
`resource` parameter in authorization and token requests, compared exactly
against Protected Resource Metadata `resource`, and used in token-store keys.

    iex> ConduitMcp.Client.OAuth.Resource.canonical("HTTPS://MCP.Example.com:443/mcp/#frag")
    {:ok, "https://mcp.example.com/mcp"}

`canonical/2` applies the MCP authorization spec's rules (*Canonical Server
URI*):

  * the scheme and host are lowercased;
  * a default port (`443` for `https`, `80` for `http`) is dropped, any other
    port is kept;
  * the fragment is removed;
  * trailing slashes are removed (`https://ex.com/` → `https://ex.com`); the
    rest of the path and any query are kept byte for byte (percent-encoding
    is not normalized);
  * the scheme must be `https`. Plain `http` is accepted only for a loopback
    host (`localhost`, `127.0.0.0/8`, `::1`) and only with
    `allow_insecure: true`, for local development and tests;
  * a URL without a host or with user info is refused.

# `canonical`

```elixir
@spec canonical(String.t(), keyword()) ::
  {:ok, String.t()} | {:error, ConduitMcp.Client.OAuth.Error.t()}
```

Returns the canonical form of `url`.

## Options

  * `:allow_insecure` - admit `http` on a loopback host (default `false`).

Errors: `:invalid_url` (unparsable, no host, user info) and `:insecure_url`.

---

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