Give any MCP client a Linux computer. Provides shell access, file operations, browser automation, and system information tools.
Husk provides 21 well-structured tools with consistent naming (verb_noun pattern: shell, read_file, write_file, edit_file, list_dir, expose_port, browse, etc.). All tools have descriptions (avg ~120 chars, within 10-1024 range). Input schemas are present and properly typed with JSON Schema. However, parameter descriptions are sparse, many lack detail on constraints, formats, or when to use them. Output schemas are not documented. Error handling is minimal; no recovery guidance or actionable error messages visible. Tool composition is strong (single responsibility, clear chaining via IDs), but descriptions could be more LLM-optimized per the 50-200 char baseline.
Load a web page from inside this computer and get its text and links. Prefer this over your own web tools when what matters is what THIS machine can reach: it shares the computer network, DNS and egress policy, so the result matches what a command running here would see.
Click the element with this ref, then return a fresh snapshot of whatever the page became. Refs come from browser_snapshot; there is deliberately no way to click a coordinate.
Open a URL in a real Chromium inside your computer and return the rendered text. Use this instead of `browse` when the page needs JavaScript to render, or when you need to stay logged in across several pages. First use on a machine downloads Chromium (~111 MB) and takes a minute; after that it is fast, and `browse` is still the cheaper choice for a plain article.
Move the pointer over an element, for menus that only appear on hover.
Go back, go forward, or reload the current page.
Output schemas not documented. LLMs cannot plan downstream tool calls or extract required fields without knowing what each tool returns. E.g., shell returns what structure? browser_snapshot returns what fields for each element?
Parameter descriptions lack constraint details. E.g., timeoutSec in shell has no min/max bounds; maxBytes in browse has no guidance on typical values; limit in browser_snapshot defaults to 400 but no explanation of cost/benefit tradeoff.
No error handling guidance. Tools like shell (IRREVERSIBLE risk) and write_file (WRITE risk) provide no recovery hints. E.g., if shell fails, should the agent retry? Call computer_info first? The descriptions do not say.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | <=2025-11-25 | v2 |
Take a PNG of the current page. Saved into the computer, and returned inline when it is small enough to be worth the tokens. Good for checking a layout or showing a human what you see -- for deciding what to click, browser_snapshot is smaller and more exact.
Scroll the page, or bring one element into view. The snapshot lists the whole document, so an element can be listed and still be off screen; scroll to it before clicking if a click does not take. Also how you load more of an infinite-scroll page.
Choose an option in a dropdown (a native <select>). Clicking one does nothing useful -- the menu is drawn by the operating system, not the page -- so use this instead. Matches the option by value or by its visible label.
List everything on the current page you can read or act on, each with a `ref`. Pass a ref to browser_click or browser_type. Take a fresh snapshot after anything that changes the page -- refs do not survive a navigation.
Whether this computer already has a browser, without installing one, and whether this provider can get one at all. Call it before browser_goto if you want to know whether the first call pays the ~111 MB download -- on a metered connection, or on a container provider that cannot perform the download, that is worth knowing first.
List the open tabs, or switch to one. A link that opens in a new tab lands somewhere you are not looking, and every other browser tool keeps acting on the old page -- if a click seemed to do nothing, check here before concluding it failed.
Type into the field with this ref, replacing what is already there. Set submit to press Enter afterwards. Returns a fresh snapshot.
Attach files to a file input. The paths are paths inside your computer, so write or download the file there first -- the browser is in the same machine as your filesystem.
Wait until some text or a CSS selector appears on the page (or disappears, with gone). Use this after anything that loads content without navigating -- which on a modern site is most things. Waiting for a page load instead will return immediately and you will snapshot an empty page.
Describe the machine: OS, kernel, CPU, memory, disk, network reachability, and which language runtimes are installed. Call this once before assuming a tool exists, instead of probing with several shell commands.
Replace an exact string in a file. Fails if old_string is absent or appears more than once, so include enough surrounding context to be unambiguous. Safer than write_file for edits.
Publish a port the computer is listening on and get a URL reachable from the host. Start your server first, then call this.
List a directory. Directories are listed first.
Read a text file from the computer. Use offset/limit for large files rather than reading the whole thing -- output is capped and the middle will be elided.
Run a shell command on your Linux computer and return its output. This is the primary tool -- prefer it for anything a command line can do. The filesystem persists across calls within a session. Commands run from /work by default.
Create or overwrite a file. Creates parent directories. To change part of an existing file, use edit_file instead so you do not lose content you did not read.
Tool descriptions are functional but not LLM-optimized. Baseline for A+ tools is 50-200 chars; many Husk descriptions are 60-90 chars and lack WHEN/WHY context. E.g., 'List a directory' does not explain when to call it vs shell 'ls', or what structure it returns.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). Risk levels are declared in the spec (READ_ONLY, WRITE, IRREVERSIBLE) but not exposed to the LLM via tool metadata, forcing the LLM to infer safety from descriptions alone.