ExMCP.SpecSync.GitHubClient (ex_mcp v0.9.2)

View Source

GitHub API client for fetching MCP specification files.

Uses :httpc (Erlang's built-in HTTP client) following the same pattern as ExMCP.Authorization.HTTPClient. Supports GitHub token authentication for higher rate limits.

Summary

Functions

Discovers available specification versions from the GitHub repository.

Fetches a raw file from the repository.

Extracts the ETag value from response headers.

Lists files in a GitHub directory recursively using the Contents API.

Returns rate limit info from the last API response headers.

Functions

discover_versions(opts \\ [])

@spec discover_versions(keyword()) :: {:ok, [String.t()]} | {:error, term()}

Discovers available specification versions from the GitHub repository.

Queries the GitHub Contents API for directories under schema/ that match the date-based version pattern (YYYY-MM-DD).

Returns {:ok, versions} with a sorted list of version strings, or {:error, reason}.

fetch_raw_file(path, opts \\ [])

@spec fetch_raw_file(
  String.t(),
  keyword()
) ::
  {:ok, {binary(), list()}}
  | {:ok, :not_modified}
  | {:ok, :not_found}
  | {:error, term()}

Fetches a raw file from the repository.

Uses raw.githubusercontent.com which does NOT count against the GitHub API rate limit. Supports conditional requests via ETag/If-None-Match.

Returns:

  • {:ok, {content, headers}} on success (200)
  • {:ok, :not_modified} when the file hasn't changed (304)
  • {:ok, :not_found} when the file doesn't exist (404)
  • {:error, reason} on failure

get_etag(headers)

@spec get_etag(list()) :: String.t() | nil

Extracts the ETag value from response headers.

list_directory(dir_path, opts \\ [])

@spec list_directory(
  String.t(),
  keyword()
) :: {:ok, [String.t()]} | {:error, term()}

Lists files in a GitHub directory recursively using the Contents API.

Returns {:ok, paths} with a list of file paths relative to the repo root.

rate_limit_info(headers)

@spec rate_limit_info(list()) :: map()

Returns rate limit info from the last API response headers.