SHPBL · Case study 06 · Unedited

The instrument reads itself

A pre-purchase evaluation of shpbl.com — this site, the MCP server that serves it, and the Collective Master Library behind both — run through the same repository audit and repair method we sell, by an independent reviewer using nothing but the public MCP surface. The findings below are printed as they were returned. Nothing was removed for being unflattering; the two items that were unflattering are the reason this study exists.

Verdict

Method sound, hygiene not. The staging, the refusals and the error messages held up under an adversarial pass. Three classes of defect did not: a literal substring search that made a 7,595-row library answer “not present” to ordinary questions, three disagreeing version numbers, and an ignore file that did not name environment files. All three are fixed in server 1.15.0.

What was run

ScopeEvery free tool, every gated tool, deliberate error paths, and two passes over this repository through this repository's own instrument
InstrumentSHPBL MCP — evaluate_repo, fix_repo, harvest_repo, library_search, library_search, library_document, subscription_status, list_repos, run_gauntlet
ReviewerIndependent, working only from the published surface and its own reasoning. The server ran no model.
Host lines changed by the run0 — the run only read; every repair below was written afterwards by hand

Findings, worst first

High · 1. No ignore rule for environment files, and .env is in the tree

fix_repo was asked for .gitignore and answered “Not in the tree, skipped.” That is the root cause; the symptom is a committed environment file carrying the backend project ID, URL and publishable key. Those three values are designed to be public, so this is not a breach — row-level security is the control that matters and it is enabled. The real defect is structural: with no rule, the next secret gets committed too. The instrument had already printed “An environment file is committed to the tree” and the maintainer shipped past its own warning.

Repair: ignore rules now name .env.local, .env.*.local and *.pem; private credentials live in the platform secret store, never the tree.

High · 2. Multi-word search returned zero

library_search (vault scope) returned 9 rows for webhook and 0 for webhook signature. library_search returned 0 for spend ceiling while the capability text of SUBP-07 contains both words. The cause was a single literal .includes() against the whole query, in tools whose own descriptions invite a plain-words phrase. A library of 7,595 rows looked empty to any agent that asked a normal question.

Repair: queries are split on whitespace and ANDed, ranked by which field matched — ID, then name, then capability, then API surface — and a search with no exact hit now returns the closest rows by term, labelled as such, instead of a bare empty array.

Medium · 3. Three different version numbers

subscription_status said 1.12.0, the served manifest said 1.10.0, the server definition said 1.4.0, and the package had no version at all under a scaffold name. A product that sells reproducible, citable runs cannot leave a caller guessing which build answered.

Repair: one constant, read by the server definition, the manifest and the package alike; the package is named and versioned to match.

Medium · 4. Stale instructions and unaccounted metering

The instructions string documented 14 tools while 21 were exposed, so seven were invisible to any client that trusted them. subscription_status named 6 metered and 8 free tools — 14 of 21 — leaving a paying customer unable to tell what burns allowance, and omitting list_repos, whose own description says it is free.

Repair: the metering lists are derived from the same tier table the gate itself reads, so they cannot drift from what charges; the instructions cover every tool.

Medium · 5. Protocol boilerplate ate the payload

A repair over 3,092 characters of source shipped roughly 4,500 characters of protocol first, and one runner step repeated the same narration block three times. On small work the caller paid more context for our instructions than for their code.

Repair: the method moved out of the payload into a free, unmetered method_protocol tool. Agents fetch it once and call the gated tools with brief: true, which spends the payload on source.

Low · 6. The spine heuristic was polluted

“Spine files (read these first)” listed 40 entries, 20 of them database migrations, twelve of those empty, plus a generated route tree, a stylesheet and vendored UI boilerplate — then reprinted twelve of them verbatim under “Heaviest files”.

Repair: generated files, vendored UI and sub-kilobyte migrations are filtered out of the spine, and the heaviest list now shows only what the spine did not already name.

Low · 7. Counts and papercuts

library_search reported 1,162 indexed components against a published 1,116, because rows from an excised class were still reachable through the index. One case study carried no upstream repository link, an evaluation line read “.env — 1 files”, and the package declared no typecheck script for a product whose remediation protocol demands a guard beside every diff.

Repair: the index parses to the published figure, the missing citation and the pluralisation are corrected, and typecheck is a first-class script.

What held up

Why this is published

Five case studies read other people's repositories. This one reads ours, and it is the only one where the author had something to lose by printing the result. The claim the whole library rests on is that an honest instrument will refuse a claim it cannot support — including about its own maker. That claim is worth nothing until it is tested where it costs something.