Skip to main content
Glama

htb-hosts

CI License: MIT Python 3.11+

Sudo-free, cleanable /etc/hosts management for Hack The Box (and any lab work).

Doing HTB, pentests, or CTFs means constantly adding IP → hostname lines to /etc/hosts, then hunting them down to clean up later. htb-hosts keeps every entry it manages inside one delimited block, grants you passwordless write access via a POSIX ACL, and gives you one command to wipe a box (or everything). It ships as both a CLI and a zero-dependency MCP server, so you and your AI coding agents can manage hosts the same safe way.

$ htb-hosts add 10.10.11.161 forest.htb dc01.forest.htb
added: 10.10.11.161 forest.htb dc01.forest.htb [tag=forest]

$ htb-hosts show
HTB hosts — 5 managed entries in 3 boxes

  forest (2)
    10.10.11.161    forest.htb
    10.10.11.161    dc01.forest.htb

  machine (1)
    10.129.45.2     machine.htb www.machine.htb

  sequel (2)
    10.10.11.202    sequel.htb dc01.sequel.htb

$ nmap -p- $(htb-hosts get forest)      # resolve a box name to its IP, inline
Starting Nmap 7.95 ( https://nmap.org ) ...

$ htb-hosts clean --exclude forest      # done with everything but forest
cleaned 3 entry/entries (all except ~forest)

Features

  • No sudo for daily use: a one-time ACL grant lets you edit /etc/hosts without sudo ever again.

  • One-shot cleanup: everything lives in a managed block. clean wipes it; clean --tag forest drops one box; clean --exclude forest keeps one and clears the rest.

  • Pipe-friendly lookups: htb-hosts get forest prints just the IP, so nmap $(htb-hosts get forest) and ffuf -u http://$(htb-hosts get forest --host) just work.

  • Automatic per-box tagging: hostnames are grouped by box name (dc01.forest.htb → forest), even across multiple IPs.

  • Safe by construction: strict input validation (no injection), flock locking for writers and readers, in-place writes that preserve the ACL, and automatic backups on every change (loud warning if a snapshot ever fails).

  • Backup & restore: named snapshots (private: 0700/0600) and one-command rollback.

  • Tab completion: zsh and bash completions for commands, flags, and your live hostnames, IPs, tags, and snapshots.

  • MCP server included: first-class tools for Claude Code / MCP agents.

  • Zero runtime dependencies: pure Python standard library.

Related MCP server: ssh-chat-mcp

Install

Requirements: Linux, Python 3.11+, and a filesystem with POSIX ACL support (ext4/xfs/btrfs, the default almost everywhere) plus setfacl.

git clone https://github.com/sresarehumantoo/htb-hosts.git
cd htb-hosts
make install

make install copies the tool into /opt/htb-hosts and /usr/local/bin, grants your user an ACL on /etc/hosts, installs the shell completions, and registers the MCP server. It works whether you run it directly or under sudo: the steps that need privilege call sudo themselves, and the human user is auto-detected (SUDO_USER when under sudo, else the current user) so the ACL always targets you, not root. Override with HOSTS_USER=<name> if needed.

The one-time install needs privilege (it writes to /opt and /usr/local/bin and sets the ACL). Everyday htb-hosts use afterward needs no sudo.

New shells pick the completions up automatically; in a shell that is already open, exec zsh (or rm -f ~/.zcompdump && compinit) refreshes them.

Already have a pile of entries in /etc/hosts? Pull them into the managed block:

htb-hosts migrate      # imports existing host lines, tagged by box name

To uninstall: make remove (leaves your entries + ACL) or make purge (removes everything, including the managed block and ACL).

Usage

htb-hosts add 10.10.11.161 forest.htb dc01.forest.htb   # IP and hosts in any order
htb-hosts add 10.10.11.161 "forest.htb, dc01.forest.htb"  # ...or one quoted string
htb-hosts add www.forest.htb 10.10.11.161 --tag forest  # extra vhost, same box
htb-hosts show                                          # box-grouped overview
htb-hosts show forest                                   # ...narrowed to one box
htb-hosts show --flat                                   # one line per entry
htb-hosts show --full                                   # also show unmanaged/system lines
htb-hosts get forest                                    # just the IP, for $(...)
htb-hosts get forest --host                             # just the hostnames
htb-hosts get forest --host -i 1                        # just the first hostname
htb-hosts get forest --host -n                          # numbered, to pick an index
htb-hosts rm forest.htb                                 # remove one hostname
htb-hosts clean --tag forest                            # remove a whole box
htb-hosts clean --match forest web                      # remove what `get` would show
htb-hosts clean --exclude forest                        # remove everything EXCEPT forest
htb-hosts clean                                         # wipe all managed entries
htb-hosts doctor                                        # check access / show the fix

The IP can go anywhere in the arguments: htb-hosts add forest.htb 10.10.11.161 works too, and any single argument may carry several names separated by commas or spaces. Add --json to most commands for machine-readable output.

Command reference

Command

What it does

add <ip> <host…>

Add/update an entry (idempotent; merges by IP)

rm <host|ip>

Remove a hostname or a whole IP from the block

show [pattern…]

Box-grouped view, narrowed to the pattern (--flat, --full)

get [pattern…]

Bare values for matching entries, for $(…)

get … -i N

Keep only the Nth value when a box has several

clean [--tag T | --match P… | --exclude P…]

Remove all, one box, a fuzzy match, or all-but-matches

retag

Re-derive every tag from its box name

backup [--label L]

Save an explicit snapshot

restore [--list] [name]

Roll back to a snapshot

migrate

Import existing /etc/hosts entries into the block

doctor

Check access + managed-block integrity; print the exact fix

One rule for the two read commands: show is for your eyes, get is for your pipes. Both take the same patterns; only get promises bare, parseable output.

Selecting values for other tools

get prints nothing but the values of the entries matching a fuzzy pattern, one per line, deduplicated, so they drop straight into another command:

nmap -p- $(htb-hosts get forest)                   # -> 10.10.11.161
ffuf -u "http://$(htb-hosts get forest --host)/FUZZ" -w words.txt
htb-hosts get                                      # every managed IP

The pattern is matched case-insensitively against each entry's IP, tag, and hostnames. --host switches the output from IPs to hostnames; with --host, the output narrows to the hostnames that actually matched (get jobs --host → jobs.example.htb), falling back to all of the entry's names when the match came from its IP or tag.

Several patterns narrow, they don't add. Each one has to match, so patterns drill into a selection rather than growing it:

$ htb-hosts get forest --host          # the whole box
forest.htb
dc01.forest.htb
www.forest.htb

$ htb-hosts get forest dc01 --host     # drill in
dc01.forest.htb

(clean --exclude is the opposite and deliberately so: it is a repeatable, additive keep-list, where --exclude forest --exclude sequel keeps both.)

Nothing matched is an error: stdout stays empty and the exit code is 1, so a typo can't silently hand an empty target list to the next command.

Picking one of several values

A box with a few vhosts has a few hostnames on one IP, and pasting all of them into $(...) word-splits into several arguments: curl http://a.htb b.htb c.htb/. -n/--numbered shows you what's there, and -i/--index keeps just the lines you want (1-based):

$ htb-hosts get forest --host -n
1  forest.htb
2  dc01.forest.htb
3  www.forest.htb

$ curl "http://$(htb-hosts get forest --host -i 1)/"       # -> forest.htb
$ htb-hosts get forest --host -i 2                         # -> dc01.forest.htb
$ htb-hosts get forest --host -i -1                        # last one
$ htb-hosts get forest --host -i 2-3                       # a range
$ htb-hosts get forest --host -i 1,3                       # a list, in that order

An out-of-range index is an error (exit 2, empty stdout) rather than a silent drop, for the same reason an empty match is: a pipeline should never quietly get fewer arguments than you asked for.

When you want every value but on one line, --sep joins them instead:

nmap $(htb-hosts get forest --sep ,)      # -> nmap 10.10.11.161,10.10.11.162

Tab completion

make install drops a zsh completion in $PREFIX/share/zsh/site-functions and a bash one in $PREFIX/share/bash-completion/completions, both on the default search paths, so no rc-file edit is needed. make completions installs just those.

Completion is live: candidates come from the managed block as it stands right now, not a static list.

You type

You get

htb-hosts <TAB>

subcommands, with descriptions

htb-hosts rm <TAB>

your managed hostnames and IPs

htb-hosts get <TAB>

hostnames, IPs and tags (anything a pattern matches)

htb-hosts get forest --host <TAB>

only the hostnames inside the forest box

htb-hosts clean --tag <TAB>

your box tags

htb-hosts restore <TAB>

your snapshots, newest first

htb-hosts add … --<TAB>

that subcommand's flags

Completion is also scoped and field-aware: once you have typed a pattern, the next one completes only from what that selection contains, and --host restricts the menu to the hostnames that field can actually print. Accepting a suggestion therefore always does what the menu implied, which is why patterns narrow.

The scripts get their data from htb-hosts complete <kind> [pattern…], a hidden subcommand that prints one candidate per line. It is deliberately silent on failure: an unreadable or malformed /etc/hosts degrades completion rather than spraying errors into your prompt.

Tagging

Every entry carries a tag, defaulting to the box name derived from its first hostname (dc01.forest.htb → forest; fileserver.corp.local → corp). That groups a whole box (even across several IPs) under one tag, so clean --tag forest clears it in one go. Re-derive tags for existing entries any time:

htb-hosts retag

Removing a fuzzy match: clean --match

--match takes the same patterns as get, so what you selected is what goes:

$ htb-hosts get forest web --host       # check first
web01.forest.htb
web02.forest.htb

$ htb-hosts clean --match forest web
will remove 2 entries:
  10.10.11.161    web01.forest.htb  [tag=forest]
  10.10.11.161    web02.forest.htb  [tag=forest]
proceed? [y/N] y
cleaned 2 entry/entries (~forest web)

Because a fuzzy pattern is the one removal you cannot verify by reading the command line, --match prints its plan and asks whenever it would remove more than one entry. --yes skips the prompt, and --json implies it; with no terminal to ask, it refuses rather than guessing. The exact modes (--tag, --exclude, bare clean) are unchanged and still act immediately.

Keep-all-but: fuzzy --exclude

The inverse of --tag: remove everything except fuzzy matches. Patterns are case-insensitive substrings tested against each entry's IP, tag, and hostnames, and --exclude is repeatable:

htb-hosts clean --exclude forest             # keep the forest box, clear the rest
htb-hosts clean --exclude forest --exclude vpn

Backup & restore

Every write drops an automatic snapshot (last 5 kept). You can also take named snapshots that are never auto-pruned, and roll back:

htb-hosts backup --label before-pivot   # explicit snapshot
htb-hosts restore --list                # show snapshots (auto + saved)
htb-hosts restore                       # roll back to the most recent
htb-hosts restore before-pivot          # roll back to a named/substring match

MCP integration

htb-hosts includes a stdio MCP server so MCP-aware agents (e.g. Claude Code) can manage hosts natively. make install registers it; to register by hand:

claude mcp add -s user htb-hosts -- python3 /opt/htb-hosts/mcp_server.py

htb_hosts_add, htb_hosts_remove, htb_hosts_show (accepts patterns), htb_hosts_select, htb_hosts_clean (accepts match/exclude/dry_run), htb_hosts_retag, htb_hosts_backup, htb_hosts_restore, htb_hosts_list_backups.

How it works

Everything the tool manages lives between two markers:

# >>> htb-hosts >>>  (managed by htb-hosts; run `htb-hosts clean` to remove)
10.10.11.161	forest.htb dc01.forest.htb  # tag=forest added=2026-07-11
# <<< htb-hosts <<<

Lines outside the markers (localhost, IPv6, anything you added by hand) are never touched.

Write access is granted once via a POSIX ACL:

setfacl -m u:youruser:rw /etc/hosts

Because a non-owner can't re-apply an ACL, the tool edits /etc/hosts in place (open r+, rewrite, truncate) under an flock; it never renames a temp file over it, which would drop the ACL and flip ownership. All input is strictly validated so nothing can inject extra lines, and the prior contents are snapshotted before every change. If the ACL is ever lost, htb-hosts doctor prints the exact command to restore it (doctor also flags a mangled managed block, e.g. an orphaned marker).

Security notes

  • The ACL is broader than the tool. setfacl -m u:you:rw /etc/hosts lets any process running as your user rewrite the whole file and redirect name resolution system-wide; the managed block is a convention the tool honors, not something the kernel enforces. That's the deliberate trade-off for sudo-free use; make it on a personal lab machine, not a shared or production one. make purge removes the ACL again.

  • Backups outlive clean. Snapshots under ~/.local/state/htb-hosts keep old box/engagement hostnames after you wipe the block. The directory is created 0700 (snapshots 0600); delete snapshots by hand if that history matters.

Configuration

Variable

Default

Purpose

HTB_HOSTS_FILE

/etc/hosts

Target hosts file (handy for testing)

HTB_HOSTS_BACKUP_DIR

~/.local/state/htb-hosts

Where snapshots are stored

HTB_HOSTS_KEEP

(empty)

Comma-separated domain substrings to keep outside the block on migrate (e.g. a homelab domain: HTB_HOSTS_KEEP=corp.lan,homelab.internal)

Development

make test     # stdlib unittest suite (no root, /etc/hosts untouched)
make smoke    # quick end-to-end CLI check against a throwaway file
make lint     # black --check + pylint (gated at 10.00/10)
make audit    # uv audit of the locked dev deps + zizmor over .github/
make help     # list all targets

The dev toolchain (black, pylint, zizmor) is pinned in uv.lock and run through uv run --locked; make lint UV_RUN= uses whatever is already on your PATH.

Tests load the modules directly from src/, so they exercise the in-repo copy regardless of what's installed under /opt, and each test runs against a throwaway temp file, so your real /etc/hosts is never touched. Coverage includes input validation/injection rejection, add/merge/rehome/idempotency, clean/exclude, migration + tagging, backup/restore (including snapshot permissions, symlink and tamper refusal, and the warn-but-don't-block behavior on backup failure), doctor's marker-integrity check, the in-place-edit (inode-preserving) invariant that protects the ACL, flock concurrency, and the full CLI + MCP surfaces.

