What the install publishes, without a key, about its public API: the guide
GET /mcp, the API catalog /.well-known/api-catalog (RFC 9727), the Link
headers that point to them and the API section of /llms.txt.
Everything here is built from PhoenixKit.API.Registry.visible_tools/2 of
the public audience on every request (nothing is cached), so a module
that is switched off or a tool hidden in Settings -> API is gone from the
documents at once. Nothing here names the admin API: a document served
without a key never mentions an admin path, tool, scope or permission.
One predicate
check/1 and visible?/1 decide whether anything is published at all, and
every document and header of this module asks it:
- the public API switch is on (
PhoenixKit.API.Config.public_enabled?/0); - the website password gate does not hide the site from this client
(
PhoenixKit.API.Auth.gated?/2): a gated pre-production site publishes nothing it would not serve through the API itself; - at least one public tool is visible. The list is returned, so one request walks the registry once.
Which host a document names
The Host header is never trusted by itself (PhoenixKit.API.RequestContext
defaults its :hosts to the request host, so "the host is one of the hosts"
proves nothing on a default install). origin/1 uses the request host only
when it is a well-formed hostname and one of the hosts
PhoenixKit.API.MCP.Origin.known_hosts/1 lists (the canonical host and the
hosts the :api_request_context hook explicitly returns); else it uses
PhoenixKit.API.MCP.Origin.canonical_origin/0. Never
PhoenixKit.Utils.Routes.base_url/0, which reads the database uncached.
The scheme and the port never come from the request either, whatever its
Host port or X-Forwarded-Proto say: the canonical host is named by
canonical_origin/0 as it is, any other known host takes the canonical
scheme and the canonical port (none when that is the scheme's default).
The documents are cached publicly, so a request must not shape them.
The API and the guide live under the kit's URL prefix (PhoenixKit.Utils.Routes.path/1);
/llms.txt and /.well-known/* are origin-root URLs.
Summary
Functions
The API catalog (RFC 9727 linkset) naming the origin's public API.
The URL of the public REST API under origin.
The Cache-Control of a published document.
The Content-Type of the API catalog.
The Link header value that points to the API catalog.
The URL of the API catalog: at the origin root, whatever the URL prefix.
Whether anything is published for conn, with the public tools that make it
so. The three parts are checked in the order of the moduledoc, cheapest first.
The content of the guide for conn, as one map the two renderers
(PhoenixKit.API.PublicDiscovery.GuideHTML, PhoenixKit.API.PublicDiscovery.GuideMarkdown)
turn into text. tools is the list check/1 returned.
The URL of the guide under origin.
The language a page for context is written in: the domain's language
reduced to a locale PhoenixKitWeb.Gettext has a catalogue for, else "en".
The API section of /llms.txt for origin, to append after the operator's text.
The URL of /llms.txt: at the origin root, whatever the URL prefix.
The URL of the public MCP server under origin.
The URL of the public OpenAPI description under origin.
The origin (scheme://host[:port]) the documents for conn name, by the
rule of the moduledoc.
Adds value to the Link header of conn, after the value an earlier plug
may have set (one header, values joined by a comma, as RFC 8288 allows). A
value that is already there is not repeated, and a blank earlier header is
ignored.
The Link header of GET /api/public/v1, the tool list: the OpenAPI
description and the guide. Added on a 200 only, and only when the guide
is published; the check runs when the answer is sent.
Adds Link: <guide>; rel="service-doc" to the 405 of GET /mcp/public when
the guide is published.
Whether anything is published for conn (check/1).
Functions
The API catalog (RFC 9727 linkset) naming the origin's public API.
The URL of the public REST API under origin.
@spec cache_control() :: String.t()
The Cache-Control of a published document.
While the website gate is on the answer depends on the client address, so a shared cache must not keep it.
@spec catalog_content_type() :: String.t()
The Content-Type of the API catalog.
The Link header value that points to the API catalog.
The URL of the API catalog: at the origin root, whatever the URL prefix.
@spec check(Plug.Conn.t()) :: {:ok, [PhoenixKit.API.Tool.t()]} | :hidden
Whether anything is published for conn, with the public tools that make it
so. The three parts are checked in the order of the moduledoc, cheapest first.
@spec guide(Plug.Conn.t(), [PhoenixKit.API.Tool.t()]) :: map()
The content of the guide for conn, as one map the two renderers
(PhoenixKit.API.PublicDiscovery.GuideHTML, PhoenixKit.API.PublicDiscovery.GuideMarkdown)
turn into text. tools is the list check/1 returned.
The URL of the guide under origin.
@spec language(PhoenixKit.API.RequestContext.t()) :: String.t()
The language a page for context is written in: the domain's language
reduced to a locale PhoenixKitWeb.Gettext has a catalogue for, else "en".
The API section of /llms.txt for origin, to append after the operator's text.
The URL of /llms.txt: at the origin root, whatever the URL prefix.
The URL of the public MCP server under origin.
The URL of the public OpenAPI description under origin.
@spec origin(Plug.Conn.t()) :: String.t()
The origin (scheme://host[:port]) the documents for conn name, by the
rule of the moduledoc.
@spec put_link(Plug.Conn.t(), String.t()) :: Plug.Conn.t()
Adds value to the Link header of conn, after the value an earlier plug
may have set (one header, values joined by a comma, as RFC 8288 allows). A
value that is already there is not repeated, and a blank earlier header is
ignored.
@spec put_list_links(Plug.Conn.t()) :: Plug.Conn.t()
The Link header of GET /api/public/v1, the tool list: the OpenAPI
description and the guide. Added on a 200 only, and only when the guide
is published; the check runs when the answer is sent.
@spec put_service_doc_link(Plug.Conn.t()) :: Plug.Conn.t()
Adds Link: <guide>; rel="service-doc" to the 405 of GET /mcp/public when
the guide is published.
@spec visible?(Plug.Conn.t()) :: boolean()
Whether anything is published for conn (check/1).