Sake.Tool behaviour (Sake v0.4.3)

Copy Markdown View Source

A tool: use Sake.Tool with options, arg lines, an optional output block, and execute/2.

defmodule MyApp.MCP.SearchIssues do
  use Sake.Tool, name: "search_issues", description: "Search issues", scope: "issues:read"
  arg :query, :string, required: true
  @impl true
  def execute(%{query: q}, ctx), do: {:ok, Issues.search(ctx.scope, q)}
end

Options: name (default: the module's last segment in snake case), title, description, icons, scope (one or many), annotations (read_only, destructive, idempotent, open_world), stream, ttl, meta, input_schema (a schema map instead of arg lines), task (:optional or true, or :required: the tool runs as a task for a client that takes one, see Sake.Tasks), ui (a Sake.UI module: the app the host shows with the tool's result), visibility ([:model, :app] by default; [:app] for a tool only an app calls, which a client without MCP Apps does not see), authentication ([acr: ["mfa"], max_age: 300]: how the person must have signed in to call it, see "Step-up authentication" in Sake.Server).

Summary

Callbacks

Runs before execute/2, in the request itself, and returns the arguments execute/2 receives (or a tool error). A task tool asks the client for input here when the answer decides whether the task should start at all: inside the request, the question travels as a multi round-trip request; inside the task, it would wait on the task.

Functions

Declares an argument (or, inside output, an output property).

Declares the output schema with arg lines.

Callbacks

complete(arg, partial, ctx)

(optional)
@callback complete(arg :: String.t(), partial :: String.t(), ctx :: Sake.Context.t()) ::
  {:ok, [String.t()]} | {:ok, [String.t()], keyword()}

execute(args, ctx)

@callback execute(args :: map(), ctx :: Sake.Context.t()) ::
  {:ok, term()}
  | {:ok, term(), keyword()}
  | {:error, String.t()}
  | {:error, {:missing_capability, map()}}

prepare(args, ctx)

(optional)
@callback prepare(args :: map(), ctx :: Sake.Context.t()) ::
  {:ok, map()} | {:error, String.t()}

Runs before execute/2, in the request itself, and returns the arguments execute/2 receives (or a tool error). A task tool asks the client for input here when the answer decides whether the task should start at all: inside the request, the question travels as a multi round-trip request; inside the task, it would wait on the task.

spec()

@callback spec() :: Sake.Tool.Spec.t()

Functions

arg(name, type, opts \\ [])

(macro)

Declares an argument (or, inside output, an output property).

output(list)

(macro)

Declares the output schema with arg lines.