Skip to content
SKILLS
MCP ServerPublisher identity verifiedNo findings from static checks

@spboucher/research-ledger-mcpv1.0.0

Offline MCP server keeping a hash-chained, append-only ledger for preregistered research: hypotheses, protocol freeze and amendments, decisions, deviations, gates, runs, spending, results.

  • downloadable
  • installable
  • executable
Version
1.0.0
Published
Nov 10, 2026
Licence
MIT
Archive
47 kB
Files
11
Transport
stdio
Tools
21

Install

Register the local server

claude mcp add --transport stdio --env RESEARCH_LEDGER_ROOT=<value> research-ledger-mcp -- node server.mjs
.mcp.json (project scope)
{
  "mcpServers": {
    "research-ledger-mcp": {
      "command": "node",
      "args": [
        "server.mjs"
      ],
      "env": {
        "RESEARCH_LEDGER_ROOT": "${RESEARCH_LEDGER_ROOT}"
      }
    }
  }
}

Environment variables — set locally, never sent to the registry

VariableRequiredPurpose
RESEARCH_LEDGER_ROOToptionalProject root holding .research/ (default: working directory). Every file path must resolve inside it.
More steps
  1. 1Set the required environment variables locally

    RESEARCH_LEDGER_ROOT — configured on your machine only; never sent to the registry.

  2. 2Optional: download the listing's source archive for review

    skills download @spboucher/research-ledger-mcp@1.0.0
  • Declared permissions: shell, filesystem:read, filesystem:write.
  • This server runs locally on your machine with your user's privileges. Review the source before running it; the registry does not execute or host it.

Installing only copies or configures. Nothing is executed for you. The Skills CLI verifies the checksum before writing files.

Documentation

research-ledger-mcp

An MCP server that keeps the record of a preregistered study: what was hypothesised, what was fixed in advance, what was decided and when, what departed from the plan, what was run, what it cost, and what came out.

It is offline and deterministic. It never uses the network, never runs a command, and writes only inside .research/ in the project root.

Why

An agent that runs a study over several sessions forgets. It re-runs the costly step, tunes the specification after seeing the result, and reports the outcome as if it had been predicted. This server gives it a place to write things down that it cannot quietly rewrite, and derives the label "confirmatory" or "exploratory" from the timeline instead of taking anyone's word for it.

Install

Requires Node.js 20 or later.

shell
npm install

Claude Code:

shell
claude mcp add research-ledger --env RESEARCH_LEDGER_ROOT=/path/to/project -- node /path/to/research-ledger-mcp/server.mjs

Any MCP client (stdio):

json
{
  "mcpServers": {
    "research-ledger": {
      "command": "node",
      "args": ["/path/to/research-ledger-mcp/server.mjs"],
      "env": { "RESEARCH_LEDGER_ROOT": "/path/to/project" }
    }
  }
}
VariableMeaning
RESEARCH_LEDGER_ROOTProject root. Default: the working directory of the server. Every file path given to a tool must resolve inside it.

Tools

ToolWhat it does
init_projectCreate the ledger (once), with an optional budget
register_hypothesisRecord a hypothesis with its test and decision rule
freeze_protocolHash the protocol files and hypotheses into one root hash; refuses to freeze twice
verify_protocolRe-hash the frozen files; report which changed, went missing or were renamed
amend_protocolNew linked protocol version, with the reason and whether data had been seen
mark_data_accessRecord when outcome data are first opened
log_decisionQuestion, options, choice, rationale, before or after data (D-01, D-02…)
log_deviationProtocol said / done / why / impact on confirmatory status (V-01…)
open_gate, close_gateGo / no-go / conditional review, criteria recorded before evidence
check_rerunIs an identical run already on record, and was it expensive?
register_runCommand, hashes of code, inputs and outputs, seed, environment (R-01…)
record_spend, spend_report, set_budgetCost of paid calls, exact totals, budget remaining
record_resultEstimate, uncertainty, verdict; status derived by the ledger (X-01…)
log_question, resolve_questionOpen questions carried across sessions
statusEverything needed to resume
export_reportTransparency report, Markdown and JSON
verify_ledgerRe-compute the hash chain; pinpoint the first broken record

How a result gets its status

record_result never asks whether a result is confirmatory. It works it out:

SituationStatus
Hypothesis fixed by a protocol version frozen before outcome data; files intact; no deviationconfirmatory
Same, with deviations declared minorconfirmatory_with_deviations
No freeze before the resultexploratory
First freeze made after outcome data were accessedexploratory
Hypothesis registered after the last pre-data protocol versionexploratory
Protocol amended after data were seen, for this hypothesisexploratory (results recorded after the amendment)
A deviation declared exploratory appliesexploratory
Frozen files differ from the manifest when the result is recordedexploratory

Outcome data count as accessed from the first of: a mark_data_access record with outcome_data true, an amendment declared with data_seen true, or any recorded result.

Storage

text
.research/
  ledger.jsonl      one JSON record per line, append-only
  HEAD              sequence number and hash of the last record
  lock              present only while a record is being appended
  reports/          written by export_report with write: true

Each record is {seq, ts, type, data, prev, hash}. hash is the SHA-256 of the canonical JSON (sorted keys) of the other five fields; prev is the hash of the record before.

  • Atomic writes. The ledger is written to a temporary file, flushed to disk, then renamed over the old one. A writer that dies leaves either the old ledger or the new one, never half a record.
  • Locking. Appends are serialised by an exclusive lock file. Numbers (D-01, R-01…) are assigned inside the lock, so concurrent writers never receive the same one. A lock older than 30 seconds is treated as abandoned.
  • Corruption stops writes. If verification fails, every tool that appends refuses, and says at which record the chain broke.

