Skip to content

Tool reference

This page catalogs every tool kenny exposes to Claude — over MCP (a local client) and in the Ask kenny overlay — and explains which ones can change a PC, who has to approve them, and where each call is recorded. For the operator workflow around these tools, see user-guide.md.

Two kinds of tools

kenny splits its tools into two families:

  • Capability tools run on a single agent PC (Windows, Linux, or macOS). Every call names its target with an agent_id argument, forwards a request frame to that agent through the tunnel, and returns the agent's response. powershell_exec, shell_exec, the fs_*, winget_*, diag_*, net_* tools, screen_capture, remotehelp_*, telemetry_collect, and agent_update are all capability tools. powershell_exec and shell_exec are OS-scoped mirrors of each other (Windows vs. Linux/macOS) — the server's OS guard (below) refuses to forward the wrong one for a given agent's OS.
  • Server-only orchestration tools read the registry, telemetry store, and health rules on the server. They are never forwarded to an agent: list_agents, select_agent, fleet_overview, agent_health, agent_snapshot, agent_availability (plus the server-side web-filter tools).

agent_id targeting, and what select_agent actually does now (ADR-0038)

A remote MCP client (Claude Desktop, claude.ai) gives the server no reliable per-conversation identifier, so every capability tool call over MCP must include its own agent_id naming the target host — there is no server-side "current agent" a raw MCP call can rely on. select_agent still validates an id and is useful for discovery, but it no longer routes anything; passing it once and then omitting agent_id on a later call fails with an explicit no_agent error rather than guessing a host.

The Ask kenny overlay is the one place a sticky selection is still safe, because each conversation is a genuinely separate, non-shared session: it forwards to whichever agent is selected in the dashboard's context pill, and the model can pass agent_id to target a different host for one call without changing that selection.

Windows-only capabilities stay green on Linux CI

Capability tools that touch Windows internals have portable fallbacks in the agent, so cargo test / cargo build pass on Linux dev and CI. On a non-Windows host the affected tools return error.code = "unsupported" rather than failing the build. This is the agent's #[cfg(windows)] discipline.

Three tiers, and who enforces what

Every tool is classified into one of three tiers (kenny_server/tool_classes.py, the single source of truth):

  • read_only — observes; changes nothing on the host or on the server.
  • standard_change — a change that is routine, reversible and low-blast-radius: flushing a DNS cache, opening a remote-help session, updating an already-installed package, pushing a block list that is already configured.
  • normal_change — everything else that changes state: arbitrary code execution, installing/uninstalling software, who may sign in to a family PC, changing what the server itself enforces. Unknown tools fail closed into this tier.

The tier is a property of the tool. The gate is a property of the calling surface. A tier is never permission to skip a confirmation — it only says how consequential a change is. Whether that consequence gets confirmed, runs autonomously, or is refused outright is decided independently by whichever surface is calling: today the Ask kenny overlay and MCP, and — for the Discord ticket surface described in ITSM & the Discord bot — a per-tier autonomy split.

Tier Dashboard chat MCP Ticket chat (see itsm.md) Triage
read_only runs runs runs (a consent hold first, for a privacy-sensitive one) runs — but the privacy-sensitive ones are withheld entirely
standard_change holds (confirm-gate) runs runs autonomously, with a trail row same, and only ticket_triage_verdict is on offer
normal_change holds (confirm-gate) runs holds for an operator's approval withheld entirely

The triage column is the one surface that withholds rather than gates, and the reason is that it is the one surface with nobody in it: an unprompted investigation has no operator to answer an approval and no person to give consent, so a hold would park the ticket forever. A tool absent from its schemas is never a call to hold. See ADR-0056.

The Ask kenny overlay holds both change tiers, exactly as it always has — moving a tool from normal_change to standard_change changes its blast-radius classification, never whether the dashboard confirms it. Only the Discord ticket surface treats standard_change as safe to run on its own, and it still records a trail row saying so. See ADR-0045 for why the tier and the gate are kept apart, and ADR-0009 for the dashboard confirm-gate this refines.

The Ask kenny overlay's confirm-gate pausing a state-changing winget_update until the operator approves. The confirm-gate pausing a winget_update until the operator approves. It is a standard_change — which the Discord surface runs on its own, and Ask kenny still confirms. That difference is the point of the table above: the tier describes the tool, the surface decides the gate.

