Skip to main content
Glama
m053m716

LaTeX MCP

by m053m716
README.md
# LaTeX MCP

LaTeX MCP is a local stdio Model Context Protocol server for compiling and inspecting LaTeX projects with this machine's TeX Live 2025 installation. It is intended for Claude Code and OpenAI Codex in VS Code, but any MCP client that supports local stdio servers can use it.

The server always invokes binaries under `C:\texlive\2025\bin\windows`; it does not trust the caller's `PATH`, cannot fall through to MiKTeX, never enables shell escape, and does not expose package installation.

## Architecture

```text
VS Code client
  -> .venv\Scripts\python.exe server.py (MCP over stdio)
     -> C:\tools\latex\build-latex.ps1
        -> C:\texlive\2025\bin\windows\latexmk.exe
           -> C:\texlive\2025\bin\windows\pdflatex.exe
```

The MCP repository owns the protocol surface, tests, and an MCP-local minimal English format configuration. TeX Live is a machine dependency. The PowerShell wrapper remains the canonical low-level build entry point.

Manuscript repositories do not need copies of `server.py`, `.venv`, or this repository. Tools accept an explicit absolute `project_dir`, so the MCP server process does not need to start in the manuscript workspace. If `project_dir` is empty, `CLAUDE_PROJECT_DIR` is used when available.

## Prerequisites and setup

- Windows 11 x64.
- Python 3.11 or newer; this installation uses Python 3.12.10.
- TeX Live 2025 at `C:\texlive\2025`.
- Build wrapper at `C:\tools\latex\build-latex.ps1`.

### TeX Live 2025
On Windows 11 if you don't have it yet, you can follow these steps from admin powershell:  
1. Install/update git
```powershell
winget install --id Git.Git -e
```
2. Install/update Python 3.12
```powershell
winget install --id Python.Python.3.12 -e
```
3. Install/update cURL
```powershell
winget install --id cURL.cURL -e
```
4. Use `cURL` to install TeX Live 2025 installer/follow instructions thereafter:  
```powershell
$repo = "https://ftp.math.utah.edu/pub/tex/historic/systems/texlive/2025/tlnet-final"
$installer = "$env:TEMP\install-tl-2025.exe"

curl.exe -L "$repo/install-tl-windows.exe" -o "$installer"

& $installer -repository $repo
```
In the TeX Live installer, select Advanced and configure:

Scheme:              small
Installation root:   C:\texlive\2025
Default paper size:  Letter

Source and documentation installation can also be disabled if you want to minimize the installation size.

Complete the TeX Live installation. 

5. Install the additional packages required by LaTeX_MCP  
After the base installation succeeds:
```powershell
$tlmgr = "C:\texlive\2025\bin\windows\tlmgr.bat"

& $tlmgr --repository $repo install `
    ieeetran `
    latexmk `
    microtype `
    amsmath `
    amsfonts `
    mathtools `
    siunitx `
    booktabs `
    tools `
    makecell `
    algorithms `
    algorithmicx `
    pgf `
    xcolor `
    dblfloatfix `
    hyperref `
    placeins `
    preprint `
    cm-super
```
tlmgr automatically resolves and installs dependencies required by these packages.

6. Verify the installation
```powershell
$bin = "C:\texlive\2025\bin\windows"

& "$bin\pdflatex.exe" --version
& "$bin\latexmk.exe" --version
& "$bin\tlmgr.bat" --version
& "$bin\kpsewhich.exe" IEEEtran.cls
& "$bin\kpsewhich.exe" tikz.sty
& "$bin\kpsewhich.exe" siunitx.sty
& "$bin\kpsewhich.exe" algpseudocode.sty
```
Verify the default paper configuration with:
```powershell
& "$bin\tlmgr.bat" paper
```
If necessary, explicitly set Letter afterward:
```powershell
& "$bin\tlmgr.bat" paper letter
```
The resulting installation should reside at:
```powershell
C:\texlive\2025
```
and the executables used by LaTeX_MCP should come explicitly from:
```powershell
C:\texlive\2025\bin\windows
```
rather than from MiKTeX or another TeX distribution on PATH.

## Installation from Repo

Create or refresh the isolated environment from this repository:

```powershell
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install ".[test]"
```

Dependencies are pinned in `pyproject.toml`; no global Python install is required. The current MCP SDK pin is `mcp==2.0.0` and the test pin is `pytest==8.4.2`.

An editable install also exposes helper console scripts for registration:

```powershell
.\.venv\Scripts\python.exe -m pip install -e .
```

| Script | Scope | Purpose |
| --- | --- | --- |
| `latex-mcp` | — | Run the stdio MCP server (same as invoking `server.py`). |
| `latex-mcp-vscode` | Project | Generate project-local config for one VS Code repository. |
| `latex-mcp-install` | User | Register the server in the global user Claude and Codex config. |

Both registration scripts resolve this repository's `.venv` interpreter and `server.py` automatically (override with `--python` / `--server`), and every file they touch is reconciled in place: an existing `latex` entry is replaced rather than duplicated. Pass `--dry-run` to preview.

This machine's protected TeX Live tree does not contain a writable `texmf-dist\ls-R` filename database. The server handles that state by configuring read-only Kpathsea disk searches and user-scoped formats/maps. The MCP-local `texmf` directory supplies a minimal US-English format configuration; it does not change manuscript sources.

## Tools

| Tool | Arguments | Result and behavior |
| --- | --- | --- |
| `latex_environment` | None | Reports exact TeX Live roots, binary paths, versions, BibTeX/Biber availability, wrapper availability, and filename-database state. |
| `latex_find_file` | `filename` | Resolves a simple TeX filename using the explicit TeX Live `kpsewhich.exe`; paths and option-like input are rejected. |
| `latex_build` | `project_dir`, `main_tex="main.tex"`, `clean_first=false` | Runs the known wrapper with pdfLaTeX/LatexMk, noninteractive file/line errors, halt-on-error, SyncTeX, and no shell escape. Output is bounded; the full `.log` remains beside the manuscript. |
| `latex_clean` | `project_dir`, `main_tex="main.tex"` | Runs LatexMk `-C` for the selected main file and removes only standard generated products. |

`main_tex` must resolve to a `.tex` file inside `project_dir`. Absolute paths, option-like names, missing files, and traversal outside the project are rejected. Subprocesses use argument arrays with `shell=False`.

## Resources

| URI | MIME type | Purpose |
| --- | --- | --- |
| `latex://templates/ieeetran-journal-preamble.tex` | `text/x-tex` | Preferred baseline preamble for new 10-point IEEEtran journal manuscripts, including the documented mathematics, units, table, algorithm, TikZ, float, link, and balancing setup. |

