Skip to main content
Glama
README.md
# overleaf-mcp

Let your coding agent (Claude Code, Cursor, Codex CLI, Windsurf, Claude
Desktop, …) work on your Overleaf projects: list projects, read and write
`.tex`/`.bib` files, compile, read the LaTeX log, download the PDF.

Built for our team Overleaf at **overleaf.yihome.org** (API at
`https://github.yihome.org/api/v1`, used by default). Works with any
self-hosted Overleaf running the
[overleaf-selfhost](https://github.com/yidong72/overleaf-selfhost) companion
API — set `OVERLEAF_API_URL` to point elsewhere. (overleaf.com has no such API.)

> **Using an AI coding agent?** Paste this repo's URL to it and say
> *"install this MCP server"*. The agent should follow
> [`llms-install.md`](llms-install.md), which contains everything it needs.

## What you need

1. An API key — sign in at **https://github.yihome.org** with your Overleaf
   account → **API keys → Create key**. Copy it once; it's shown only once.
   *Tip:* create a separate Overleaf account for your AI and share only the
   projects it should touch, then make the key from that account.
2. (Only for other deployments) the API URL, shaped like
   `https://github.<domain>/api/v1`, passed as `OVERLEAF_API_URL`.

## Install (one command per client)

No clone, no build — `npx` fetches and runs it straight from GitHub.

**Claude Code**
```bash
claude mcp add overleaf -s user -e OVERLEAF_API_KEY=olk_... -- npx -y github:yidong72/overleaf-mcp
```

**Codex CLI** (`~/.codex/config.toml`)
```toml
[mcp_servers.overleaf]
command = "npx"
args = ["-y", "github:yidong72/overleaf-mcp"]
env = { OVERLEAF_API_KEY = "olk_..." }
```

**Cursor** (`.cursor/mcp.json` in the project, or `~/.cursor/mcp.json`) /
**Windsurf** (`~/.codeium/windsurf/mcp_config.json`) /
**Claude Desktop** (`claude_desktop_config.json`) — same JSON shape:
```json
{
  "mcpServers": {
    "overleaf": {
      "command": "npx",
      "args": ["-y", "github:yidong72/overleaf-mcp"],
      "env": { "OVERLEAF_API_KEY": "olk_..." }
    }
  }
}
```

**Verify** (any shell):
```bash
OVERLEAF_API_KEY=olk_... npx -y github:yidong72/overleaf-mcp --check
# → OK: connected to ... as you@example.com (key "..."); 3 project(s) visible
```

## Tools

| tool | what it does |
|---|---|
| `list_projects()` | projects you can access (id, name, access) |
| `create_project(name)` | new blank project |
| `delete_project(project_id, confirm_name)` | delete a project you own (only on explicit user request; name must match) |
| `list_files(project_id)` | all files with sizes |
| `read_file(project_id, path)` | file contents |
| `write_files(project_id, message, files[{path, content}])` | atomic multi-file write for small hand edits (whole-file contents; `content: null` deletes) |
| `upload_files(project_id, message, files[{local, remote}])` | **bulk upload from local disk** — text or binary, any size; content never passes through the model (use for .bib, figures, large .tex) |
| `download_file(project_id, path, save_to)` | download a project file to disk without passing it through the model |
| `delete_file(project_id, path)` | delete |
| `compile(project_id, stop_on_first_error?, compiler?)` | compile; returns status + log tail |
| `download_pdf(project_id, save_to)` | compile if needed, save the PDF locally |
| `github_status(project_id)` | is the project linked to a GitHub repo; commits to pull / changes to push |
| `github_push(project_id, message?)` | push Overleaf content to the linked GitHub repo as one commit |
| `github_pull(project_id)` | pull the repo's default branch into Overleaf |
| `github_link(project_id, mode, name?/repo?)` | connect a project to GitHub: create a new repo (and push) or link an existing one (project owner only) |
| `github_unlink(project_id)` | disconnect (repo untouched) |

Typical agent loop: `list_projects` → `read_file main.tex` → `write_files` (small edits) or
`upload_files` (whole files from disk) → `compile` (read the log on failure, fix, repeat) →
`download_pdf` → optionally `github_push`.

**Speed note:** `write_files` makes the model *generate* the file as tokens (a 200 KB .bib ≈ 50K
tokens). `upload_files` reads the bytes locally and sends them straight to the API, so large
or binary files transfer in seconds.

The GitHub tools need the user to have linked their GitHub account and the
project to a repository once in the sync web UI (the same place API keys are
made); until then they return a 409 explaining what to do.

## Notes

- Writes are whole-file replacements applied atomically; Overleaf users
  editing the same file in the browser see a "changed externally" notice.
- The API acts with exactly the permissions of the account that made the key.
- The full REST API this wraps is documented at
  `https://<your api host>/api/v1/docs` and, for agents, `/api/v1/llms.txt`.
- Requires Node.js ≥ 18 (for `fetch` and `npx`).
- Different Overleaf deployment? Add `-e OVERLEAF_API_URL=https://github.<domain>/api/v1`
  (or the same key in the JSON `env`).

## License

MIT