Alongside the tier, two independent flags apply to a handful of tools regardless of which surface calls them:

  • Privacy-sensitive (screen_capture, remotehelp_start, fs_read, web_activity_query) — invoking the tool touches someone's privacy, or needs the person at the keyboard to know. On the Discord surface this needs the affected person's consent, separately from whether the caller is authorized — see ITSM: operator approval vs. user consent.
  • Redacted output (screen_capture, fs_read, fs_search, web_activity_query, diag_eventlog) — the result carries screen pixels, file contents, event-log text or browsing history, and must never be echoed verbatim to an external chat surface; Discord summarises and links to the ticket in the authenticated dashboard instead.

The three-tier classification lives in one place, so it is worth being precise about the other controls that also gate a call, independent of tier or surface:

Control Where it lives What it does
Role & host scope (ADR-0033) Auth middleware + tool layer (server) The access token — an OAuth token (ADR-0037) or a personal access token — identifies a user; a user-role caller only sees/targets its assigned hosts (select_agent, agent_*, forwarders, and list_agents/fleet_overview are scope-filtered), and parental-controls mutation tools require operator+. The legacy shared token acts as a superuser.
Capability profile (ADR-0047) Tool schemas + dispatch (server) An optional, named per-account tool allowlist that only ever narrows what the role already allows — checked twice: the tool is not offered to the model, and dispatch refuses it again. See ITSM: capability profiles.
Agent-side safety guard (ADR-0019) Compiled into the agent Deterministically refuses individually catastrophic calls (disk wipes, shadow-copy deletion, event-log clearing, Defender disable, sensitive-path fs_*, unlisted agent_update hosts) regardless of operator approval — and it cannot be turned off from the server.
Shell execution mode (ADR-0064) Set on the server, enforced at the agent What powershell_exec and shell_exec may run fleet-wide: unrestricted (the default), allowlist (only commands that match a declared rule in full), or off. Deny rules are checked first either way, so an allow rule can never lift one. Set by a superuser in Admin → Shell policy.
OS guard Server (forwarder) Refuses powershell_exec/shell_exec for the wrong agent OS — e.g. shell_exec on a Windows agent — before ever forwarding, naming the correct tool.
Local kill-switch (ADR-0011) Agent + tray, at the PC The person at the PC turns all state-changing tools off. Forwarded calls then return error.code = "disabled"; telemetry and read-only tools keep working.

A raw MCP client is not confirm-gated

The confirm-gate is a property of the Ask kenny overlay loop, not of the server's tool surface. A raw external MCP client (e.g. Claude Desktop) pointed at /mcp is not confirm-gated by the server — every tier runs. The agent-side guard and the local kill-switch still apply — they are enforced at the agent, the boundary that actually runs the command — so they hold no matter who calls the tool. It also must name its target explicitly: every forwarded call takes its own agent_id (see the note above), so a raw MCP client can never fall back onto whatever host another concurrent session happened to select.

Capability tools

Names are exactly as they appear on the wire, over MCP, and in the chat. The Arguments column lists only each tool's own parameters — every capability tool additionally takes agent_id naming the target host (required over MCP; optional in the Ask kenny overlay, where it overrides the session's selection for one call). agent_id is routing metadata the server consumes and never puts on the wire (ADR-0038).

Shell

powershell_exec and shell_exec are OS-scoped mirrors: each runs only on its matching agent OS (Windows / Linux+macOS) and is unsupported on the other. The server's OS guard (see the confirm-gate table above) refuses to forward the wrong one before it ever reaches the agent.

Tool Arguments Tier
powershell_exec script, timeout_s normal_change
shell_exec command, timeout_s normal_change

Both are governed by the fleet's shell execution mode (ADR-0064). Out of the box the mode is unrestricted and they behave as they always have. Under allowlist a command runs only if it matches a declared allow rule in its entirety — a rule of uname -a does not admit uname -a; rm -rf / — and under off neither tool runs at all. A refusal comes back as error.code = "blocked", the same code the safety guard uses.