Discover the template with MCP `resources/list` and fetch its text with `resources/read`. It is a starting point: add manuscript-specific packages after reviewing compatibility, and let repository or venue requirements override it. The resource ends before title metadata and `\\begin{document}`, so callers can append a project-specific body. Existing documents are not automatically rewritten to use it.

## Development and tests

Launch the stdio server directly:

```powershell
C:\MyRepos\Python\LaTeX_MCP\.venv\Scripts\python.exe C:\MyRepos\Python\LaTeX_MCP\server.py
```

The terminal appears idle because it is waiting for MCP JSON-RPC on stdin. Diagnostics go to stderr; stdout is reserved for the protocol.

Run all automated unit, integration, and stdio protocol tests:

```powershell
.\.venv\Scripts\python.exe -m pytest -q
```

The realistic IEEE smoke source is `testdata\ieee_smoke\main.tex`. Tests compile it with IEEEtran, algorithms, TikZ, siunitx, microtype, and the rest of the documented package stack, confirm PDF creation, and clean the generated output.

## Registration

### Project scope (one repository)

Run the generator from inside the repository you want to configure, or pass its path:

```powershell
latex-mcp-vscode              # configures the current directory
latex-mcp-vscode C:\MyRepos\Papers\MyPaper
```

It reconciles these local artifacts, upserting a single `latex` entry into each:

| File | Client |
| --- | --- |
| `.mcp.json` | Claude Code (project scope) |
| `.codex\config.toml` | Codex (project-local) |
| `.vscode\mcp.json` | VS Code native MCP client |
| `.gitignore` | Ignores the machine-specific local config above |
| `AGENTS.md` | Agent usage guidance and preferred IEEE style (managed block) |
| `LATEX_MCP.md` | Human note describing what was generated and how to verify |

### User scope (every project)

To register the server for all projects at once:

```powershell
latex-mcp-install
```

It upserts the `latex` entry into `%USERPROFILE%\.claude.json` (`mcpServers`) and `%USERPROFILE%\.codex\config.toml` (`[mcp_servers.latex]`), preserving unrelated servers and settings.

## Claude Code registration (manual reference)

