Skip to main content

catalog-audit

Audit existing ToolHive catalog server entries for drift: whether the pinned image still exists, the upstream repo is still alive and active, and the declared env vars and network-permission profile still match what the server actually needs. Use whenever asked to audit, health-check, sweep, or spot-check catalog entries / server.json files for staleness, broken images, dead repos, abandoned projects, or wrong env-vars/permissions - for the community tier, the official tier, the whole registry, or a named subset. Report-only; it never edits entries. NOT for reviewing a new submission (use mcp-review) or creating one (use add-mcp-server).

Informations de source

Dépôt
stacklok/toolhive-catalog
Dernière activité de la source
27 juin 2026 à 12:01
Langue détectée de SKILL.md
anglais
Étoiles
23
Forks
40

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Explorateur de fichiers
4 fichiers

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
catalog-audit
description
Audit existing ToolHive catalog server entries for drift: whether the pinned image still exists, the upstream repo is still alive and active, and the declared env vars and network-permission profile still match what the server actually needs. Use whenever asked to audit, health-check, sweep, or spot-check catalog entries / server.json files for staleness, broken images, dead repos, abandoned projects, or wrong env-vars/permissions - for the community tier, the official tier, the whole registry, or a named subset. Report-only; it never edits entries. NOT for reviewing a new submission (use mcp-review) or creating one (use add-mcp-server).
allowed-tools
Read Grep Glob Bash WebFetch Task
# Catalog audit Audit catalog entries that are **already in the registry** for three kinds of drift: 1. **Still valid** - the pinned OCI image still resolves; `repository.url` still loads. 2. **Still active** - the upstream repo isn't archived/disabled and isn't stale. 3. **Still canonically correct** - declared env vars and the network-permission profile match what the upstream project actually documents and requires. This is **report-only**. Produce findings for a human to triage; never edit a `server.json`, open a PR, or change permissions. The output is a dated markdown report under `audits/`. Checks 1 and 2 are mechanical and run via the bundled script. Check 3 needs judgment over upstream docs and is done by fanning out sub-agents. Grading rules and severity live in [references/audit-criteria.md](references/audit-criteria.md) - read it before writing findings. ## Step 1 - resolve scope Infer scope from the request, don't ask for rigid flags. Map intent to a server set: - "the community servers" / "community tier" -> `--tier community` - "official servers" -> `--tier official` - "the whole catalog" / "everything" -> `--tier all` - "re-check X, Y, Z" / a list of names -> `--names X,Y,Z` - a specific registry tree -> `--registry toolhive|official|all` (default `toolhive`) The repo has two server trees: `registries/toolhive/servers/` (contribution path, default) and `registries/official/servers/` (curated subset). Default to `toolhive` unless the user clearly means otherwise. Skills (`registries/toolhive/skills/`) are **out of scope** unless explicitly asked. If asked, audit them separately (their `packages[]` carry `registryType: git` with a `ref`/`subfolder` and `registryType: oci` images - check the git ref resolves and the repo is active; there are no env vars or network permissions to canonicalize). State the resolved scope and the entry count back to the user before crawling, so a mistaken scope is caught early. ## Step 2 - mechanical checks (script) Run the bundled deterministic script. It needs `gh` (authenticated) and `docker` or `skopeo` on PATH. ```bash python3 .claude/skills/catalog-audit/scripts/check_entries.py \ --tier community \ --out <scratch>/mechanical.json ``` Use `--names a,b,c` for a subset, or `--paths .../server.json ...` for exact files. The script prints a JSON array (also written to `--out`): per entry it reports `imageExists` / `imageMethod`, `repoResolves`, `archived`, `disabled`, `lastPushISO`, `monthsStale` / `isStale`, `openIssues`, plus `dockyard` and `tier`. `null` on an image/repo field means inconclusive (tooling couldn't run / transient), **not** a pass. It also reports `officialDrift`: for an Official-tier entry, whether its `registries/official` mirror has drifted from the `registries/toolhive` source - `false` (in sync), a list of differing top-level keys (e.g. `["repository"]`), or `null` (no mirror, e.g. Community-tier). A non-empty list is a finding worth reporting and means a fix needs applying to both copies. ## Step 3 - deep canonical-correctness checks (sub-agents) For each in-scope entry, spawn a sub-agent to do check 3. Keep it cheap: these are independent, doc-reading tasks. For a handful of entries, launch `Task` agents in parallel (batches of ~8). For a large sweep (dozens), prefer the `Workflow` tool to pipeline the fan-out if the user has opted into it; otherwise batch `Task` agents. Give each sub-agent: - the `server.json` path and its parsed env vars + `permissions` block, - the `repository.url` (and note if `dockyard:true`, so it reads the upstream repo, not the dockyard wrapper), - the relevant criteria from [references/audit-criteria.md](references/audit-criteria.md). Instruct each agent to read the upstream README and relevant source (via `gh api repos/{owner}/{repo}/readme`, `gh api`/`get_file_contents` for files, `search_code` for env-var references, or `WebFetch`), then return **structured findings only**: ```json { "name": "<server>", "envVars": [{"name": "...", "issue": "...", "severity": "...", "evidence": "<url-or-file:line>"}], "permissions": [{"issue": "...", "severity": "...", "evidence": "..."}], "couldNotVerify": ["..."] } ``` Each finding must cite upstream evidence (a URL or `file:line`). Findings without evidence are not actionable - drop them or mark `couldNotVerify`. ## Step 4 - verify findings before reporting (adversarial) Single-pass deep checks over-report - this is not optional cleanup, it's a core step. A cheap finder reliably flags plausible-but-wrong issues: a host that a leading-dot `allow_host` already covers, an "unused" var its own evidence shows is used, an `insecure_allow_all` that is actually justified, a 401 from a healthy OAuth-gated remote. For every high/critical finding (and ideally all of them), spawn an **independent agent - a stronger model than the finder** - to re-check it against upstream, prompted to refute by default: "confirm only if you can re-derive this from upstream; mark refuted if the entry is actually correct; uncertain if you can't tell." Drop refuted findings; keep confirmed ones with the verifier's note. In the first official-tier run this stage refuted ~6 high and ~21 medium false positives that had survived the finder. When fixes are later applied, re-verify each one against upstream while editing (grep the actual var name / host) - a cheap third check that catches the cases a verifier still misses (e.g. a contested host the second pass got wrong). ## Step 5 - merge and write the report Merge mechanical results (step 2) with deep findings (step 3) into severity-ranked findings using the scale in the criteria file. Write to `audits/<scope>-<YYYY-MM-DD>.md` (create `audits/` if absent; get the date with `date +%F`). Use this structure: ```markdown # Catalog audit - <scope> - <date> Scope: <description> (<N> entries). Methods: docker/skopeo image probe, gh repo API, sub-agent upstream-doc review. Report only - no entries were modified. ## Summary | entry | image | repo | active | env issues | perm issues | worst | |-------|-------|------|--------|-----------|-------------|-------| ... ## Critical ... ## High ... ## Medium ... ## Low ... ## Could not verify <entries/fields where a check was inconclusive> ## Clean <entries with no findings> ``` Each finding lists the entry, category, detail, evidence (URL/command), and a suggested action for the human (since this is report-only). Lead with the worst. ## Step 6 - hand off Show the user the summary table and the top findings inline. Do **not** commit the report or edit any entry unless the user explicitly asks. If they want fixes, that's a separate pass (and `mcp-review` / `add-mcp-server` cover the editing rules). When fixing an Official-tier entry, remember it has a mirror copy (see Notes) that must be updated too. ## Notes - **Inconclusive is not clean.** Surface `null` image/repo results and unreachable upstream docs as "could not verify," never as passing. - **Check wildcard coverage before flagging a missing host.** `allow_host` is Squid-style: a leading-dot entry (`.example.com`) already matches every subdomain. List the actual `allow_host` and confirm the needed host isn't already covered before reporting it missing. (Both the finder and a verifier missed this on `aws-documentation` in the first run.) - **A remote endpoint returning 401/403 is alive,** not a finding - it's auth/OAuth-gated. Only DNS failure, connection refused, 404, 5xx, or TLS errors mean it may be down. - **Official-tier entries are mirrored in `registries/official/servers/`** (a copy, not a symlink). Flag when an entry's `registries/official` copy has drifted from its `registries/toolhive` source - that drift is itself a finding. And any fix to an Official-tier entry must be applied to both copies (CI reconciles only the auto-populated `metadata` / `tool_definitions`, not the hand-edited fields). - **Be fair on staleness.** A small, finished server can be quiet for good reasons; weigh `monthsStale` against the server's scope before flagging. - **Be fair on `insecure_allow_all`.** Servers that reach arbitrary user-supplied hosts (fetch, scrapers, browsers, db/cluster/registry clients) may legitimately need it; flag it only where a concrete scoped host list is feasible, and propose that list.
Voir sur GitHub