salvor-tools 0.5.1

ToolHandler trait, derive macro, and MCP client integration for the Salvor agent runtime
Documentation

Salvor tools: the typed tool-contract layer for the agent runtime.

A tool is a typed, effect-classified operation a model may call. This crate defines what a tool is and how the runtime dispatches one; it declares contracts and performs no IO. Persisting tool-call events and driving the dispatch is the runtime's job, built on the seam this crate exposes.

The layers

  • The typed contract. [ToolMeta] carries a tool's identity and Effect; [ToolHandler] adds its typed Input, Output, and async call. The split is the seam the future #[derive(Tool)] macro cuts: the macro generates ToolMeta, the user writes ToolHandler. See [ToolMeta]'s docs for the exact contract.
  • The tool outcome. [ToolHandler::call] returns a [ToolOutcome]: either an Output, or a [Suspension] that parks the run for a human. Suspension is a return value in v0.1, not a runtime call.
  • Type-erased dispatch. [DynTool] is the Value-in/Value-out, dyn-compatible trait the runtime dispatches through. [TypedTool] adapts any [ToolHandler] into a DynTool, validating the model's JSON against the input type before the handler runs. MCP-backed tools (a later task) implement DynTool directly.
  • The registry. [ToolSet] registers tools by name, looks them up, and enumerates them as [ToolDescriptor]s for a model. Duplicate names are a [RegistryError].
  • Retry policy. [RetryPolicy] encodes the per-effect rule for retrying a failed live execution. It classifies; the runtime loop enforces.
  • MCP tools. Behind the mcp cargo feature (on by default), the [mcp] module connects to an MCP server over stdio and surfaces each of its tools as a [DynTool], registering alongside native tools. All of the MCP dependency surface (the rmcp SDK, a Tokio runtime) is gated behind that feature, so the contract layer above still builds with --no-default-features. MCP stays isolated to that one module by design: rmcp/MCP protocol churn is a standing risk.

Errors

A tool's own failure is a [HandlerError]. The erased layer's error is a [ToolError], whose InvalidInput variant (the model sent malformed arguments, and the handler never ran) is deliberately distinct from Handler (the tool ran and failed), so the runtime loop can route them differently.