[Claude Code's MCP documentation](https://code.claude.com/docs/en/mcp) specifies that user-scoped MCP servers are stored at `%USERPROFILE%\.claude.json`. The `latex` entry belongs under the top-level `mcpServers` object:

```json
{
  "type": "stdio",
  "command": "C:\\MyRepos\\Python\\LaTeX_MCP\\.venv\\Scripts\\python.exe",
  "args": [
    "C:\\MyRepos\\Python\\LaTeX_MCP\\server.py"
  ]
}
```

This is user scope, so it is available in every Claude Code project. After configuration changes, reload the Claude Code VS Code session, open `/mcp` or the MCP management UI, and confirm that `latex` is connected and exposes four tools. The standalone `claude` CLI is not required.

## Codex registration (manual reference)

[OpenAI's MCP documentation](https://learn.chatgpt.com/docs/extend/mcp?surface=cli) specifies that the Codex IDE extension and CLI share `%USERPROFILE%\.codex\config.toml`. The user-level entry is:

```toml
[mcp_servers.latex]
command = "C:\\MyRepos\\Python\\LaTeX_MCP\\.venv\\Scripts\\python.exe"
args = ["C:\\MyRepos\\Python\\LaTeX_MCP\\server.py"]
cwd = "C:\\MyRepos\\Python\\LaTeX_MCP"
startup_timeout_sec = 15
tool_timeout_sec = 300
enabled = true
```

In VS Code, open the Codex gear menu, select **MCP servers**, and restart the extension after configuration changes. Confirm that `latex` is enabled and connected. Codex's official documentation states that the IDE extension and CLI share `config.toml`; the standalone CLI is not required for normal extension use.

## Example agent requests

For guidance on selectively turning substantive implementation concepts into repository-local technical notes, see [the technical manuscript workflow](docs/technical-manuscript-workflow.md).

From any unrelated manuscript repository, ask:

> Use the latex MCP server to compile the manuscript in the current workspace. Find the main TeX file, compile it, inspect any errors, fix the errors, and recompile until the build succeeds.

For a precise call, provide the project path:

```text
Use latex_build with project_dir="C:\MyRepos\Papers\MyPaper" and main_tex="main.tex".
```

## Troubleshooting

- Call `latex_environment` first. Its `pdflatex.path` must be `C:\texlive\2025\bin\windows\pdflatex.exe`, and its version must contain `TeX Live 2025`. A MiKTeX path or version indicates that execution did not come through this server.
- Use `latex_find_file("package.sty")` to distinguish a missing TeX package from a manuscript error. Package installation is intentionally not an MCP tool; maintain TeX Live separately with deliberate `tlmgr` administration.
- Review the returned error summary, then open the complete `.log` at the returned `log_path`. MCP responses intentionally truncate large process output.
- A normal warning that shell escape is disabled confirms the intended security policy. Documents that require external shell commands must use a separately reviewed workflow.
- If a client shows the server as disconnected, verify both absolute registered paths, run the test suite, then reload the relevant VS Code extension. Editing a configuration file alone does not prove extension connectivity.
- The TeX Live tree on this machine is read-only and uses per-user formats/maps. After changing TeX Live format sources or font packages, rerun the appropriate user maintenance (`fmtutil-user` or `updmap-user`) before rebuilding.

## Updating

Pull or edit this single repository, activate no global environment, and run:

```powershell
.\.venv\Scripts\python.exe -m pip install --upgrade ".[test]"
.\.venv\Scripts\python.exe -m pytest -q
```

The Claude and Codex registrations use stable absolute paths into this repository, so routine server updates do not require copying files or duplicating configuration in manuscript repositories.

<!-- handoff-mcp:begin (managed by `handoff-mcp init --vscode`) -->
## Handoff MCP — session memory for agents

This repo has the `handoff` MCP server configured (see `.mcp.json` /
`.codex/config.toml`). It is a durable, project-scoped place to leave
breadcrumbs between sessions. Use it instead of re-deriving context.

**At the start of a session**, call `handoff_list` to reload where prior work
stopped and what to do next, and `todo_list` for outstanding next steps. This is
cheaper and more reliable than re-reading the whole transcript.

**While working**, when you find something that must be done but is not the
current focus, call `todo_add` rather than holding it in the conversation.

**When context gets heavy** (stale greps, large logs, finished sub-tasks pile
up), call `context_report`, then `context_compact` — it returns a
summarise-then-handoff procedure and can persist the summary as a handoff in one
call.

**At the end of a work chunk**, call `handoff_add` with a summary, next steps,
and the few key facts (file paths, decisions, gotchas) the next worker needs. A
fresh session can then resume from `handoff_list` alone.

**Close the loop** with `todo_update` (done/dropped) and `handoff_resolve` so
the open lists stay a true worklist.

| Tool | Use it to |
| --- | --- |
| `handoff_list` | Reload breadcrumbs at session start. |
| `handoff_add` | Record where you stopped and what is next. |
| `handoff_resolve` | Mark a handoff done. |
| `todo_add` / `todo_list` / `todo_update` | Track next-step TODOs. |
| `project_status` | Counts of open todos and handoffs. |
| `context_report` / `context_compact` | Notice and shrink a bloated context window. |

Every tool is scoped to this project only; there is no way to reach another
project's data. Full reference: `docs/TOOL_GUIDE.md`.
<!-- handoff-mcp:end -->

TDQS

A3.7/5.0

Scored across 4 tools

Disambiguation5/5

Each tool targets a distinct concern: environment inspection, file resolution, compilation, and cleanup. There is no functional overlap between them.

Naming Consistency4/5

All tools share the latex_ prefix and mostly use verb-led names like find_file, build, and clean. latex_environment is the only noun-based deviation but remains predictable in context.

Tool Count5/5

Four tools form a tight, well-scoped set for LaTeX project workflows without redundancy or bloat. Each tool serves a clear purpose.

Completeness4/5

The set covers the main lifecycle of inspecting, resolving, building, and cleaning LaTeX projects. Minor gaps exist such as no explicit output preview or detailed log retrieval, but the core workflow is complete.

Maintenance

ActivityMaintained
ResponsivenessNo issues