Wymcp.Help (Wymcp v0.1.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 shares its content source with the tools/list description builder (Wymcp.Tool.Schema.action_summaries/1), 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.

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 in run/2, which calls the same Wymcp.Tool.check_arguments/4 a generated tool's dispatch uses, with help's own valid set derived from the schema above. Both halves are needed: Wymcp.Methods.ToolsCall strips the declaration before argument validation runs — 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 at every server's boot (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.

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 boot (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.