Layout

src/htb_hosts.py    core library (parse/validate/lock/backup)  → /opt/htb-hosts
src/mcp_server.py   zero-dependency stdio JSON-RPC MCP server   → /opt/htb-hosts
src/htb-hosts       CLI entrypoint                              → /usr/local/bin
completions/        zsh + bash tab completion scripts           → share/{zsh,bash-completion}
tests/              unittest suite (core, CLI, MCP)
Makefile            install / remove / lint / test targets
pyproject.toml      dev dependency group + black/pylint config (line length 100)
uv.lock             locked dev toolchain

License

MIT

Available Tools

9 tools
htb_hosts_addA

Add or update an HTB host entry in /etc/hosts (no sudo needed). Use this whenever you need a hostname like machine.htb to resolve to a box IP. Entries go in a managed block and can be cleaned later.

NameRequiredDescriptionDefault
ipYesBox IP, e.g. 10.129.45.2
tagNoOptional group tag (defaults to the box name) for bulk cleanup
hostnamesYesOne or more hostnames, e.g. ['machine.htb','www.machine.htb']. A single comma/space separated string also works.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden well: it discloses that it writes to /etc/hosts, that no sudo is required, that entries are isolated in a managed block, and that the write is reversible via later cleanup. It stops short of saying whether an existing hostname mapping is overwritten or what the call returns.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, each earning its place: what it does, when to use it, and how its effects are scoped/reversible. The key fact (no sudo) is front-loaded in the first sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter mutation of a system file with no annotations and no output schema, the description covers the essentials: where it writes, privilege requirements, scoping, and reversibility. Overwrite semantics for pre-existing hostnames are the one notable omission.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3; the description adds conceptual grounding by explaining the 'managed block' that the tag parameter's 'bulk cleanup' grouping relies on. That link between the tag and the cleanup lifecycle is real value beyond the schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb pair ('add or update') plus the exact resource and location ('HTB host entry in /etc/hosts'), which is unambiguous. It does not explicitly name the sibling it complements (e.g. htb_hosts_remove/htb_hosts_clean), but the verb is distinct enough from the other hosts_* tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use this whenever you need a hostname like machine.htb to resolve to a box IP' gives a concrete triggering condition with an example. It hints at the cleanup sibling ('can be cleaned later') but does not explicitly state when to prefer remove/clean/show instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