What the chain proves, and what it does not

It detects a record that was edited, deleted, inserted, reordered or cut off, and reports the first affected line. The freeze manifest detects any change to a listed file.

It does not stop someone with write access from rebuilding the whole chain and HEAD from scratch: there is no secret key and no outside witness. If you need to prove to someone else what was fixed and when, copy the root hash returned by freeze_protocol (and, later, the head hash from verify_ledger) somewhere you do not control alone: a commit on a remote, a registry entry, a dated message.

Other limits to know:

  • Timestamps are the local clock of the machine. They are part of each hash but are not independently attested.
  • The server records what it is told. register_run hashes the files you list at the moment you call it; it does not execute or observe the run. mark_data_access, timing and data_seen are declarations. The ledger catches contradictions with its own timeline, not what was never written.
  • "Renamed" detection looks for identical content in the same directory only.
  • Costs are stored in millionths of a US dollar. One currency.
  • The whole ledger is rewritten on each append (that is what makes the write atomic). This suits thousands of records, not millions.
  • The lock is advisory and local: it does not coordinate writers on a network file system that lacks exclusive create.

Permissions

The server reads the files you list (to hash them) and writes inside .research/. It starts no process and opens no connection. The manifest declares shell only because the client launches it with node and the test suite starts worker processes to test concurrent writers.

Tests

shell
npm test

49 engine tests and 8 protocol tests, all offline, in temporary directories. They cover every tool, tampering (edited, deleted, inserted, swapped and truncated records), one-byte and renamed-file detection, refusal to refreeze, numbering under six concurrent writers, the expensive-run guard, exact spend arithmetic, status classification including an amendment after data, two simulated crashes during a write, and path confinement including symbolic links.

Licence

MIT

Tools

21 tools · declared by the publisher
ToolWhat it does
init_projectCreate the ledger for a project, with an optional budget
register_hypothesisRecord a hypothesis with its test and decision rule
freeze_protocolHash the protocol files and hypotheses; refuses to freeze twice
verify_protocolReport which frozen files changed, went missing or were renamed
amend_protocolNew linked protocol version with reason and data-seen flag
mark_data_accessRecord when outcome data are first opened
log_decisionRecord a decision: options, choice, rationale, timing
log_deviationRecord a departure from the protocol and its impact
open_gateOpen a go / no-go review with its criteria
close_gateClose a gate as go, no-go or conditional, with evidence
check_rerunCheck whether an identical run is already on record
register_runRecord a run: command, hashes, seed, environment, outputs
record_spendRecord the cost of paid calls
spend_reportTotals by provider, model and purpose; budget remaining
set_budgetChange the spending limit, with the reason
record_resultRecord a result; confirmatory status is derived
log_questionNote an open question for later sessions
resolve_questionRecord the answer to an open question
statusEverything needed to resume the project
export_reportTransparency report in Markdown and JSON
verify_ledgerRe-compute the hash chain; pinpoint the first broken record

Environment variables

VariableRequiredPurpose
RESEARCH_LEDGER_ROOToptionalProject root holding .research/ (default: working directory). Every file path must resolve inside it.

Files

11 files · 168 kB unpacked

Select a file to preview it. Files are shown as plain text and never executed.

Security & permissions

Declared permissions

  • shell
  • filesystem:read
  • filesystem:write

Static checks

  • lowscript spawns other processestest/offline.test.mjs

Static checks are advisory. They never certify that a package is safe. Compatibility entries are publisher claims unless marked verified.

Compatibility

  • claude-code · claimed
  • codex · claimed
  • cursor · claimed
  • generic-mcp · claimed

Versions

1 release · immutable
VersionPublishedSizeSHA-256State
1.0.0latestNov 10, 202647 kBaaf96afc922e…published

Publication history

  1. release.publish@spboucher/research-ledger-mcp@1.0.0by Simon-Pierre Boucher
  2. artifact.create@spboucher/research-ledger-mcpby Simon-Pierre Boucher
  • MCP ServerVerified publisher

    @spboucher/manuscript-audit-mcp

    MCP server for deterministic, offline audits of LaTeX and Markdown manuscripts: citations, cross-references, numbers, statistics reporting, tables, claims, style, replication statements, referee-report scaffold, version comparison.

    Latest version
    v1.0.0
    Licence
    MIT
    Updated
    5 h ago
  • MCP ServerVerified publisher

    @spboucher/xlsx-audit-mcp

    MCP server that audits Excel workbooks without Excel: errors, hard-coded numbers, broken formula patterns, circular references, controls, stale values, comparison with a reference and a rubric-based grading aid. Read-only, dependency-free reader.

    Latest version
    v1.0.0
    Licence
    MIT
    Updated
    5 h ago
  • MCP ServerVerified publisher

    @spboucher/scholarly-mcp

    MCP server for scholarly search and citation verification over Crossref, OpenAlex, arXiv and doi.org: checks that a DOI resolves and its metadata matches, audits .bib files, flags retractions, walks the citation graph.

    Latest version
    v1.0.0
    Licence
    MIT
    Updated
    5 h ago

↑↓ to navigate · enter to open · esc to close