{
  "markdown": "# MagicTeX — LaTeX Editor for AI Agents\n\n<!-- badges -->\n[![npm](https://img.shields.io/npm/v/magictex-mcp?logo=npm)](https://www.npmjs.com/package/magictex-mcp)\n[![MCP registry](https://img.shields.io/badge/MCP%20registry-io.github.ZoeLinUTS%2Fmagictex-6f42c1)](https://registry.modelcontextprotocol.io)\n[![CI](https://github.com/ZoeLinUTS/MagicTeX-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/ZoeLinUTS/MagicTeX-mcp/actions/workflows/ci.yml)\n[![stars](https://img.shields.io/github/stars/ZoeLinUTS/MagicTeX-mcp?style=flat)](https://github.com/ZoeLinUTS/MagicTeX-mcp/stargazers)\n[![last commit](https://img.shields.io/github/last-commit/ZoeLinUTS/MagicTeX-mcp)](https://github.com/ZoeLinUTS/MagicTeX-mcp/commits/main)\n[![license](https://img.shields.io/badge/license-AGPL--3.0-blue)](LICENSE)\n[![Sponsor](https://img.shields.io/badge/%E2%9D%A4-Sponsor-db61a2)](https://github.com/sponsors/ZoeLinUTS)\n\n**English** · [简体中文](docs/i18n/README.zh-CN.md) · [日本語](docs/i18n/README.ja.md) · [한국어](docs/i18n/README.ko.md) · [Español](docs/i18n/README.es.md) · [Français](docs/i18n/README.fr.md) · [Deutsch](docs/i18n/README.de.md) · [Português](docs/i18n/README.pt.md)\n\n**MagicTeX** is a **LaTeX editor built for AI agents** — an Overleaf-like\none-window workspace for Claude Code, served by an MCP server, with **no local TeX\ninstall and no Overleaf account**: live PDF preview, a source editor with a Visual\n(WYSIWYG) mode, change history, and **comments you anchor on the rendered PDF that\nbecome edit instructions for the agent**. (npm package: `magictex-mcp`.)\n\nIt compiles with a WASM TeX Live 2026 engine ([texlyre-busytex](https://github.com/TeXlyre/texlyre-busytex))\nrunning inside a headless browser, so there's nothing multi-gigabyte to install —\njust a one-time WASM asset download.\n\n![The MagicTeX workspace: file tree, source editor, live PDF, and a reviewer comment](docs/images/workspace.png)\n\n## See it before you install\n\nA guided walkthrough of the comment → agent loop lives at\n**[zoelin.dev/tools/magictex](https://zoelin.dev/tools/magictex)**, built from real\ntool output. It's a replay, not a hosted instance — the TeX engine is a one-time\n~650 MB download and the agent half is Claude itself, so MagicTeX runs next to your\nproject rather than in a web page.\n\n## The workspace\n\nOne browser window (inspired by Typst's one-surface editor and LiquidText's\nanchored annotations):\n\n```\n┌──────────────────────────────────────────────────────────────┐\n│  ✓ up to date · 13 pages        Export .zip · Download PDF   │\n├────────────┬──────────────────────────────┬──────────────────┤\n│ Source /   │          PDF (live)          │    Comments      │\n│ History    │  select text → 💬 comment    │  accepted → ask  │\n│  editor,   │  highlights stay anchored    │  Claude to       │\n│  timeline  │  auto-reloads on every edit  │  address them    │\n│  + diffs   │                              │  → resolved ✓    │\n└────────────┴──────────────────────────────┴──────────────────┘\n```\n\n- **Comment → Claude loop (the point of it all).** Review the *rendered* document\n  like a supervisor marking up a printout: select text, attach a comment\n  (\"tighten this paragraph\"). Then tell Claude to *\"address my comments\"* — it\n  pulls them via `check_comments` as **located work items** (page + quoted passage\n  + the source `file:line` it anchors to + your ask), edits the source, and\n  resolves each card with a note. You interact with the document; Claude interacts\n  with the source. Run it hands-off with `/loop` — see\n  [`docs/AGENT-LOOP.md`](docs/AGENT-LOOP.md).\n- **Editable source panel.** A CodeMirror LaTeX editor with the project's files —\n  save (Ctrl+S) recompiles and refreshes the PDF, Typst-style. Or keep using your\n  own editor: any save triggers the same live loop.\n- **Live reload.** A file watcher recompiles on every save — Claude's edits, the\n  built-in editor's, or your external editor's.\n- **Change history.** Each successful compile is auto-snapshotted to a **hidden\n  git ref** (`refs/latex-preview/checkpoints`) — never touching your branches,\n  `git log`, or working tree. The History tab shows the timeline and each\n  checkpoint's colorized diff beside the PDF.\n- **Get to Overleaf.** **Download PDF**, **Export .zip** (clean build-inputs\n  bundle), and a one-click **Open in Overleaf** link for public GitHub repos;\n  Premium Git-bridge sync is a documented `git push`. See [`docs/USER-GUIDE.md`](docs/USER-GUIDE.md).\n- **Review workflow (reviewer → gate → resolver).** A reviewer/defender agent posts\n  comments via `add_comment`; you **Accept/Reject** them (or flip *Auto-accept* for\n  copilot mode); an author loop resolves the accepted ones. Comments carry roles and\n  a reply thread. See [`docs/AGENT-LOOP.md`](docs/AGENT-LOOP.md).\n- **Save vs. recompile, your call.** The built-in editor auto-saves every 30s without\n  recompiling; **Ctrl+S** / **Save** / **Recompile** rebuild the PDF on demand. (Flip\n  **⚡ Live** for recompile-as-you-type.) Your own editor and Claude's edits still\n  auto-recompile via the watcher.\n- **Real projects.** Auto-detects the main file, gathers multi-file\n  `\\input`/`\\include`, `.bib`, in-repo `.cls`/`.sty`/`.bst` and figures, runs\n  BibTeX and reruns when needed; common missing packages are auto-injected.\n- **Compile backend.** Uses your local **latexmk** when you have one — full package\n  fidelity, output matching Overleaf — and the bundled zero-install **WASM** TeX Live\n  when you don't. Force either with `backend: \"system\"` / `\"wasm\"`. Every compile\n  reports which one ran.\n- **Document classes.** `IEEEtran` is bundled, because no venue class ships in the\n  WASM TeX Live and a missing class can't be worked around the way a package can.\n  Conference classes (NeurIPS, ICML, CVPR, ACL, AAAI …) carry no redistributable\n  licence, so put the `.cls` from the author kit beside your source — it's picked up\n  automatically.\n- **MCP tools:** `render_preview` (compile + open the workspace), `check_comments` /\n  `resolve_comment` / `add_comment` / `reply_to_comment` (the review loop), `show_diff`\n  (side-by-side diff as an image — useful on image-capable clients).\n- **Actionable errors.** Failed compiles return parsed `{file, line, message}`\n  errors so Claude can self-correct, and show in the workspace.\n\n## Setup\n\nMagicTeX is on npm as [`magictex-mcp`](https://www.npmjs.com/package/magictex-mcp) and\nlisted in the [official MCP registry](https://registry.modelcontextprotocol.io) as\n**`io.github.ZoeLinUTS/magictex`** — so any client that reads the registry can find it.\nThere's nothing to clone and no TeX install; `npx` fetches it on first use.\n\n1. **Add it to your paper project's `.mcp.json`** (see [`.mcp.json.example`](.mcp.json.example)):\n\n   ```json\n   {\n     \"mcpServers\": {\n       \"magictex\": { \"command\": \"npx\", \"args\": [\"-y\", \"magictex-mcp\"] }\n     }\n   }\n   ```\n\n   For local development from a clone, point it at the source instead:\n   `\"command\": \"npx\", \"args\": [\"tsx\", \"/absolute/path/to/magictex-mcp/src/server.ts\"]`\n\n2. **Restart Claude Code** (or `/mcp` reconnect) so it picks up the server.\n\n3. **Ask Claude to render.** e.g. *\"render a preview of this paper\"* → the first call\n   downloads the WASM TeX Live assets (~650 MB, one time), compiles, and opens the\n   live preview tab. Subsequent edits reload it automatically.\n\nThe WASM assets are **not** in this repo. They're fetched on first run into a\nper-user cache — `~/Library/Caches/magictex` on macOS, `$XDG_CACHE_HOME/magictex`\non Linux, `%LOCALAPPDATA%\\magictex` on Windows — so upgrading MagicTeX doesn't\nre-download them, and a checkout, a global install and an `npx` run share one copy.\nSet `MAGICTEX_ASSETS_DIR` to put them elsewhere. To pre-fetch:\n`npx texlyre-busytex download-assets <that directory>`.\n\n## Install as a Claude Code plugin (slash commands)\n\nFor a low-typing workflow, install MagicTeX as a plugin — one install gives you the\nMCP server **and** the slash commands:\n\n```\n/plugin marketplace add ZoeLinUTS/MagicTeX-mcp\n/plugin install magictex\n```\n\nThen, in your paper project, use the **workflow commands** for the common flows:\n\n- **`/magic-latex`** — compile and open the workspace (the live preview).\n- **`/ai-review [skill]`** — review the paper with a skill (default\n  `academic-paper-revision`; pass any skill name) and post comments for you to\n  Accept/Reject. Missing skills are reported with an install hint.\n- **`/address-comments`** — resolve your accepted comments (loop it with\n  `/loop 60s /address-comments`).\n- ⚡ **`/ultra-agents [skill] [depth]`** — fully autonomous: review, auto-accept, fix,\n  repeat, up to `depth` rounds (default 2), stopping early the moment a round finds\n  nothing new. No per-round approval — that's the point, and the risk. `depth > 5`\n  asks you to confirm before starting. Ends with a summary (what was raised, what\n  changed, which checkpoints to look at) — every round is still an ordinary,\n  revertible checkpoint. See [`docs/AGENT-LOOP.md`](docs/AGENT-LOOP.md#ultra-agents).\n\n### One command per tool\n\nEvery MCP tool also has a slash command with the **same name**, so you can drive any\nsingle step by typing the tool name. The rule to teach: *the tool is `X` → type\n`/X`.*\n\n| Type this      | Runs tool         | What it does |\n| -------------- | ----------------- | ------------ |\n| `/render_preview` | `render_preview` | Compile the paper and open/refresh the live preview. |\n| `/check_comments` | `check_comments` | List the comments you've accepted, as edit instructions (no edits yet). |\n| `/resolve_comment [id] [note]` | `resolve_comment` | Mark a comment done after the edit; it turns **green** for your review. |\n| `/add_comment [\"quote\"] [note]` | `add_comment` | Anchor a comment onto a passage for you to Accept/Reject. |\n| `/reply_to_comment [id] [text]` | `reply_to_comment` | Add a threaded reply to a comment. |\n| `/show_diff [checkpoint]` | `show_diff` | Side-by-side visual diff as an image (current changes, or a checkpoint). |\n| `/list_checkpoints [limit]` | `list_checkpoints` | Recent checkpoints with their sha, newest first — find one to pass into `/show_diff`. |\n\nYou never *have* to type these — plain English works too (*\"render a preview\"*,\n*\"address my comments\"*). The commands are just a fast, teachable shorthand.\n\n> The plugin bundles the MCP server (`npx magictex-mcp`), so installing the plugin is\n> all you need — the `.mcp.json` above is the alternative if you'd rather not install\n> a plugin. The slash commands work either way.\n\n## Tools\n\nThe MCP surface, for any client that speaks MCP. (In Claude Code you can just ask in\nplain English, or use the slash commands above — these are the underlying tools.)\n\n| Tool | Parameters | What it does |\n| ---- | ---------- | ------------ |\n| `render_preview` | `mainFile?` · `engine?` (`pdflatex` \\| `xelatex` \\| `lualatex`, default `xelatex`) · `backend?` (`wasm` \\| `system` \\| `auto`, default `auto` — local latexmk if installed, else the bundled WASM engine) | Compiles the project and opens/refreshes the live workspace. The main file is auto-detected by scanning for `\\documentclass` if omitted. |\n| `check_comments` | `includeResolved?` (default `false`) | Returns the accepted comments as located work items — page, quoted passage, the source `file:line`, and the ask. Reviewer suggestions awaiting your decision are reported but not returned as work. |\n| `add_comment` | `quote` · `comment` · `role?` (`reviewer` \\| `defender`) · `page?` · `accepted?` | Anchors a comment onto a passage. Posts as a *suggestion* awaiting your Accept/Reject unless `accepted` is set — that flag is what makes autonomous mode autonomous. |\n| `resolve_comment` | `id` · `note` | Marks a comment done after the edit, with one line describing what changed. It turns **green** in the workspace for your review. |\n| `reply_to_comment` | `id` · `text` · `role?` (`author` \\| `reviewer` \\| `defender`) | Adds a threaded reply, so a disagreement can be worked out on the comment instead of in chat. |\n| `show_diff` | `checkpoint?` | Renders a side-by-side diff **as an image**, shown inline in the conversation. Defaults to the current uncommitted changes; pass a checkpoint sha for a saved version. |\n| `list_checkpoints` | `limit?` (default 10, max 50) | Recent checkpoints with their sha, newest first — use it to find one to pass to `show_diff`. |\n\n**The headline workflows are built on top of these, not among them.** `/magic-latex`,\n`/ai-review`, `/address-comments` and ⚡ `/ultra-agents` are Claude Code plugin\ncommands that orchestrate the tools above — `/ultra-agents` chains review →\nauto-accept → fix for as many rounds as you allow, and is the reason `add_comment`\ntakes an `accepted` flag. They are not part of the MCP surface, so another MCP client\nsees the seven tools only. See [the plugin section](#install-as-a-claude-code-plugin-slash-commands)\nand [docs/AGENT-LOOP.md](docs/AGENT-LOOP.md).\n\n## See it in the terminal\n\nThese are real tool outputs, captured verbatim from an actual run against the sample\npaper — not mocked up. This is what you see in Claude Code while the browser\nworkspace (screenshot above) reflects the same state live.\n\nYou type:\n```\n/magic-latex\n```\nClaude calls `render_preview` and replies:\n```\n✓ Compiled main.tex with xelatex in 1900ms — 2 files. Workspace (live preview,\nsource editor, history, PDF comments — auto-reloads on edits):\nhttp://127.0.0.1:52042/app\n```\n\nYou (or a reviewer skill) leave a comment, then ask what's ready to act on. Claude\ncalls `check_comments`:\n```\n1 accepted comment — edit each at its source location per the instruction, then\ncall resolve_comment with its id and a one-line note:\n\n[id: 2fce9e3c8b5f] p.1 — \"Sorting widgets efficiently is a long-standing problem\"\n  ↳ source: main.tex:15\n  → Tighten this opening sentence.\n\n(1 reviewer suggestion still awaits the human's accept in the workspace — not\nactionable yet.)\n```\nClaude makes the edit and calls `resolve_comment`:\n```\n✓ Resolved comment 2fce9e3c8b5f (\"Sorting widgets efficiently is a long-standing\nproblem…\") — the card now shows: Rewrote the opening sentence.\n```\nAsk again, and the accepted queue is empty — only the still-unaccepted suggestion\nremains, waiting on you:\n```\nNo accepted comments. (2 already resolved.)\n\n(1 reviewer suggestion still awaits the human's accept in the workspace — not\nactionable yet.)\n```\n\n## How it works\n\n```\nClaude edits .tex ─┐\n file watcher ─────┼─▶ compile coordinator ─▶ headless Chromium ─▶ WASM TeX ─▶ PDF\n render_preview ───┘         (serialized)         (engine host)                │\n                                                                               ▼\n                     your workspace (/app)  ◀── WebSocket \"reload\" ◀── local HTTP server\n                     Source · PDF · History · Comments        (serves /app + /latest.pdf)\n```\n\nThe WASM engines need DOM/Worker globals, so the server hosts a hidden headless\nChromium as its compile worker; the workspace *you* open is a lightweight React +\npdf.js app with no WASM in it. See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).\n\n```mermaid\nflowchart LR\n  H[\"👤 You<br/>Source · PDF · History · Comments\"]\n  A[\"🤖 Claude Code<br/>+ review / author agents\"]\n\n  H <-->|\"select text →<br/>anchor comment\"| SRV[\"Preview server<br/>HTTP + WebSocket · serves /app\"]\n  A -->|\"7 MCP tools\"| MCP[\"MCP server<br/>render_preview · show_diff · list_checkpoints<br/>check / resolve / add / reply_comment\"]\n\n  SRV --> CO[\"Compile coordinator<br/>(serialized)\"]\n  MCP --> CO\n  A -. edits source .-> FILES[(\"Paper files · git repo\")]\n  FILES --> WATCH[\"File watcher\"] --> CO\n  CO --> ENG[\"WASM busytex<br/>(headless Chromium)\"] --> PDF[\"/latest.pdf\"]\n  PDF -. live reload .-> H\n  CO --> CK[\"git checkpoints<br/>(hidden ref) → History\"]\n\n  SRV <--> CJSON[(\".latex-preview/<br/>comments.json\")]\n  MCP <--> CJSON\n  CJSON -->|\"check_comments<br/>(your accepted asks)\"| A\n```\n\nBoth front doors — you in the workspace, agents through the 7 MCP tools — meet at\nthe same coordinator, comment store, and git history. You act on the *rendered\ndocument* (anchor a comment); Claude acts on the *source* (reads your comments via\n`check_comments`, edits, `resolve_comment`). That shared substrate is what makes\nthe comment loop, the review workflow, and traceable history possible.\n\n## Requirements\n\n- Node 20.19+ (the floor `chokidar` and `playwright` actually need; the server checks at startup and says so)\n- Playwright's Chromium (installed automatically; ~150–300 MB) — or set it to reuse\n  your installed Chrome.\n- ~650 MB disk for the one-time WASM TeX Live assets — all of it fetched on the\n  first run, in three package sets (basic 87 MB, recommended 190 MB, extra 324 MB,\n  plus the 31 MB engine). A normal paper only *loads* the basic set; the larger two\n  sit on disk until something needs them. Cached per user, not per install, so\n  upgrading MagicTeX doesn't re-download them. Override the location with\n  `MAGICTEX_ASSETS_DIR`.\n- **A local TeX install is optional.** See below for when it matters.\n\n### Do I need a local TeX distribution?\n\nNo — the bundled WASM engine compiles with nothing installed, which is the whole\npoint. But it ships a *subset* of TeX Live, so some things aren't in it: `svg`,\nmost venue document classes, and various less common packages. When one is\nmissing you'll be told, rather than handed a silently wrong PDF.\n\nInstall a distribution when you want output that matches Overleaf exactly.\nMagicTeX picks it up on its own — no configuration:\n\n| | |\n|---|---|\n| macOS | [MacTeX](https://tug.org/mactex/) |\n| Linux | `texlive-full`, via your package manager |\n| Windows | [TeX Live](https://tug.org/texlive/), or [MiKTeX](https://miktex.org/) **plus** [Strawberry Perl](https://strawberryperl.com/) |\n\n> `latexmk` is what MagicTeX looks for on `PATH`, but it isn't something you\n> install on its own — it's a driver script that comes inside the distributions\n> above. Check with **`latexmk -version`**, not `which latexmk`: `latexmk` is a\n> Perl script, and MiKTeX puts `latexmk.exe` on your `PATH` without shipping a\n> Perl to run it with — so the file is found and still cannot execute. On macOS\n> you may need `eval \"$(/usr/libexec/path_helper)\"` or a fresh terminal first.\n\nEvery compile tells you which one ran — `xelatex · system` or `xelatex · wasm`.\n\n## Development\n\n```bash\nnpm install\nnpm run typecheck    # tsc for the server and the UI\nnpm run build:ui     # build the React workspace to ui/dist\nnpm test             # the unit suite — engine-free, no browser, seconds\nnpm start            # run the server on stdio (for a manual MCP client)\n```\n\nTwo tiers, on purpose. `npm test` covers the comment store, anchor matching, line\nand column geometry, the history repo, asset paths, compile-log classification, the\npreview server's shutdown, and an MCP workflow E2E — all without a browser or a TeX\nengine, so it stays fast and deterministic. CI (`.github/workflows/ci.yml`) runs\ntypecheck + UI build + that suite on Node 20 and 22 for every push and pull request.\n\nThe things a unit test structurally cannot see — highlight geometry at several zoom\nlevels, what a failed render actually tells the reader, whether shutting down closes\nthe server and warns any open window — live in `scripts/smoke-*.mjs` and run against\na real browser and a real compile in `.github/workflows/smoke-macos.yml`. Each of\nthose exists because something shipped broken that the unit suite was green through.\nPlease keep both green and add coverage with changes.\n\n## Documentation\n\n- [**User guide**](docs/USER-GUIDE.md) — everyday use, the comment loop, Visual mode, the\n  file tree, getting your paper into Overleaf, package coverage.\n- [**The agent loop**](docs/AGENT-LOOP.md) — comments as triggers, running it hands-off with\n  `/loop`, the reviewer → gate → resolver workflow, and ⚡ `/ultra-agents`.\n- [**Roadmap**](docs/ROADMAP.md) — what's shipped for concurrent agents, and what real\n  parallel multi-agent editing still needs.\n- [**Architecture**](docs/ARCHITECTURE.md) — why a headless browser, what every module does,\n  the compile flow.\n\nAll four are translated into the same 8 languages as this README — each page has its own\nlanguage switcher at the top.\n\n## Roadmap\n\nMultiple Claude Code sessions can already work the same project concurrently without\ncorrupting comments or the checkpoint history (see [`docs/ROADMAP.md`](docs/ROADMAP.md))\n— true parallel multi-agent editing (reviewer/author/defender on their own git branches,\nmerged back together) is the next milestone.\n\n## Sponsor this project\n\nMagicTeX is free and open source (AGPL-3.0). If it saves you time on your papers,\nplease consider **[sponsoring the project](https://github.com/sponsors/ZoeLinUTS)** —\nit funds continued development. A ⭐ on the repo helps too.\n\n## Acknowledgements\n\nMagicTeX is written and maintained by [Zoe Lin](https://zoelin.dev), built with\n**[Claude Code](https://claude.com/claude-code)**.\n\nThanks to **David Turnbull**, who told me the story of Knuth spending ten years\nbuilding his own typesetter rather than accept how his book looked — the story this\nproject keeps arguing with. And to the maintainers of\n[`texlyre-busytex`](https://github.com/TeXlyre/texlyre-busytex), without whose WASM\nTeX Live none of this would run locally at all.\n\n## License\n\n[AGPL-3.0-or-later](LICENSE) — matching the `texlyre-busytex` engine it builds on.\nSee [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md).\n",
  "bytes": 21449,
  "sha": "547a10692c5c44adecf9c538d1cd275d2375e6cf369bdb8c4a2b4dde1ffcc25f",
  "repo_slug": "zoelinuts/magictex-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_zoelinuts_magictex_a859c6f0/readme"
}