htb_hosts_backupA

Save an explicit snapshot of /etc/hosts (never auto-pruned).

NameRequiredDescriptionDefault
labelNoOptional label for the backup filename

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It does disclose a genuine lifecycle trait — the snapshot is never auto-pruned — but says nothing about where the backup is written, whether repeat calls create duplicates, or whether permission errors are possible for a write operation on /etc/hosts.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence, front-loaded with the action and target, with the non-pruned guarantee appended as a parenthetical. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-optional-param tool with no output schema, the description is close to sufficient, but it omits the return value (an identifier or filename an agent would need to later call htb_hosts_restore or htb_hosts_list_backups) and where the snapshot lives. Those are the remaining gaps an agent must discover empirically.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single 'label' parameter is described as an optional label for the backup filename, so the schema does the work. The description adds nothing about how the label affects filename collisions or ordering, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Save') and resource ('snapshot of /etc/hosts'), which cleanly separates it from siblings like htb_hosts_restore, htb_hosts_list_backups and htb_hosts_clean. It does not name a sibling explicitly, but 'explicit snapshot' implies a deliberate manual backup versus any automatic copy.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'explicit snapshot' and '(never auto-pruned)' imply the tool is for intentional, permanent backups before risky changes, but no when-to-use/when-not statement or alternative is given. An agent must infer that this is the pre-change safety step from the presence of htb_hosts_restore and htb_hosts_clean.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