A new server ships a default allow list, restorable from Admin → Shell policy, so switching to allowlist does not start from nothing. It admits read-only diagnostics — system, load, storage, services and logs, network state and reachability, packages, accounts, firewall state, containers — and one remediation per OS: restarting a service by exact name. Commands that read files are left to fs_read and fs_list, whose path guard a shell would bypass, and the rules keep out what turns a diagnostic into something else: command chaining, redirection, variables and subexpressions, interpreters, pipes into anything but filters like grep, Select-Object or Where-Object with a plain comparison, and the forms of a read-only tool that write, delete or run forever (journalctl --vacuum-*, dmesg -c, ping -t).

The mode is a defence against an abused or prompt-injected credential and against accidental destruction. It is not a sandbox: it cannot help against a compromised kenny server, which is what pushes the mode, or against someone who is already root on the managed host.

Files

Tool Arguments Tier
fs_list path read_only
fs_search root, pattern read_only (redacted output)
fs_read path read_only (privacy-sensitive, redacted output)
fs_disk_usage — read_only

Packages

Tool Arguments Tier
winget_list — read_only
winget_install id normal_change
winget_uninstall id normal_change
winget_update id? standard_change — updating an already-installed package is the routine, reversible half of the package family

Diagnostics

Tool Arguments Tier
diag_processes — read_only
diag_services filter? read_only
diag_eventlog log, count read_only (redacted output)
diag_autostart — read_only

On Windows, diag_services, diag_eventlog and diag_autostart each run one CIM or event-log query that the agent stops after 50 s; the server waits 90 s for these three. A query that runs out of time comes back as a timeout error naming the query, so a slow, busy machine is not mistaken for one that returned nothing.

Network

Tool Arguments Tier
net_config — read_only
net_dns_flush — standard_change
net_adapter_reset name standard_change

Screen

Tool Arguments Tier
screen_capture — read_only (privacy-sensitive, redacted output)

Screenshots are captured in the interactive user session via the tray helper, not from the session-0 service (which would grab a black frame) — see ADR-0018.

Remote help

Tool Arguments Tier
remotehelp_status — read_only
remotehelp_start — standard_change (privacy-sensitive)
remotehelp_stop — standard_change

remotehelp_start launches Windows Quick Assist on the user's desktop; kenny acts as a concierge, not the transport. A helper shares the 6-digit code and the person at the PC must click Allow — the consent steps stay with the people (ADR-0021). It is standard_change and privacy-sensitive at once — the case where both of Discord's gates apply to the same call; see ITSM: operator approval vs. user consent.

Telemetry

Tool Arguments Tier
telemetry_collect sections? read_only

Agent management

Tool Arguments Tier
agent_update version, url, sha256 normal_change

Parental controls

Registered on the agent when the web filter is wired up. See parental-controls.md.

Tool Arguments Tier
webfilter_status — read_only
webfilter_apply domains, doh_policy, list_hash normal_change
webfilter_clear — normal_change

Account governance

Who may sign in to the machine. principal is the account name — the same tool works for a local, a Microsoft and a Linux account, on Windows and Linux hosts alike, because below this layer neither operating system draws the distinctions above it. There is no account_list: the inventory is the local_accounts telemetry section, refreshable on demand with telemetry_collect — and it is also where each account publishes the verbs it cannot perform, with a reason. All of these require the operator role and are confirm-gated — and every one is normal_change: deciding who may sign in to a family PC is never routine. See account-governance.md.

Tool Arguments Tier
account_set_enabled principal, enabled normal_change
account_set_admin principal, admin normal_change
account_set_logon_rights principal, deny (⊆ network, remote_interactive) normal_change (network is Windows-only)
account_create name, password, display_name?, admin? normal_change (local accounts only; no asymmetry on Linux)
account_delete principal, remove_profile normal_change
account_session_action principal, action (lock / logoff), warn_seconds? normal_change
password_policy_set min_length?, max_age_days?, lockout_threshold? normal_change (accounts stored on the machine only)

The agent refuses — with blocked, not overridable from the server — any call that would disable, demote, delete or restrict the last enabled administrator, or delete a built-in account.

Server-only orchestration tools

These read server state and are never forwarded. All are read-only.

