ExMCP.Authorization.ClientIdMetadata (ex_mcp v1.0.0-rc.8)

Copy Markdown View Source

OAuth Client ID Metadata Document support for MCP authorization.

Implements the OAuth Client ID Metadata Document mechanism where the client's client_id is a URL that resolves to a JSON document containing the client's OAuth metadata.

This enables dynamic client registration-like behavior without requiring a registration endpoint.

Client IDs are exact HTTPS URLs with a non-root path. The document at that URL must repeat the exact client ID and provide client_name and redirect_uris. Authorization servers advertise support with client_id_metadata_document_supported: true.

Summary

Functions

Builds a client metadata document for this application.

Fetches and parses client metadata from a client_id URL.

Returns whether authorization-server metadata advertises CIMD support.

Validates client metadata structure.

Validates the URL form required for a CIMD client identifier.

Types

client_metadata()

@type client_metadata() :: %{required(String.t()) => term()}

Functions

build_metadata(opts \\ [])

@spec build_metadata(keyword()) :: client_metadata()

Builds a client metadata document for this application.

Useful for MCP clients that want to publish their own metadata.

fetch(client_id_url, opts \\ [])

@spec fetch(
  String.t(),
  keyword()
) :: {:ok, client_metadata()} | {:error, term()}

Fetches and parses client metadata from a client_id URL.

Parameters

  • client_id_url - The client_id URL to fetch metadata from
  • opts - Hardened metadata-fetch options. A custom :http_client must implement get(uri, approved_address, opts) and connect to the supplied address while preserving uri.host for TLS and HTTP host validation.

Returns

  • {:ok, metadata} - Successfully fetched client metadata
  • {:error, reason} - Failed to fetch or parse metadata

The default client permits only HTTPS public addresses, revalidates and pins every redirect hop, bounds time and response bytes, and sends no credentials.

supported?(metadata)

@spec supported?(map()) :: boolean()

Returns whether authorization-server metadata advertises CIMD support.

validate(metadata, expected_client_id)

@spec validate(client_metadata(), String.t()) :: :ok | {:error, term()}

Validates client metadata structure.

Required Fields

  • client_id - Must match the URL it was fetched from
  • client_name - Human-readable name for the client
  • redirect_uris - List of allowed redirect URIs

Optional Fields

  • client_uri - URL of the client's home page
  • logo_uri - URL of the client's logo
  • scope - Space-separated list of requested scopes
  • contacts - List of contact emails
  • tos_uri - Terms of service URL
  • policy_uri - Privacy policy URL

validate_url(client_id_url)

@spec validate_url(String.t()) :: :ok | {:error, term()}

Validates the URL form required for a CIMD client identifier.