htb_hosts_cleanA

Remove managed host entries. No args wipes the whole block; tag removes one box by its exact tag; match removes the entries htb_hosts_select would return for the same patterns (every pattern must match); exclude is the inverse keep-list, removing everything EXCEPT entries matching ANY pattern. The three are mutually exclusive. Set dry_run to preview what would go without touching the file.

NameRequiredDescriptionDefault
tagNoRemove only entries with this exact tag
matchNoRemove entries matching EVERY pattern (as htb_hosts_select)
dry_runNoReport what would be removed without changing the file
excludeNoFuzzy patterns to KEEP; everything else is removed

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden and does reasonably well: it discloses that the operation mutates a file, that the no-argument form destroys the entire block, and that dry_run previews without writing. It does not mention reversibility or the existence of the backup/restore siblings, which would matter for a destructive tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then one clause per mode, then the exclusivity rule, then dry_run. Dense and mostly waste-free, though the mode enumeration and the exclusivity sentence could be merged for tighter structure.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers all four optional parameters, the destructive default case, and the preview path, which is close to sufficient for a 4-param mutation tool with no annotations and no output schema. What's absent is what the operation returns and whether backups are taken automatically.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description adds genuine meaning on top by tying `match` to htb_hosts_select's semantics, framing `exclude` as its inverse keep-list, and declaring the three selection parameters mutually exclusive. Only `dry_run`'s interaction with the other modes (e.g. combined with no args) is left implicit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ("Remove managed host entries") and then enumerates the four operating modes, so the agent knows exactly what the tool does. It does not, however, differentiate itself from the sibling htb_hosts_remove, which an agent could easily confuse with this tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Each mode's selection condition is spelled out (no args = full block, tag = exact tag, match = htb_hosts_select semantics, exclude = inverse keep-list) and mutual exclusivity is stated explicitly. Missing is any guidance on when to prefer this over htb_hosts_remove, or any prerequisite/confirmation context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

