Wymcp.Help (Wymcp v0.2.1)

View Source

The framework-owned introspection tool — the server's entire introspection surface, injected by Wymcp.Router into every server under the reserved tool name help.

Help answers at three levels: a bare call returns the server index (every tool with its action summaries); tool returns that tool complete (all action schemas with notes, related actions, and examples); tool plus action returns one action complete, with the target tool's Wymcp.Tool.action_context/2 output under "context". Resolution order is tool first, then actionaction without tool is an error, and unknown targets error naming the valid ones and pointing at the help index (isError: true content the calling LLM can self-correct from), never a silent fallback to a broader answer.

The index renders through Wymcp.Tool.Schema.action_summaries/1, which shares its content source with the tools/list description builder (Wymcp.Tool.Schema.build/1) rather than being called by it, so the two cannot drift. Server-level prose does not live here — it belongs in the initialize instructions router option.

Help answers from ctx.tools — the request's resolved tool list, which Wymcp.Methods.ToolsCall sets on every context — so it needs no session and serves both eras.

It will not render around a gap, at any of the three levels. Help obtains every action schema it renders through Wymcp.Tool.fetch_action_schema!/3 or Wymcp.Tool.fetch_action_schemas!/1, which check the mandatory keys where the schema is obtained — the read-side corollary stated in Wymcp.Tool's moduledoc — so a schema missing one raises ArgumentError naming the tool, the action and the key before anything is rendered. Publishing the entry instead would assert something false about the action: silence about :properties reads as a claim that it takes none, and a null description reaches the wire as the action's description.

This module implements the tool wire contract by hand (input_schema/0, run/2) rather than through use Wymcp.Tool: help has no action dispatch, its two parameters live at the top level of arguments, and its input schema sets additionalProperties: false so a misspelled parameter is a stated contract violation rather than a silent answer to the wrong question. Publishing that is one half; the other is the gate pair in run/2: vocabulary through the same Wymcp.Tool.check_arguments/4 a generated tool's dispatch uses, and types through help's own check_argument_types/2 — a tool that hand-writes its schema owns the types of the keys it declares, and the framework's two type checks cover only its own action/data. Both valid sets derive from the schema above. Both halves are needed: argument validation in Wymcp.Methods.ToolsCall checks structure only — a stray name is a dispatch gate's answer everywhere in wymcp, never a -32602 naming no key — so without the gate a misspelled tol would silently answer the index. Its definition/0 is assembled by the same Wymcp.Tool.build_definition/1 every generated tool uses, so a definition key added there reaches help without hand-sync.

It is the framework's only @behaviour Wymcp.Tool tool, and the only reason that path exists. Wymcp.Tool's run/2 and input_schema/0 come from __before_compile__ and are not defoverridable, so a tool without action dispatch cannot use the macro — the path is an internal accommodation, not a consumer contract; a consumer tool uses the macro. Being behaviour-only, this module owes every required callback by hand: actions/0, run_action/3, hints/2 and handle_error/1 are dead stubs carried for that reason alone, and Wymcp.Router.init/1 checks them while a mount module compiles (the callback-surface invariant, homed in Wymcp.Tool).

Every call that reaches an answer emits [:wymcp, :help, :called] after that answer is resolved — see Wymcp.Telemetry. A call rejected by the arguments gate above does not: it resolved no target, so the event's tool, action and level would describe an index call that never happened. Such a rejection stays observable as [:wymcp, :tool, :stop] with error_kind: :dispatch, like any other tool's gate rejection. (A mistyped action or data never gets this far: ToolsCall's argument validation answers it -32602 before any tool runs, unobserved by tool telemetry — a property of the -32602 path, not of help.)

flowchart TD
    H[Wymcp.Help] --> R["run/2"]
    subgraph External
        R -->|"action_summaries/1"| SC[Tool.Schema]
        R -->|"shared tool-surface helpers"| WT[Wymcp.Tool]
        WT -->|"action_context/2"| T(Target tool)
        H -->|"build_definition/1"| WT
        R --> TE[Telemetry]
    end

Summary

Functions

True when module claims the reserved tool name.

Functions

uses_reserved_name?(module)

True when module claims the reserved tool name.

The reserved name is "help" — the tool name only the framework may use: consumer tools may neither claim it at a mount module's compile (Wymcp.Router.init/1) nor replace it at runtime (Wymcp.Session.register_tool/2). Both raise sites route through this predicate; each keeps its own message tail naming its path.