lnm-writer
# lnm-writer
Agent Skills and an MCP server for writing, refereeing, and illustrating papers in the **lesion network mapping** literature — the family of studies that localize a symptom or a therapeutic effect to a brain network using causal evidence and a normative connectome.
Covers six designs: lesion network mapping, voxel-based lesion-symptom mapping, DBS sweet-spot and probabilistic stimulation mapping, DBS network mapping, convergent causal mapping, and coordinate or atrophy network mapping.
The knowledge base was distilled from a close structural reading of fourteen published papers in this literature. It encodes the section skeletons, the reporting obligations each design carries, the statistics and their failure modes, the figure conventions, the limitations bank, and the sentence frames the genre uses. It contains no text from those papers.
## What it does
| Capability | Skill | MCP tool |
|---|---|---|
| Decide which design a study is | `lnm-paper` | `lnm_classify_design` |
| Plan the sections, and find the analyses that are missing | `lnm-paper` | `lnm_outline_paper` |
| Get the reporting checklist for a design | `lnm-paper` | `lnm_methods_checklist` |
| Read the guidance on methods, statistics, argument, figures | all | `lnm_list_guidance`, `lnm_get_guidance` |
| Get sentence frames for a section | `lnm-paper` | `lnm_phrasebook` |
| Get the limitations that actually apply to this study | `lnm-paper` | `lnm_limitations` |
| Audit a draft for missing reporting elements and overstatement | `lnm-review` | `lnm_audit_manuscript` |
| Plan the figure set, sized to a journal's column | `lnm-figures` | `lnm_figure_plan` |
| Check a caption for the elements the genre requires | `lnm-figures` | `lnm_caption_check` |
| Render brain figures, and audit a finished figure file | `lnm-figures` | `lnmfig` command |
The server holds no model and writes no prose. It serves the structure of the genre; the calling agent does the writing. Pixels are a separate concern: `lnmfig`, the Python package in this repository, does the rendering.
## lnmfig: the figure toolkit
```bash
pip install -e '.[all]'
lnmfig whole-brain map.nii.gz -o fig3 --threshold 2.5 --journal nature --column double
lnmfig montage map.nii.gz -o fig2 --plane axial --cuts=-26,-14,2,18,34 --threshold 2.5
lnmfig overlap lesions/*.nii.gz -o fig1a --save-counts overlap.nii.gz
lnmfig convergence mapA.nii.gz mapB.nii.gz -o fig4 --threshold 2.5 --similarity
lnmfig audit fig3.pdf --journal nature --column double --caption caption.txt
```
Renders the field's visual grammar: the inflated cortex, the SUIT cerebellar flatmap, slice montages on an anatomical underlay, glass-brain overlap maps, the convergence overlay, predicted-against-empirical scatters with their confidence band, permutation nulls, and JAMA-style forest tables. Reads Lead-DBS atlases and electrode reconstructions without MATLAB.
Three properties it enforces that a bare plotting call does not:
- **One scale, resolved once.** A cortex panel and a cerebellum panel of the same map share limits, threshold, and colormap, because a reader compares them and they are only comparable if the scale is identical.
- **True printed size.** Figures are authored at the journal's column width in inches and exported without cropping to content, so the declared canvas is the delivered canvas and nothing silently drops below the minimum legible font size.
- **Provenance.** Every render carries the scale that produced it, so `lnmfig caption` builds a caption stub from the render, with a bracketed placeholder for every fact it does not have.
`lnmfig audit` checks a finished file against a journal's rules: resolution at the printed size, canvas width against the column, colour mode, greyscale legibility, Type 3 fonts, and whether the caption carries the threshold, correction, template, test, and sample size.
## Install
### As a Claude Code plugin (skills and MCP server together)
```bash
git clone https://github.com/nielspac177/lnm-writer.git ~/.claude/skills/lnm-writer && cd ~/.claude/skills/lnm-writer && npm install
```
The repository carries a `.claude-plugin/plugin.json`, so any folder under a skills directory containing that manifest loads as a plugin on the next session — with no marketplace and no install step. Restart Claude Code, approve the MCP server when prompted, and all three skills plus the nine tools are available.
### Skills only, on any agent CLI
```bash
npx skills add nielspac177/lnm-writer
```
Installs to Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, opencode, Zed, and the rest of the agents that CLI supports. Add `-g` for a global install, or `--skill lnm-paper` to take just one. The skills are self-contained: each carries its own copy of the references it reads, so they work with no MCP server present.
### MCP server only, on any MCP client
```bash
git clone https://github.com/nielspac177/lnm-writer.git && cd lnm-writer && npm install
```
`npm install` builds `dist/`. Then register the server with your client.
Claude Code:
```bash
claude mcp add lnm-writer -- node /absolute/path/to/lnm-writer/dist/index.js
```
Codex, in `~/.codex/config.toml`:
```toml
[mcp_servers.lnm-writer]
command = "node"
args = ["/absolute/path/to/lnm-writer/dist/index.js"]
```
Any client that reads an `mcpServers` block, including Cursor, Gemini CLI, and Claude Desktop:
```json
{
"mcpServers": {
"lnm-writer": {
"command": "node",
"args": ["/absolute/path/to/lnm-writer/dist/index.js"]
}
}
}
```
Transport is stdio. The knowledge base is bundled and local, so there is no remote state, no credential, and no network call at runtime.
## Tools
All nine are read-only and annotated as such.
- **`lnm_list_designs`** — the six designs, with the claim each one can establish.
- **`lnm_classify_design`** — scores a free-text study description against every design and returns a ranked list with the signals it matched, plus the analyses reviewers of the winner expect. Declines to guess when nothing matches, and says which facts to add.
- **`lnm_outline_paper`** — a section-by-section plan: subsections in the literature's order, word budgets, per-section reporting obligations, and sentence frames. Leads with the gaps: analyses the design normally has to defend that nothing in the described study covers.
- **`lnm_list_guidance`** / **`lnm_get_guidance`** — the five long-form documents, whole or sliced to one heading.
- **`lnm_methods_checklist`** — 66 reporting items graded required, expected, or optional, each with the reason it matters, filterable by design and section.
- **`lnm_phrasebook`** — 59 sentence frames across 12 groups, by section and purpose.
- **`lnm_limitations`** — the limitations bank filtered by what the study actually did. Each entry pairs the concession with the counter published papers use. Entries the study already answers come back separately as retired, so they are reported as strengths rather than conceded.
- **`lnm_audit_manuscript`** — 36 deterministic checks over a draft, graded blocking, address-before-submission, and consider. Half look for missing reporting elements; the rest look for phrasings that overstate what the design supports, and quote the text that triggered them.
Resources are exposed at `lnm://guidance/{id}`. Two prompts, `write_lnm_paper` and `review_lnm_manuscript`, drive the full workflow.
### What the audit is and is not
It is a text search for required reporting elements. It tells you whether a manuscript says an analysis was done; it cannot tell you whether the analysis was done well. A clean audit is a floor, not a verdict.
## Repository layout
```
knowledge/ single source of truth: 5 markdown documents + 8 JSON data files
skills/ three Agent Skills, each with a committed copy of the references it reads
src/ MCP server (TypeScript, stdio, @modelcontextprotocol/sdk)
lnmfig/ the figure toolkit (Python, nilearn + SUITPy + matplotlib)
scripts/ sync-knowledge.mjs keeps the skill copies identical to knowledge/
test/ smoke.mjs drives the server over a real MCP client session
tests/ test_lnmfig.py covers the toolkit, skipping renderers when extras are absent
```
Edit files in `knowledge/`, then `npm run sync`. `npm run build` fails if the copies drift.
## Development
```bash
npm install # installs and builds the MCP server
npm run build # compile, then verify the skill copies are in sync
npm run sync # propagate knowledge/ into skills/*/references/
node test/smoke.mjs # 51 end-to-end checks over a real MCP client session
npm run inspect # open the MCP Inspector against the server
uv venv .venv && uv pip install --python .venv/bin/python -e '.[all]' pytest scikit-image
.venv/bin/python -m pytest tests/ # 39 checks over the figure toolkit
```
`knowledge/journals.json` is a copy of `lnmfig/data/journals.json`, which is the source: the Python package has to install standalone, and the MCP server has to serve the same numbers without importing Python. `npm run sync` propagates it and `npm run build` fails if it drifts.
## Scope and limits
This encodes the conventions of a specific literature. It will make a manuscript conform to that literature's expectations; it will not make a study sound, and it cannot see your data.
The tools never generate numbers. Where a value is missing, the skills write an explicit placeholder and collect them for you to fill in. A fabricated coordinate or p-value in a neuroimaging manuscript is a research-integrity problem, so this is a hard rule rather than a preference.
## License
MIT. See [LICENSE](LICENSE).
TDQS
Scored across 9 tools
Each tool has a distinct role: design listing/classification, paper outlining, guidance retrieval, checklist generation, phrasebook lookup, limitations, and manuscript audit. Even the closely related checklist and audit tools are clearly differentiated by drafting versus finished-text use.
All tools share the lnm_ prefix and snake_case convention, and most follow verb_noun naming (list_designs, classify_design, outline_paper, get_guidance, audit_manuscript). A few noun-only names (methods_checklist, phrasebook, limitations) are minor deviations from the pattern.
Nine tools is well within the ideal range and each tool earns its place by supporting a distinct stage of the study-design-to-manuscript workflow. The count feels neither sparse nor bloated.
The toolset covers the full workflow this server promises: design identification, paper outlining, guidance retrieval, methods checklisting, phrase support, limitations handling, and final manuscript audit. There are no obvious dead ends or missing stages within its stated purpose.