htb_hosts_list_backupsA

List available /etc/hosts snapshots, oldest first.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description must carry the load; 'List available' implies a safe read and the 'oldest first' ordering is a genuine behavioral detail. However, it says nothing about return shape (names vs. paths), whether the list can be empty, or failure modes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with zero filler; the ordering detail is attached directly to the resource rather than buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter tool with no output schema, the description should at least indicate what a returned snapshot looks like so the agent can hand an identifier to htb_hosts_restore. It covers purpose and ordering but leaves the return-value contract unspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4. The description correctly implies no filtering or sorting options are needed to call it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List') and resource ('/etc/hosts snapshots'), plus the ordering ('oldest first'), which cleanly separates it from the mutating siblings htb_hosts_backup and htb_hosts_restore. It never names a sibling explicitly, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The listing purpose implies the workflow (inspect snapshots before htb_hosts_restore), but the description gives no explicit when-to-use, prerequisites, or named alternative. Usage is inferred rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

htb_hosts_removeB

Remove an HTB host entry from the managed block by hostname or IP.

NameRequiredDescriptionDefault
selectorYesHostname or IP to remove

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. It identifies an update to the managed block but does not say whether removal is idempotent, what happens if the host is absent, whether the change is reversible, whether a backup is created, or what permissions are required.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence that states action, target, scope, and selector format with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter tool with a complete schema, the definition is minimally adequate. However, as a mutation tool with no annotations or output schema, it should at least state idempotency, missing-host behavior, and relationship to backup/restore siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the single parameter is documented with 'Hostname or IP to remove'. The description repeats that the selector accepts a hostname or IP but adds no matching/format details beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (Remove) and resource (HTB host entry), and scopes it to the managed block by hostname or IP. This clearly separates it from siblings like htb_hosts_add or htb_hosts_show, though it does not explicitly name alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this versus htb_hosts_clean or htb_hosts_add, nor any prerequisites or exclusions. Usage is only implied by the mutation verb 'Remove'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