Tool Arguments Purpose
list_agents — Known agents with online state and rolled-up health: overall, flagged_sections (the incidents — warn/crit) and posture_sections (standing facts that never roll up; see the status model in telemetry.md).
select_agent id Validate an agent id and set the Ask kenny overlay's default (advisory only over MCP — it does not route forwarded calls there; see the note above).
fleet_overview — Per-agent rolled-up health for the whole fleet, in the same shape as list_agents.
agent_health id Per-section health for one agent: status, summary, reason, attention, tier (incident / posture / none), since and age_seconds (how long the section has held its current status, from the alert loop's state; null until it has seen it) and, where a rule has structured evidence, details (the reliability rule's per-pattern activity record, win_update's per-KB failures).
agent_snapshot id, section? Latest stored telemetry snapshot (optionally one section).
agent_availability id, days? When one host was reachable over the last days (1–30, default 7): online_pct (unknown time excluded), totals, outages (offline stretches ≥ 5 min, newest first), unknown_spans (the server itself was down), boots, and ledger_since (before it, stretches are reconstructed from telemetry arrival and marked approx).

select_agent is withheld from the ticket surface

Every other server-only tool above is available wherever a ticket's profile allows it; select_agent alone is filtered out there, because its only job is changing the target — exactly what a ticket freezes at creation. See ITSM: the lifecycle.

The Ask kenny overlay has two ticket tools of its own (ADR-0063). Both are read_only and neither writes a ticket: ticket_draft proposes one for the operator to correct and open through the ordinary create route, which stays the only path that opens a ticket, and ticket_find looks for one already on the queue. They are withheld from every ticket-bound and unprompted-triage turn, and are not registered over MCP — a remote client has no form for a draft to appear in.

Tool Arguments Tier
ticket_draft title, summary, agent_id? read_only (creates nothing)
ticket_find agent_id? read_only

A ticket opened from a draft records what the conversation had already checked: one note row naming the successful read-only calls from that chat session, composed on the server from the session itself rather than sent by the browser.

The server-side web-filter tools are also server-only. webfilter_get and web_activity_query are read_only; webfilter_set and webfilter_push change state, but at different tiers — webfilter_set changes what the server enforces, webfilter_push only ships the already-configured list to the host, which is the routine half.

Tool Arguments Tier
webfilter_get id read_only
webfilter_set id, plus enforcement / history / config toggles / add_domain / remove_domain normal_change
webfilter_push id standard_change
web_activity_query id, hours?, flagged_only? read_only (privacy-sensitive, redacted output)

Reliability alarm suppression (ADR-0041, issue #166) is server-only too: rules exclude a (source, event_id) reliability event pattern from severity scoring, fleet-wide by default or scoped to one host, without hiding its raw count. reliability_suppression_add/_remove are normal_change (they hit the ADR-0009 confirm-gate in the Ask kenny overlay).

Tool Arguments Tier
reliability_suppression_list agent_id? read_only
reliability_suppression_add event_id, source?, agent_id?, note? normal_change
reliability_suppression_remove rule_id normal_change

Auto-ticket rules are also server-only: they decide which alerts open a ticket automatically, by default every genuine alert and nothing else. Operator+ on every one of these, including the read — an alert-origin ticket is itself operator-only, so a scoped user has no legitimate use for the rules that decide when one opens. ticket_rule_set takes an event_type of health, offline, disk_forecast, hardware_forecast or change, and a decision of open_all, open_crit or never.

Tool Arguments Tier
ticket_rule_list agent_id? read_only
ticket_rule_set event_type, decision, section?, agent_id?, note? normal_change
ticket_rule_remove rule_id normal_change

Auditing

Every forwarded capability call is appended to the tool-call audit log, annotated read-only vs state-changing (plus, additively, its tier), with its agent, timestamp, and ok/error outcome. Read it in the dashboard's Log page, filtered to the TOOLS chip. See dashboard.md.

The Log page, filtered to tool calls, each tagged read-only or state-changing. The Log page, filtered to tool calls, each tagged read-only or state-changing.

Tool naming

Tools use Anthropic-native snake_case names, identical to the wire-contract tool catalog (ADR-0016). There is one canonical identifier per tool across the contract, fixtures, MCP, the Ask kenny overlay, and the agent's dispatch table — no boundary translation. The same names you see here appear over MCP and in the chat.

See also

  • user-guide.md — the operator workflow around these tools.
  • dashboard.md — Fleet, the host page, and the Log page.
  • protocol.md — the authoritative agent⇄server wire contract.