Request-scoped server guidance and tool presentation.
Instructions
:instructions remains a static string. :instructions_provider is an
optional one-argument callback (a function, {module, function}, or
{module, function, prefix_args}) that receives the trusted request context
and returns:
{:ok, instructions}with a non-empty UTF-8 string of at most 65,536 bytes;:omitto send no instructions for this request; or{:error, reason}to fail the request.
A configured provider supplies the instructions for modern server/discover
and legacy initialize; the static string is used only when no provider is
configured. A failing provider never falls back to the static string. An
error, exception, exit, throw, invalid value, or request timeout returns a
controlled internal error ("instructions_provider_failure") and publishes
no instructions. A failed legacy initialize leaves the session
unnegotiated, so a later valid initialize can succeed.
Tool presentation
:tool_presentation is an optional two-argument callback that receives an
already visible tool's public descriptor (string keys) and the trusted
request context. It returns {:ok, overrides}, :default, or
{:error, reason}. overrides may contain only:
"title": a non-empty UTF-8 string of at most 1,024 bytes;"description": a non-blank UTF-8 string of at most 4,096 bytes;"icons": a complete icon list (seeAttestoMCP.Server.API);"_meta": application keys merged over the registered_meta. Keys must follow the MCP_metakey grammar and must not use a reserved MCP prefix,progressToken, or trace-context names.
Atom keys are accepted for these four fields. Any other field, including
name, inputSchema, outputSchema, annotations, execution, a handler,
scopes, or an authorization callback, fails the list request with
"tool_presentation_failure". No partial catalog is returned.
Scope requirements, authorize callbacks, and HTTP definition policies
decide availability first; hidden tools are never passed to the callback.
Presentation never changes registered definitions, and tools/call repeats
every eligibility check. Customized descriptors are part of the pagination
fingerprint, so a cursor stops working when the presentation it was issued
for changes.
Both callbacks run in the request worker under the request deadline. Their
output is treated as private: responses that include it use
cacheScope: "private" and ttlMs: 0 unless a cache policy explicitly
supplies a TTL (see AttestoMCP.Server.CachePolicy). Guidance is not an
authorization mechanism.