htb_hosts_restoreA

Restore /etc/hosts from a snapshot (most recent if no name is given).

NameRequiredDescriptionDefault
nameNoBackup name or substring to restore

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. 'Restore' implies overwriting the current /etc/hosts and the default-to-latest behavior is disclosed, but it never says the existing file content is replaced, whether a pre-restore backup is taken, or what privileges are required.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence that front-loads the verb and resource and packs the default-behavior rule into a parenthetical. Nothing is wasted and nothing needs to be scanned for.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-optional-parameter tool with no output schema, this covers the core action, but with zero annotations the omission of destructiveness (current hosts file is discarded), error behavior for unmatched names, and multi-match handling leaves meaningful gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so 'Backup name or substring' is already documented. The description adds real value by explaining the omission default (most recent snapshot), which the schema does not state for this optional parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (restore) plus resource (/etc/hosts) plus source (a snapshot), which cleanly separates it from siblings like htb_hosts_backup and htb_hosts_list_backups. It stops short of naming those siblings as the related steps, but the operation itself is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The parenthetical 'most recent if no name is given' tells the agent what happens when the parameter is omitted, which is genuine usage guidance. However, there is no statement of prerequisites, no mention that a backup must exist first, and no pointer to htb_hosts_list_backups for discovering names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

htb_hosts_retagA

Recompute every entry's tag from its box name (fixes bulk tag=imported).

NameRequiredDescriptionDefault

No parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It usefully discloses the blast radius ('every entry') and that tags are overwritten rather than merged, which is the key risk. It does not say whether manually curated tags are lost, whether the change is reversible, or whether it requires a populated host list.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with the action first and the motivating case in parentheses. Zero filler, nothing to trim.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a no-parameter tool with no output schema this is close to sufficient, but a bulk mutation with zero annotations and no reversibility warning leaves an agent guessing about side effects. A hint about backing up first (a sibling exists for exactly that) or about failure when a box name is missing would close the gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing for the description to disambiguate; baseline 4 applies. The description correctly implies the operation is global and requires no scoping arguments.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Recompute every entry's tag from its box name', which is clearly distinct from siblings like htb_hosts_add, htb_hosts_clean and htb_hosts_restore. It doesn't name an adjacent sibling (e.g. htb_hosts_clean) to sharpen the boundary, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'fixes bulk tag=imported' implies the triggering scenario, so an agent can infer when this tool is warranted. However, there are no explicit when-not conditions, no mention of prerequisites (e.g. that host entries must already exist), and no pointer to alternatives such as htb_hosts_backup before a bulk overwrite.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

htb_hosts_selectA

Look up managed entries by fuzzy pattern and return just their bare values, ready to feed into another command. patterns matches against ip/tag/hostname, and several patterns NARROW (every one must match). field picks what comes back: 'ip' (default) or 'host'. Use this to resolve a box name to its IP before scanning.

