{"$schema":"https://verifymcp.io/schemas/trust-report.json","schemaVersion":1,"license":{"name":"CC BY-NC 4.0","url":"https://creativecommons.org/licenses/by-nc/4.0/"},"generatedAt":"2026-11-05T18:45:32.913Z","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp","markdownUrl":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp.md","server":{"slug":"lkopietz3-byte-honesty-mcp","name":"honesty-mcp","registryName":"io.github.lkopietz3-byte/honesty-mcp","description":"MCP server exposing 11 honesty-SDK kits (grounding, trust, audit, corroboration) as agent tools.","registryStatus":"active","deletedAt":null,"statusMessage":null,"liveness":"live","publisher":{"class":"unknown","claimed":false}},"component":{"slug":"honesty-mcp","type":"npm","identifier":"honesty-mcp","withdrawn":false,"url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp","version":"0.3.0","transport":"stdio","scoredAt":"2026-11-05T03:54:10.183Z"},"score":{"total":88,"tier":"high trust","status":"scored","weekDelta":-3,"history":[{"date":"2026-11-05","total":88},{"date":"2026-11-04","total":91},{"date":"2026-11-03","total":91},{"date":"2026-11-02","total":91},{"date":"2026-11-01","total":91},{"date":"2026-10-31","total":91},{"date":"2026-10-30","total":91},{"date":"2026-10-29","total":91},{"date":"2026-10-28","total":91},{"date":"2026-10-27","total":91},{"date":"2026-10-26","total":90},{"date":"2026-10-25","total":90},{"date":"2026-10-24","total":89},{"date":"2026-10-23","total":89},{"date":"2026-10-22","total":88},{"date":"2026-10-21","total":88},{"date":"2026-10-20","total":87},{"date":"2026-10-19","total":87},{"date":"2026-10-18","total":86},{"date":"2026-10-17","total":86},{"date":"2026-10-16","total":86},{"date":"2026-10-15","total":85},{"date":"2026-10-14","total":85},{"date":"2026-10-13","total":50},{"date":"2026-10-12","total":50},{"date":"2026-10-11","total":74},{"date":"2026-10-07","total":73},{"date":"2026-10-05","total":72},{"date":"2026-10-04","total":71},{"date":"2026-10-03","total":71}]},"categories":[{"name":"Supply Chain Security","score":99,"verdict":"partial","reasons":["No malware found by supply-chain analysis.","No known CVEs affecting this package version or its production dependencies.","No install/post-install scripts declared.","30 of 103 dependencies flagged as unhealthy."],"codes":[{"code":"supplychain.malware_clean","args":{}},{"code":"cve.none","args":{}},{"code":"installscript.none","args":{}},{"code":"dephealth.assessed","args":{"deps":"103","unhealthy":"30"}}]},{"name":"Provenance & Transparency","score":100,"verdict":"pass","reasons":["Source repository is publicly reachable at the declared URL.","Cryptographically verified build provenance (signed, bound to lkopietz3-byte/honesty-mcp).","Clear OSI-approved license (MIT).","Actively maintained (last published 23 days ago).","Publishes a security disclosure policy (SECURITY.md)."],"codes":[{"code":"provenance.repo_verified","args":{}},{"code":"provenance.verified","args":{"repo":"lkopietz3-byte/honesty-mcp"}},{"code":"license.osi","args":{"spdx":"MIT"}},{"code":"maintenance.recent","args":{"age_days":"23"}},{"code":"disclosure.present","args":{}}]},{"name":"Schema Quality & AI Usability","score":59,"verdict":"fail","reasons":["AI-judged instruction clarity (excellent).","Context-footprint check failed: tool/resource definitions use about 6203 tokens (~477/item across 13 items; 13 tools + 0 resources), over budget; trim descriptions and params.","Usage-examples check failed: none of the tools include examples."],"codes":[{"code":"schema.ai_quality","args":{"band":"excellent"}},{"code":"schema.footprint_heavy","args":{"avg":"477","items":"13","tools":"13","tokens":"6203","resources":"0"}},{"code":"schema.examples_absent","args":{}}]},{"name":"Stability & Change Management","score":73,"verdict":"partial","reasons":["Stability observed for 22 of 30 days with no destabilising changes; credit accrues until the full window elapses."],"codes":[{"code":"stability.building_history","args":{"days":"22"}}]},{"name":"Tool Coverage","score":99,"verdict":"partial","reasons":["100% of tools have a non-trivial description (not blank, and not just the tool's name).","98% of tool parameters carry a description."],"codes":[{"code":"toolquality.descriptions","args":{"pct":"100"}},{"code":"toolquality.param_docs","args":{"pct":"98"}}]},{"name":"Tool Safety","score":100,"verdict":"pass","reasons":["No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.","We read all 13 captured tool definition(s), and no name or description among them implies an irreversible operation.","An AI judge read all 14 captured unit(s) of tool text and found none that tries to manipulate the model reading it."],"codes":[{"code":"toolsafety.injection_clean","args":{}},{"code":"toolsafety.destructive_none","args":{"tools":"13"}},{"code":"toolsafety.manipulation_clean","args":{"units":"14","judged":"14"}}]},{"name":"Capabilities","score":100,"verdict":"pass","reasons":["Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28."],"codes":[{"code":"protocol.supported","args":{"latest":"2026-07-28","version":"2025-11-25"}}]}],"inconclusive":[],"malware":[],"components":[{"slug":"honesty-mcp","type":"npm","identifier":"honesty-mcp","withdrawn":false,"score":88,"current":true,"url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp","markdownUrl":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp.md"}],"facts":[{"label":"Registry","value":"npm"},{"label":"Package","value":"honesty-mcp"},{"label":"Version","value":"0.3.0"},{"label":"Transport","value":"stdio"}],"install":{"available":true,"bundleSha256":null},"tools":[{"name":"check_grounding","title":"Check citation grounding","description":"Checks citation markers and lexical support in AI-generated text. Splits `text` into checked units and classifies each one against `evidence`: 'grounded' (cites a marker accepted by the default lexical support matcher), 'placeholder' (an honest '[TK]'/'[citation needed]' gap), 'ungrounded' (an uncited unit without a placeholder), or 'invalid' (cites a marker id that is missing from `evidence`, or whose evidence is rejected by the default support matcher; this outranks every other status). 'invalid' means the unit needs human review. It does not establish that a citation was fabricated, and it covers both a missing id and a matcher rejection. Each unit carries `reasons` (per cited id: supported, not-supported, no-content-words, invalid-evidence or unknown-id), and `nonClaims` lists scaffolding lines (rules, table separators, bare fences) that were set aside. This is a mechanical check, not a truth checker. The default support matcher counts overlapping words. It rejects some faithful paraphrases (evidence '65% of the audio is English' against the claim 'about two thirds of the audio is English'), and it accepts a wrong figure or a negated claim when most other words overlap ('trained on 68,000 hours' passes against evidence of 680,000 hours; 'does not support real-time transcription' passes against evidence that it does). It cannot verify that the evidence itself is true. Use this before shipping any AI-written report, summary, or answer that cites sources, to find citations that need a person to look: send every 'invalid' unit to review, and treat 'ungrounded' units as claims that should probably cite something but currently don't. A 'grounded' unit is not confirmed true. For higher-stakes content, use grounding-kit directly with a custom `supports()` function (embedding-similarity or NLI-based) instead of the default matcher.","inputs":[{"name":"evidence","type":"object","required":true,"description":"Map of citation marker id -> the evidence text/span it claims to support. This is the closed world: a marker cited in `text` whose id is NOT a key here is flagged invalid, and a marker whose evidence…"},{"name":"text","type":"string","required":true,"description":"The AI-generated text to check (up to 2,000,000 characters). Citation markers use the kit's default convention `[[cite:id]]` (e.g. \"The bridge opened in 1932 [[cite:source-a]].\"). This tool uses the…"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":607},{"name":"corroborate_evidence","title":"Grade evidence corroboration for a claim","description":"Grades the supplied evidence for a claim and reports two things: the evidence direction ('supports', 'contradicts', 'mixed' or 'none') and a verdict for how strong the evidence is in that direction. Read the direction first: a 'confirmed' verdict with direction 'contradicts' means the supplied evidence strongly contradicts the claim. The grade uses distinct normalized source identities and caller-assigned signal kinds. Sources are counted by independent origin, not by string: spellings of one page (host letter case, percent-escape case, a trailing host dot, an empty query, #fragment, default port) are one source, and so are pages of one site or repository, hosts that share a registered domain, and a copy next to its upstream. The result's `groups` says which signals were merged and why. Declare `origin` or `derivedFrom` on a signal when you know better, or pass `inferOrigins: false` to count by page only. Independence is not verified. 'confirmed' requires 2+ distinct sources in the same direction (supporting OR contradicting) AND at least one non-textual signal in that direction. Disagreement among sources surfaces as 'mixed' rather than being averaged away; a null result is 'not-found' only under adequate coverage, otherwise 'inconclusive' (a thin sample can't prove a negative); and thin coverage caps the verdict below 'confirmed' no matter how clean the signals look. Use this whenever several pieces of evidence were gathered for a claim (by you, another tool, or a research/verification pass) and you need an honest, non-inflated verdict instead of eyeballing how many checks 'passed'.","inputs":[{"name":"coverage","type":null,"required":true,"description":null},{"name":"inferOrigins","type":"boolean","required":false,"description":"[corroboration-kit 0.3+] Default true: pages of one site or repository, and hosts that share a registered domain, count as one source. Pass false to count by page (spellings of one page still merge,…"},{"name":"signals","type":"array","required":true,"description":"The evidence signals gathered about the claim. May be empty."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":446},{"name":"check_payout_invariance","title":"Check whether a ranking engine ignores payout (static-imports only)","description":"Checks whether payout-related identifiers (commission, payout, affiliate rate) appear in the source of a ranking/recommendation engine. Only `static-imports` mode is available: running your ranking function under payout-mutation scenarios (`runtime` mode) is turned off because it runs caller-supplied JavaScript. The server operator can turn it on by setting HONESTY_MCP_ENABLE_CODE_EXEC=1; that runs the code with the server's full filesystem, network and environment access, and the worker thread only bounds time. `static-imports` mode greps source files you supply for any reference to payout-related identifiers, to assert the ranking engine's code never even has payout data in scope. You send the file contents as a map of path -> content; this server does not read paths from disk, and a list of paths is rejected. Matching is whole-word and case-insensitive: the identifier `commission` is NOT matched inside `commissionRate`, `commission_rate`, `affiliateUrl` or `payoutPerClick`, so those names pass as CLEAN. Pass `matchIdentifierParts: true` to also find an identifier as one part of a longer camelCase, snake_case, SCREAMING_CASE or kebab-case name (it still does not match plurals such as `affiliates`, or a word fused into another with no separator, such as `mypayout`). It is a best-effort text/regex grep, not a real parser (it won't catch a dynamically-built import specifier or a re-export under an aliased name). A CLEAN result means no match in the text you sent, not that the engine is payout-neutral in general; re-run this in CI whenever the ranking logic changes.","inputs":[{"name":"caseInsensitiveMatch","type":"boolean","required":false,"description":"[static-imports mode] Case-insensitive identifier matching. Default true."},{"name":"files","type":null,"required":false,"description":"[static-imports mode, required, at least one file] Source files to scan for payout references, as a map of path -> content. A list of paths is an error. An empty map is a tool error, never a CLEAN re…"},{"name":"matchIdentifierParts","type":"boolean","required":false,"description":"[static-imports mode, payout-invariance-kit 0.3+] Default false (whole-word matching, so `commission` does not match `commissionRate`). When true, an identifier is also found as one part of a longer…"},{"name":"mode","type":"string","required":true,"description":"Which check to run. Only `static-imports` is available."},{"name":"payoutIdentifiers","type":"array","required":false,"description":"[static-imports mode, required, non-empty] Identifiers that must never appear in the ranking engine's source, e.g. \"commission\", \"payout\", \"affiliateRate\". Each is matched as a whole word (`commissio…"},{"name":"stripComments","type":"boolean","required":false,"description":"[static-imports mode] Strip comments before matching, so a mention in a comment doesn't count. Default true."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":671},{"name":"score_trust_identified","title":"Score an entity from known contributors","description":"Scores one entity (or one dimension of one entity -- quality, reliability, communication, ...) from signals contributed by KNOWN, identified sources: reviewer accounts, raters, inspectors, verified buyers. Weighs each signal by tier x source x proof-strength x reputation x recency decay, sums to an effective (credibility-weighted) sample size, and shrinks the result toward a domain baseline ('prior') by a configurable dial -- thin evidence stays close to the prior, deep evidence overrides it. Signals whose combined weight is 0 contribute nothing; when no signal carries weight, confidence is 'insufficient' and the score equals the prior. Evidence dated more than one day after `now` is scored as undated (its recency uses `missingDateAgeDays`). Every signal's `tier`, `source` and `proof` must be a key of the matching weight table, or the call is an error that names the missing key. The built-in example configuration accepts tier new | standard | verified | expert, source imported | referred | direct, and proof none | self_attested | verified | documented; override them with `config.tierWeights`, `config.sourceWeights` and `config.proofWeights`. Inputs that push a derived value past a finite number (for example an enormous dial or weight) are a tool error. Use this for trust/reputation scores backed by attributable evidence. For unattributed/scraped signals with no identity behind them, use assess_anonymous_authenticity instead.","inputs":[{"name":"config","type":"object","required":false,"description":"Partial override merged over the library's illustrative EXAMPLE_IDENTIFIED_CONFIG (tiers new/standard/verified/expert). Real callers should supply their own tier/source/proof vocabulary for their dom…"},{"name":"dial","type":null,"required":false,"description":"Shrinkage strength: a named preset, or a raw phantom-prior-signal count. Defaults to 'balanced'."},{"name":"now","type":"string","required":true,"description":"ISO 'now' timestamp recency decay is computed against. Pass a fixed value for determinism."},{"name":"prior","type":"number","required":true,"description":"The domain/category baseline the score shrinks toward when evidence is thin."},{"name":"signals","type":"array","required":true,"description":"The identified signals to score from. May be empty (yields the prior, with insufficient confidence)."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":468},{"name":"assess_anonymous_authenticity","title":"Score how organic unattributed signals look","description":"Scores how organic a corpus of UNATTRIBUTED, scraped sentiment signals (crawled mentions, imported reviews with no verifiable identity, aggregator feeds) looks, weighing a positive composite of consensus/diversity/volume/recency against a heuristic penalty for two specific patterns: evidence concentrated in a single source type, and unusually uniform sentiment (near-maximal with near-zero variance). Neither pattern establishes fabrication, and source types are counted without verifying that they are independent. It cannot show that sentiment is fabricated or that any reviewer is fake, and varied sentiment spread across several sources isn't caught by these two checks. The score is not a sentiment ranking: the composite rewards positive consensus, so a strongly negative corpus scores lower than the same corpus with the sign flipped (with the example configuration, 20 signals at -0.9 across four source types score 46; at +0.9, 68), and an honest negative corpus can rank below a fake-looking positive one. Source labels are compared trimmed and case-folded ('Forum' and ' forum' are one type), and a source type counts as one only when its credibility x confidence is high enough (`config.fullCountWeight`), so the counted source types can be fewer than the labels. Treat a low score as 'looks statistically unusual in a specific way worth a human look', not as a finding. Signals with zero confidence, zero source weight or fully decayed recency carry no weight; a source type that is not a key of `config.sourceWeights` has credibility 0; when no signal carries weight, confidence is 'insufficient' and trustScore is null (no score is reported). Use this for reviews/mentions/buzz with no identity behind them. For signals from known, identified contributors, use score_trust_identified instead.","inputs":[{"name":"config","type":"object","required":false,"description":"Partial override merged over the library's illustrative EXAMPLE_ANONYMOUS_CONFIG -- omit to use the example config as-is."},{"name":"now","type":"string","required":true,"description":"ISO 'now' timestamp recency decay is computed against. Pass a fixed value for determinism."},{"name":"signals","type":"array","required":true,"description":"The unattributed signals to assess. May be empty."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":450},{"name":"check_provenance_claims","title":"Check claims for unbacked certainty language","description":"Scans reader-facing claims for certainty-implying language (\"(verified)\", \"independently verified\", \"guaranteed\", \"fact-checked\", \"100% accurate\", ...) that isn't backed by an appropriate provenance tier, plus tiers that require a sourceRef but don't have one, and claims carrying an unrecognized tier. Run it on any copy, marketing page, or AI-drafted content that makes factual-sounding claims before it ships. The default phrase list is a short starter list (11 phrases), not a taxonomy -- it will miss phrases it doesn't know about: compliance attestations ('SOC 2 certified', 'HIPAA-ready'), superlatives ('best-in-class') and 'clinically proven' all pass; extend `certaintyPhrases` for your domain. Phrases match as word prefixes (from the start of a word, with no end boundary), so a custom phrase 'proven' also reports 'provenance' (but not 'unproven'): list the exact words you mean and review each hit. The check does not read context: a limits statement such as 'Concurrent renames are outside this guarantee' is still reported for 'guarantee'. A negation word ('not', 'without', ...) suppresses a match only inside the same clause (a comma, semicolon, period, colon, !, ?, em or en dash, or line break ends it; a plain hyphen does not), after the last 'and'/'but', and within `negationWindow` characters. It is a window, not a parser, so it can still suppress an overclaim the negation does not govern. An empty result means no wording offenses were found under the configured rules; it does not verify the claims.","inputs":[{"name":"caseSensitive","type":"boolean","required":false,"description":"Case-sensitive phrase matching. Default false."},{"name":"certaintyPhrases","type":"array","required":false,"description":"Override the certainty-phrase vocabulary. Defaults to a generic starter list ('(verified)', 'independently verified', 'proprietary dataset', 'guaranteed', 'fact-checked', '100% accurate', ...)."},{"name":"certaintyRequiresTier","type":"array","required":false,"description":"Tiers strong enough to back certainty language. Default ['verified']."},{"name":"claims","type":"array","required":true,"description":"The claims to check."},{"name":"negationWindow","type":"integer","required":false,"description":"Maximum characters before a phrase match to scan for a negation word ('not', 'without', ...), cut off at the start of the clause. Default 40."},{"name":"requireSourceRefForTiers","type":"array","required":false,"description":"Tiers that must carry a visibly non-empty sourceRef (not only whitespace or invisible characters). Default ['verified']."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":546},{"name":"check_claims_registry","title":"Check public claims for stale or missing evidence","description":"Keeps public-facing product claims honest over time by checking each one against its own claimed evidence -- the SOC2-control-evidence pattern applied to marketing/product copy instead of compliance controls. Buckets every claim into 'current' (evidence present, review within policy), 'stale' (evidence present but `verifiedAt` is more than `maxAgeDays` x 24 hours before `now`, compared in exact milliseconds, or unparseable; `ageDays` is whole days rounded down and for display only, so a claim can show 90d and still be stale at `maxAgeDays: 90`), or 'unverified' (no evidenceRef, or a placeholder that shows no evidence: exactly TODO, TBD, N/A, none, '-' or 'see above', ignoring case -- this always wins over staleness, since a fresh date next to an empty or placeholder reference proves nothing). Use this as a periodic 'Monday-morning' review or a CI gate on a claims registry, to catch marketing copy that drifted out of sync with what the product actually does after a refactor. Note: this only checks that a reference EXISTS and is fresh, not that the thing it points to still supports the claim's text; no tool in this server verifies that (check_grounding checks citation structure in a document, not whether evidence supports a claim). Claim ids that show nothing (empty, whitespace or invisible characters only) are a tool error. The text summary escapes control and bidi characters as \\uXXXX; the JSON report keeps the raw strings.","inputs":[{"name":"claims","type":"array","required":true,"description":"The claims to evaluate."},{"name":"maxAgeDays","type":"number","required":true,"description":"Staleness policy: evidence older than this many days is flagged stale. 0 is valid (every claim must have been verified today or it's stale) -- the kit requires a finite number >= 0."},{"name":"now","type":"string","required":false,"description":"The moment to evaluate against: 'YYYY-MM-DD' (UTC midnight) or a timestamp with an explicit zone ('2026-02-01T09:30:00Z', '+hh:mm'). A zoneless timestamp is a tool error, not local time. Defaults to…"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":456},{"name":"append_audit_entry","title":"Append a tamper-evident audit-chain entry","description":"Appends one entry to an append-only, hash-chained audit log and returns the new (longer) chain. Each entry's hash binds its payload, index, createdAt, a fixed format tag (formatVersion, currently \"audit-chain-kit/v1\"), and the previous entry's hash together, so any later tampering with an earlier entry -- or an entry produced by an incompatible version of audit-chain-kit -- breaks the chain in a way verify_audit_chain will detect. Use this wherever you need a tamper-evident record of events (agent actions, approvals, state transitions) that a skeptical third party can later verify independently. This function does not persist anything itself -- store the returned chain (or just the new entry) in whatever your app already uses.","inputs":[{"name":"chain","type":"array","required":true,"description":"The existing chain, in order, exactly as previously returned/stored. Pass [] to start a new chain."},{"name":"payload","type":null,"required":true,"description":"Caller data for the new entry -- any JSON-serializable value."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":212},{"name":"verify_audit_chain","title":"Verify a tamper-evident audit chain","description":"Independently re-verifies a hash chain from genesis: recomputes every entry's hash and confirms each entry's prevHash matches the preceding entry's entryHash. Detects a mutated payload (stored entryHash no longer matches recomputed hash) and a severed link or spliced-out middle entry (prevHash mismatch) with no options at all. Two DIFFERENT truncation attacks need two DIFFERENT options, and neither is on by default: (1) entries deleted from the end and NOT replaced -- pass `expectedMinLength` to catch a chain that's simply shorter than it should be (a tail deletion alone leaves no broken pointer for the walk to find); this does NOT catch truncate-and-re-append (deleting tail entries and then appending new, self-consistent ones to reach the same length again -- `expectedMinLength` sees the 'right' length and passes). (2) to catch truncate-and-re-append, pass `anchor`: an `{ index, entryHash }` checkpoint you saved earlier from a source the chain's writer cannot edit (your own log, a separate append-only store). The chain is invalid unless the entry at `anchor.index` has exactly that `entryHash` -- this also catches a full rewrite from genesis, but entries after the anchor are only checked for internal consistency, not against anything external. Passing neither option means a truncate-and-re-append (or a full rewrite from genesis) can pass as 'valid'. An empty chain is 'valid' with nothing checked (newer kits report `entriesChecked: 0`). Proves the chain is internally consistent and unaltered since it was hashed (and, with `anchor`, unaltered up to the anchor point); it does NOT prove nobody with write access ever rewrote the whole chain from genesis when no anchor is supplied (tamper-evident, not tamper-proof). Use this to audit a chain you did not produce yourself before trusting it.","inputs":[{"name":"anchor","type":"object","required":false,"description":"A checkpoint obtained earlier from somewhere the chain's writer cannot change (your own log, a separate append-only store) -- e.g. `{ index: chain.length - 1, entryHash: chain[chain.length - 1].entry…"},{"name":"chain","type":"array","required":true,"description":"The chain to verify, exactly as stored/received."},{"name":"expectedMinLength","type":"integer","required":false,"description":"If you know how long the chain should be, pass it to catch entries deleted from the end and NOT replaced. Does NOT catch truncate-and-re-append (see `anchor`) -- a chain shortened and then extended b…"}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":614},{"name":"grade_decision","title":"Grade a decision against what happened after it","description":"Grades one recommendation-and-decision pair against a before/after observation log. Compares a pre-decision BASELINE window to a post-decision, exposure-aligned RESULT window on the same subjectId + checkKey, and returns 'holding' (the exposed post-decision window stayed under `refuteThreshold` bad observations AND its bad rate is lower than the baseline's), 'not-holding' (EITHER the exposed post-decision window hit `refuteThreshold` bad observations, OR its bad rate is not lower than the baseline's, even below that count -- 1 bad of 10 before, 1 bad of 3 exposed since is 'not-holding', and so is an exact tie such as 1 of 3 against 1 of 3), or 'refused' (the evidence didn't clear a floor -- see refusalCodes for exactly which one, never a vague 'unproven'). The rate comparison is exact -- it cross-multiplies the raw counts rather than comparing the rounded `badRate` fields or the sign of `badRateDelta`, so a `not-holding` can occur even when both windows display the same 3-place `badRate`. The refute bar is a fixed count, not a rate: 5 bad of 100 before and 2 of 500 since is 'not-holding' at the default threshold of 2, although the rate fell from 5% to 0.4%; for long windows, bound the window or raise `refuteThreshold`. Always show `badRateDelta` and the raw `baseline`/`result` counts next to the verdict, don't quote 'holding' on its own, and read `verdict` and `refusalCodes` rather than the prose sentence. The verdict grades the DECISION, not just whether advice was taken: a DISMISSED recommendation whose problem later surfaced also grades 'not-holding', because the evidence sided with the advice either way. Two things this tool refuses to let slide: (1) 'nothing has gone wrong since' only counts as a result if the baseline shows the problem existed before -- otherwise it's 'baseline_lacks_negative_signal'; (2) only observations where the advice could actually have applied (exposed === true) can create or reverse the headline verdict -- everything else is reported…","inputs":[{"name":"config","type":"object","required":false,"description":"Floors and thresholds, every field optional with a library default (see advice-ledger-kit's DEFAULT_GRADE_CONFIG). Omit entirely to use the library's defaults."},{"name":"decision","type":"object","required":true,"description":"The human's call on the recommendation."},{"name":"observations","type":"array","required":true,"description":"Every observation available. This tool does the filtering by subjectId + checkKey itself, so passing the whole ledger (observations for other subjects/checks too) is fine."},{"name":"recommendation","type":"object","required":true,"description":"The advice being graded."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":693},{"name":"compute_divergence","title":"Measure where two judges disagree, and who was right","description":"Computes how often two independent judges (e.g. an automated engine and a human override) rated the same object differently, and -- where a later outcome exists to settle it -- reports engineRight and humanRight as two SEPARATE counts, never combined into one blended accuracy number (a system can be right most of the time overall and still wrong every single time a human bothers to overrule it, and that second fact is the one worth acting on). Divergence needs BOTH a count floor (minDivergentCount) and a rate floor (minDivergentRate) before it's 'reportable' -- either alone lets noise through. Calibration (who was right) carries its own separate floor (minResolvedDivergent) and its own status, so a population can legitimately have reportable divergence and refused calibration at the same time: plenty of disagreements, not enough of them settled by a later outcome yet. Supply `group` on each pair (a custom config.groupBySource is off unless the server operator sets HONESTY_MCP_ENABLE_CODE_EXEC=1) to also get a sorted per-group breakdown alongside the overall report. Use this whenever a system has both an automated judgment and a human override/correction recorded for the same objects, to find out whether overruling the system is actually earning its keep. For grading one recommendation's own before/after outcome window instead of a whole population of engine-vs-human calls, use grade_decision.","inputs":[{"name":"config","type":"object","required":false,"description":"Floors, thresholds, and optional custom grouping, every field optional with a library default (see advice-ledger-kit's DEFAULT_DIVERGENCE_CONFIG). Omit entirely to use the library's defaults."},{"name":"pairs","type":"array","required":true,"description":"Every occasion both judges could have spoken on. Pairs missing one judgment are still counted, just not comparable."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":377},{"name":"scaffold_agent_receipts","title":"Scaffold the agent-receipt-kit authorization pattern","description":"agent-receipt-kit is a RUNTIME LIBRARY your own agent-orchestration code imports and calls at two specific moments (issue a WorkPacket before an agent runs, verify its AgentClaim after) -- it is not something this MCP server can 'check' on demand the way it checks a document's citations, because the packet only exists inside your application's own runtime. Call this tool to get the pattern explained, an install step, a copy-pasteable starter snippet for wiring issuePacket/verifyReceipt into your own agent loop, and (optionally) a live worked example run against the real kit -- one accepted claim, one rejected claim -- so you can see actual output before wiring it in. Use this when you're building or reviewing anything that lets an AI agent report back what it did (a coding agent, a browser-automation agent, a data-processing agent) and you don't yet trust that report by construction.","inputs":[{"name":"includeWorkedExample","type":"boolean","required":false,"description":"Also run a live accepted/rejected example against the real issuePacket/verifyReceipt, not just show a snippet."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":227},{"name":"scaffold_cost_governor","title":"Scaffold the cost-governor-kit spend-safety pattern","description":"cost-governor-kit is a RUNTIME LIBRARY your app installs and calls at the moment it's about to make an AI API call -- it is not something this MCP server can 'check' on demand the way it checks a document's citations. Its advisory check-then-commit piece (withReserveConfirm) needs a live UsageLedger backed by YOUR database and an async callback making the real call, neither of which exist as content to hand this tool. Call this to get all three pieces explained (estimated pre-call spend check, cache-aware pricing math, advisory successful-call usage counting), an install step, a copy-pasteable starter snippet, and (optionally) a live worked example: real checkPreCallCeiling calls (one allowed, one blocked), a real withReserveConfirm run against an in-memory demo ledger (one call under the limit, one over, one whose commit fails after a successful call), and a real estimateCostUsd comparison of the default 0.1x cache-read rate against a caller-supplied cacheReadPerMillion override. Use this when you're building or reviewing anything that calls a paid AI API and want a pre-call spend estimate plus usage counting that skips a call that threw -- NOT a strict concurrent limit and not proof a timed-out call was never billed by the provider (see concurrency_and_recovery in the output, and use withCapacityReservation instead if you need a real reservation).","inputs":[{"name":"includeWorkedExample","type":"boolean","required":false,"description":"Also run live examples against the real checkPreCallCeiling/withReserveConfirm, not just show a snippet."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":329}],"toolsTruncatedAtCapture":false,"diagnostics":{"capturedAt":"2026-11-05T03:54:10.000Z","track":"package","endpoint":null,"declaredUrl":null,"truncated":false,"tls":null,"dnssec":null,"auth":null,"httpsRedirect":null,"transports":[],"provenance":{"outcome":"verified","label":"Verified","reason":"verified","reasonLabel":"Verified","discovery":"attestation_endpoint","discoveryLabel":"Registry attestation endpoint","sourceRepo":null,"attestationSkipped":null,"attestationSkippedLabel":null},"installScripts":[],"installScriptsTotal":null,"vulnerabilities":[],"vulnerabilitiesTotal":null,"dependencies":{"nodes":103,"partial":false,"deprecated":null,"stale":30,"noRepo":null}},"mismatches":[],"changelog":{"trackingSince":"2026-09-28","recent":[{"id":"chg_01a1a9d7-bc5e-72a7-a824-d7168e2cd480","kind":"check.verdict","summary":"Stability (fail → 0.73)","materiality":"functional","direction":"neutral","scoreDelta":null,"occurredOn":"2026-11-05","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a1a9d7-bc5e-72a7-a824-d7168e2cd480"},{"id":"chg_01a1a9d7-bc62-784a-a863-c39c34a2c7b9","kind":"score.total_changed","summary":"Trust score (91 → 88)","materiality":"functional","direction":"regression","scoreDelta":-3,"occurredOn":"2026-11-05","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a1a9d7-bc62-784a-a863-c39c34a2c7b9"},{"id":"chg_01a17b70-9d82-7645-9500-935d4e8f1698","kind":"score.total_changed","summary":"Trust score (90 → 91)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-27","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a17b70-9d82-7645-9500-935d4e8f1698"},{"id":"chg_01a17124-2465-7d70-8466-aa87f414eef2","kind":"score.total_changed","summary":"Trust score (89 → 90)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-25","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a17124-2465-7d70-8466-aa87f414eef2"},{"id":"chg_01a166d4-a84a-73d6-a5b4-6a125b1dbca5","kind":"score.total_changed","summary":"Trust score (88 → 89)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-23","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a166d4-a84a-73d6-a5b4-6a125b1dbca5"},{"id":"chg_01a15c88-fdb2-7cf5-a715-903fc6ce7e8e","kind":"score.total_changed","summary":"Trust score (87 → 88)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-21","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a15c88-fdb2-7cf5-a715-903fc6ce7e8e"},{"id":"chg_01a15239-fe47-7b18-8e1d-88e9a34bdf52","kind":"check.reverified","summary":"Security disclosure (unverified → pass)","materiality":"functional","direction":"improvement","scoreDelta":null,"occurredOn":"2026-10-19","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a15239-fe47-7b18-8e1d-88e9a34bdf52"},{"id":"chg_01a15239-fe48-76f2-a29c-27a88a4395d0","kind":"score.total_changed","summary":"Trust score (86 → 87)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-19","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a15239-fe48-76f2-a29c-27a88a4395d0"},{"id":"chg_01a14d19-c8e5-7515-b267-90eea73a841d","kind":"check.unverifiable","summary":"Security disclosure (pass → unverified)","materiality":"functional","direction":"regression","scoreDelta":null,"occurredOn":"2026-10-18","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a14d19-c8e5-7515-b267-90eea73a841d"},{"id":"chg_01a142d5-7269-7901-9606-c9071b43a144","kind":"score.total_changed","summary":"Trust score (85 → 86)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-16","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a142d5-7269-7901-9606-c9071b43a144"},{"id":"chg_01a13b56-344e-77ce-a78b-a8214a7c889e","kind":"check.reverified","summary":"Stability (unverified → fail)","materiality":"security","direction":"regression","scoreDelta":null,"occurredOn":"2026-10-14","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a13b56-344e-77ce-a78b-a8214a7c889e"},{"id":"chg_01a13b56-344f-7351-928c-67b7eac35151","kind":"check.reverified","summary":"Injection markers (unverified → pass)","materiality":"security","direction":"improvement","scoreDelta":null,"occurredOn":"2026-10-14","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a13b56-344f-7351-928c-67b7eac35151"},{"id":"chg_01a13b56-344f-7762-90a1-5b371e90d9ae","kind":"check.measure","summary":"Schema quality (393 → 477)","materiality":"functional","direction":"regression","scoreDelta":null,"occurredOn":"2026-10-14","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a13b56-344f-7762-90a1-5b371e90d9ae"},{"id":"chg_01a13b56-344f-7b4b-8f17-933a5de9032e","kind":"check.reverified","summary":"Tool coverage (unverified → 100)","materiality":"functional","direction":"improvement","scoreDelta":null,"occurredOn":"2026-10-14","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a13b56-344f-7b4b-8f17-933a5de9032e"},{"id":"chg_01a13b56-3450-7047-8ab2-179f326c00bf","kind":"check.reverified","summary":"MCP protocol (unverified → pass)","materiality":"functional","direction":"improvement","scoreDelta":null,"occurredOn":"2026-10-14","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a13b56-3450-7047-8ab2-179f326c00bf"},{"id":"chg_01a13b56-3450-7431-b484-99ee05c581ce","kind":"score.total_changed","summary":"Trust score (50 → 85)","materiality":"functional","direction":"improvement","scoreDelta":35,"occurredOn":"2026-10-14","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a13b56-3450-7431-b484-99ee05c581ce"},{"id":"chg_01a13204-681e-7c79-a11e-788aa1b44334","kind":"check.unverifiable","summary":"Stability (0.43 → unverified)","materiality":"security","direction":"regression","scoreDelta":null,"occurredOn":"2026-10-12","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a13204-681e-7c79-a11e-788aa1b44334"},{"id":"chg_01a13204-681f-7e63-a8dc-e5885b16291f","kind":"check.unverifiable","summary":"Tool safety (pass → unverified)","materiality":"security","direction":"regression","scoreDelta":null,"occurredOn":"2026-10-12","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a13204-681f-7e63-a8dc-e5885b16291f"},{"id":"chg_01a13204-6820-7583-96eb-1a109be57c00","kind":"check.verdict","summary":"Provenance (fail → pass)","materiality":"security","direction":"improvement","scoreDelta":null,"occurredOn":"2026-10-12","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a13204-6820-7583-96eb-1a109be57c00"},{"id":"chg_01a13204-6820-7a63-a22d-ee1b981e6174","kind":"provenance.repo_changed","summary":"The attested source repository moved (lkopietz3-byte/honesty-mcp)","materiality":"security","direction":"neutral","scoreDelta":null,"occurredOn":"2026-10-12","url":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp#chg-chg_01a13204-6820-7a63-a22d-ee1b981e6174"}],"truncated":true,"feedUrl":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp/changelog.json"},"links":{"html":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp","markdown":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp.md","changelogJson":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp/changelog.json","changelogRss":"https://verifymcp.io/servers/lkopietz3-byte-honesty-mcp/honesty-mcp.xml","external":[{"label":"npm package","href":"https://www.npmjs.com/package/honesty-mcp"},{"label":"Socket report","href":"https://socket.dev/npm/package/honesty-mcp"},{"label":"Repository","href":"https://github.com/lkopietz3-byte/honesty-mcp"}]}}