NameRequiredDescriptionDefault
fieldNoWhich values to return (default 'ip')
indexNoKeep only these 1-based values when a box has several (a hostname per vhost): 2, -1 for the last, the range '2-4', or the list '1,3'. Omit to return them all.
patternsNoFuzzy patterns, e.g. ['machine']; omit to match everything

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full load and does disclose key traits: read-style lookup, return of bare values only (not formatted output), and the non-obvious fact that multiple patterns NARROW rather than widen. It omits error/empty-match behavior and result ordering.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place, with the core action and output shape front-loaded before the matching semantics and the use case.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-param, 100%-covered, annotation-free read tool with no output schema, this covers purpose, output shape, and the tricky matching semantics. Only the `index` parameter's effect on results and empty-result behavior go unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning the schema lacks: that `patterns` matches against ip/tag/hostname and that multiple patterns are conjunctive, plus that `field` defaults to 'ip'. The `index` parameter is left entirely to the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource ('look up managed entries ... return just their bare values') and states the output shape, which implicitly distinguishes it from the sibling htb_hosts_show. It never names that contrast explicitly, so an agent must infer it, which keeps it short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a concrete use case ('resolve a box name to its IP before scanning') plus the AND-narrowing rule. It offers no explicit when-not guidance or named alternative among htb_hosts_show / htb_hosts_list-style siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

htb_hosts_showA

Structured overview of the managed hosts, both flat ('entries') and grouped by box ('groups'). patterns narrows to the entries they select, exactly as htb_hosts_select does. Set full=true to also include unmanaged/system entries (localhost, etc.).

NameRequiredDescriptionDefault
fullNoAlso include unmanaged entries
patternsNoFuzzy patterns to narrow to; omit for everything

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does disclose the main return structure and the effect of full=true. It does not explicitly state that the tool is read-only, nor does it cover permissions, side effects, or pagination behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short, front-loaded with the main return shape, and then explains the two parameters in context. Every sentence adds useful information without repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema and no annotations, so the description should ideally explain the returned structure more fully. It identifies top-level entries/groups and the full=true inclusion behavior, but it does not describe the fields within those structures or other relevant output details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds useful meaning: `patterns` narrows the selected entries exactly as htb_hosts_select does, and full=true includes unmanaged/system entries such as localhost. It clarifies that pattern filtering applies to entries rather than groups.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific resource and result shape: a structured overview of managed hosts, with both flat entries and grouped-by-box groups. It is clear what the tool returns, but it does not explicitly distinguish its purpose from siblings such as htb_hosts_select or htb_hosts_list_backups.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied through 'overview', the `patterns` narrowing behavior, and the `full=true` option for unmanaged/system entries. However, it does not explicitly say when to use this tool instead of htb_hosts_select or other sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 9 tool updatesv1.0.0
    • First observedhtb_hosts_add
    • First observedhtb_hosts_backup
    • First observedhtb_hosts_clean
    • First observedhtb_hosts_list_backups
    • First observedhtb_hosts_remove
    • First observedhtb_hosts_restore
    • First observedhtb_hosts_retag
    • First observedhtb_hosts_select
    • First observedhtb_hosts_show

TDQS

A3.9/5.0

Scored across 9 tools

Disambiguation4/5

Most tools have clearly distinct purposes: add/remove/show/select/retag/backup/restore/list_backups are easy to separate. The main overlap is between htb_hosts_remove and htb_hosts_clean, since both can remove managed entries by hostname/IP or pattern, though their descriptions clarify the difference.

Naming Consistency5/5

All tools use the same htb_hosts_ prefix and snake_case verb-based naming. The pattern is predictable throughout, including list_backups as a verb_noun variant.

Tool Count5/5

Nine tools is well-scoped for a focused /etc/hosts management server. Each tool covers a meaningful operation: entry lifecycle, querying, cleanup, tagging, and backup/restore.

Completeness5/5

The surface covers the full lifecycle: add/update, remove, patterned cleanup, structured and bare-value lookup, retagging, snapshot creation, restore, and backup listing. No obvious operations are missing for managing a managed hosts block.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    A
    maintenance
    All-in-one homelab management MCP server. Docker monitoring, volume backup/restore (with compose and env files), Wake-on-LAN, network scanning, and multi-server SSH management.
    44
    315
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Zero-config SSH/SFTP MCP server that lets an LLM client open temporary SSH/SFTP sessions to remote hosts, run commands, and upload/download files without holding any pre-baked credentials.
    17
    11 npm
    2
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    Local AI ops broker that keeps SSH secrets on your machine, exposes intent-level MCP tools to agents, and requires approval via a loopback Web UI for dangerous writes.
    14
    1 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Turns any Linux server into an AI-agent-accessible machine over HTTPS, allowing MCP clients like ChatGPT, Claude, and Grok to securely control files, run shell commands, inspect system state, query SQLite, and work with git behind a bearer token.
    107 npm
    4
    MIT