overleaf-mcp
This server lets an agent collaborate on Overleaf projects over MCP: discover accounts/projects, open a live project session, read and edit LaTeX/text documents with tracked changes, manage comments and review suggestions, compile, download artifacts, and modify the project file tree.
Discovery & state:
ping,list_servers,list_projects,open_project,list_files— inspect available Overleaf servers, projects, and the open project's file tree.Editing:
read_file,edit_file,find_and_replace— read text/binary files, submit minimal OT diffs as tracked suggestions or direct writes, with version/strictness safeguards.Review/comments:
list_tracked_changes,accept_changes,reject_changes,list_comments,read_comment_thread,add_comment,reply_comment,resolve_comment,reopen_comment— handle pending tracked edits and native comment threads.Compilation:
compile,read_log— trigger LaTeX builds, see error/warning summaries, read full logs.Downloads:
download_file,download_project,download_output— save document snapshots, binaries, project ZIPs, and compile artifacts (e.g. PDF) to local absolute paths without overwriting.File management:
create_file,create_folder,upload_file,rename_entity,delete_entity— create empty docs/folders, upload new binary assets, rename and delete entities (non-recursive, confirmation required).Multi-server support: log in to overleaf.com and multiple self-hosted instances, select servers per project query/open, and list known servers.
Provides collaborative LaTeX editing through Overleaf, including tracked changes, review comments, compilation, file management, and downloads of documents, projects, PDFs, and logs.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@overleaf-mcp compile my project and download the PDF"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Overleaf MCP by deepghs
Collaborative LaTeX editing through MCP: native tracked changes, review comments, compilation, downloads, and file management in one connection.
Based on netique/overleaf-mcp, with its Git history and AGPL license preserved. This version adds ten tools, for 27 tools total. Document edits use Overleaf's Socket.IO OT protocol rather than whole-file uploads or the Git bridge. This is an unofficial integration, not an Overleaf-supported API.
What This Version Adds
Log in to several Overleaf servers at once (overleaf.com plus any number of self-hosted instances) and pick one per
list_projects/open_projectcall.Keep the file tree in sync from the server's real-time broadcasts instead of re-joining the project after every file-management call.
Download document snapshots, binary assets, project ZIPs, PDFs, and compile logs.
Create empty documents and folders, upload new assets, rename and delete files.
Create native comments on unique selected text, with version checks and message/anchor readback verification.
Preserve the upstream tracked OT pathway for existing document text.
Fix self-hosted compilation requests that reject a null root document path.
Source installation only. npx @netique/overleaf-mcp runs upstream, not this
enhanced version. This repository is not published to npm; build it locally.
Related MCP server: overleaf-paper-mcp
Requirements
Node.js 20.18.1 or newer and npm (Node 22 LTS recommended).
A reachable Overleaf deployment and an authorized project account.
Server support for tracked changes and comments to use those features; self-hosting alone does not guarantee they are enabled.
A supported Chromium-family browser for interactive login.
Installation
git clone https://github.com/deepghs/overleaf-mcp.git
cd overleaf-mcp
npm ci
npm run build
npm testIf the repository is private, authenticate Git with an account that has access. Keep the checkout at a stable path. Rebuild after pulling changes and restart your MCP client to load the new code.
Authentication
SSH / Headless Servers
For self-hosted instances with ordinary email/password login:
export OL_BASE_URL=https://overleaf.example.org
node dist/index.js login --password
# Or prefill the email only:
node dist/index.js login --email user@example.org
node dist/index.js statusThe interactive terminal prompts for email and a hidden password. --password
is a mode switch, NOT a password argument. Never put passwords on the command
line. Only the validated session cookie is saved; passwords are not persisted.
Failed login leaves any existing saved session unchanged. Use ssh -t when
your SSH invocation does not allocate a terminal.
On Linux without DISPLAY/WAYLAND_DISPLAY, plain login selects password mode
automatically. Set OL_HEADLESS=1 to disable automatic browser login explicitly.
Missing/expired credentials during MCP calls produce instructions to log in
from SSH; the MCP stdio stream is never used for password prompts.
This requires HTTPS and a server that accepts password login without CAPTCHA,
SSO or 2FA. It does not bypass those challenges. Session expiry still requires
another interactive login; no stored password or automatic password renewal.
For interactive browser authentication use login --browser on a desktop.
Desktop Browser Login
For a self-hosted instance, use the same origin for login and MCP configuration:
OL_BASE_URL=https://overleaf.example.org node dist/index.js login
OL_BASE_URL=https://overleaf.example.org node dist/index.js statusFor hosted Overleaf, omit OL_BASE_URL. Login opens an isolated browser profile;
sign in there. Missing or expired credentials may trigger the same flow on a
tool call. CSRF tokens are normally discovered automatically.
Cookies are plaintext in <configDir>/overleaf-mcp/cookie.json, with mode 0600
where supported. On Linux, configDir is $XDG_CONFIG_HOME or ~/.config; on
macOS it is ~/Library/Application Support; on Windows it is %APPDATA%.
Never commit this store or its dedicated browser profile.
Use a dedicated collaborator account for clear attribution and limited project access. Otherwise edits and comments use the authenticated human's identity.
Multiple Overleaf Servers
Cookies are stored per host, so one MCP process can be logged in to overleaf.com
and any number of self-hosted instances at the same time. Every host with a
stored cookie is a known server, alongside OL_BASE_URL (the default) and
anything pre-declared in OL_SERVERS:
# Log in to each server once; --server takes a host or an origin URL.
node dist/index.js login --server overleaf.example.org
node dist/index.js login --server www.overleaf.com
node dist/index.js login --password --server lab.example.edu # headless host
node dist/index.js status # every known server
node dist/index.js logout --server overleaf.example.orgAt run time, list_servers shows the known servers and which one the open
project is on. list_projects without server queries every logged-in server
and tags each project with its server; open_project accepts the same
server argument and may omit it when the project was just listed or only one
server is logged in. One project is open at a time, and every project-scoped
tool acts on that project's server. Naming a server that has no stored cookie
starts the login flow for it (a browser window on desktops; on headless hosts an
error telling you which login --server command to run). A wrong server never
logs you out: the real-time service answers with connectionRejected, which is
reported as an API error, not treated as an expired cookie.
MCP Configuration
Codex
Replace the example origin and absolute path:
codex mcp add overleaf \
--env OL_BASE_URL=https://overleaf.example.org \
-- node /absolute/path/to/overleaf-mcp/dist/index.jsEquivalent TOML:
[mcp_servers.overleaf]
command = "node"
args = ["/absolute/path/to/overleaf-mcp/dist/index.js"]
[mcp_servers.overleaf.env]
OL_BASE_URL = "https://overleaf.example.org"JSON-Based Clients
{
"mcpServers": {
"overleaf": {
"command": "node",
"args": ["/absolute/path/to/overleaf-mcp/dist/index.js"],
"env": { "OL_BASE_URL": "https://overleaf.example.org" }
}
}
}Use an absolute Node executable path if the client cannot resolve node.
Restart the client after replacing a server configuration.
Tool Reference
Project-scoped tools use the project selected by open_project.
Group | Tools | Purpose |
Discovery |
| Inspect servers, projects and the live tree |
Editing |
| Read text/version and submit minimal tracked OT edits |
Review |
| Inspect and review pending suggestions |
Comments |
| Native review-panel threads |
Compilation |
| Remote build and diagnostics |
Downloads |
| Local snapshots, ZIP, or compile artifacts |
Files |
| Tree management without uploading over existing text |
Added Tool Arguments
Tool | Required arguments | Constraints / optional arguments |
| — | No network; default, |
| — | Optional |
|
| Optional |
|
| Existing text or binary file |
|
| ZIP only, no extraction |
|
| Optional |
|
| Empty document; parent must exist |
|
| Single folder; parent must exist |
|
| New PNG/JPEG/GIF/WebP/PDF/EPS/ZIP assets only |
|
| Basename in the same parent; target must not exist |
|
| Requires |
|
| Unique text and the version from |
Remote paths are project-relative. local_path and output_path must be
absolute. Downloads require an existing parent and never overwrite a destination,
including a symlink at the destination path.
Recommended Workflow
Open the project and read the target document and relevant comments.
Edit with
track: "on",expected_versionfrom the read, andstrict_version: truewhen other writers are active.On stale-version rejection, read again and recompute the edit. Upstream refreshes its cache on rejection; blindly retrying old
new_contentagainst that cache can remove another writer's new text.Read back the result, compile, inspect diagnostics, and download the PDF.
Reply to the relevant thread. Leave suggestions and threads pending until the author explicitly requests acceptance or resolution.
Example requests:
Improve the introduction as tracked changes. Preserve citations and factual claims. Re-read and recompute if the document version changes.
Add a comment on this unique sentence explaining the missing experimental detail. Do not change the document text.
Compile the open project and download output.pdf and output.log to these absolute paths without overwriting existing files.
Safety and Compatibility
No upload fallback for text. Uploads refuse existing targets and text files. Create empty documents, then insert their content through tracked OT.
The file tree follows the server's real-time broadcasts (
reciveNewDoc,removeEntity,reciveEntityRename, ...), so collaborators' changes and your own file-management calls show up without re-joining the project, and cached document text survives them (a deleted doc is dropped from the cache). Each file-management call waits for its own broadcast and reportstree_sync: "event"; if none arrives within 5 s it re-joins the project once and reportstree_sync: "reconnect", which also clears the document cache. File-management calls are serialized with each other within one process, not with every upstream tool. Do not overlap them with project switching or text edits.Remote filename checks are not atomic with server writes. Do not create the same filename simultaneously from different clients; cross-client races are not covered by the collision guard.
A comment message and its anchor are separate writes. Partial failures return a thread ID to inspect before retrying; creation is not transactional.
Verification covers the upstream ShareJS path, not history-OT compatibility. This fork does not add live cursors or complete browser presence behavior.
OT preserves independent operations, not semantic agreement about a sentence. Reconnection and every possible concurrency failure mode are not certified.
A PDF may be generated despite LaTeX errors. Inspect
error_countand the log. A missing/unreadable log is not proof of a clean build, even if upstream reportsbuilt_cleanly.Cookies grant account access. Use trusted MCP clients, authorized accounts, and automation consistent with the deployment's applicable terms.
Environment Variables
Variable | Purpose |
| Default server origin; |
| Extra servers to pre-declare (comma/space separated hosts or origins); hosts with a stored cookie are known without this |
|
|
| Explicit Chromium-family browser executable |
| Optional CSRF override |
|
|
| Browser-login certificate exception; avoid normally and do not assume it fixes Node TLS |
Tests and Development
npm run typecheck
npm run build
npm test
git diff --checkOn September 10, 2026, this version passed 25 unit tests and live MCP stdio tests against a self-hosted deployment. Coverage included tracked insertion, anchored comment readback, stale-version rejection, binary byte roundtrips, file-management protections, PDF/log/ZIP downloads, and two-client OT merging at different positions. This was not browser visual QA or exhaustive testing of every upstream tool or every Overleaf version.
On September 22, 2026, the multi-server and tree-sync changes passed 48 unit
tests plus a live two-client run against a self-hosted deployment: eight
file-management calls (create, rename, edit, delete across two clients) all
confirmed through broadcasts with tree_sync: "event", the second client saw
the first client's changes without re-opening, and the run used exactly one
socket connection per client. Multi-server logic was exercised with one
logged-in server and one without a cookie (aggregate listing, automatic server
pick, fast failure on the cookie-less server without disturbing the open
project). Two servers logged in simultaneously was covered by unit tests only.
The opt-in integration test modifies its supplied disposable project and leaves review evidence there. It imports an existing olcli credential into an isolated cookie store after checking its origin:
export OL_BASE_URL=https://overleaf.example.org
export OL_TEST_COOKIE_CONFIG=/absolute/path/to/olcli-nodejs/config.json
export XDG_CONFIG_HOME="$(mktemp -d)"
node tests/manual/extensions.mjs DISPOSABLE_PROJECT_IDProtect that isolated directory: it contains authentication state and downloaded artifacts. Never run this test against a production manuscript.
Run npm audit before deployment. The inherited lockfile had dependency
advisories during verification; this feature branch did not resolve them.
No npm publication or production security certification is implied.
Troubleshooting
Missing tools: build this checkout and point the client to its entry point, not upstream npm or the olcli executable.
Login required: use the same
OL_BASE_URLfor login and MCP configuration.Missing parent / existing destination: create parents first and choose a new filename; edit existing text through OT.
Output unavailable: compile the currently open project, then choose a filename listed in
output_files.No tracked suggestions: check project/user settings and server feature support; do not silently fall back to untracked uploads.
Attribution and License
AGPL-3.0-or-later, see LICENSE. Preserve notices and comply with the license when distributing or operating modifications.
netique/overleaf-mcp: upstream server, authentication, OT editing, tracked-change review, and comment operations.
overleaf-workshop and overleaf/overleaf: protocol and code sources acknowledged by the original project.
googlecolab/colab-mcp: upstream UX reference.
The additions use existing server abstractions; no olcli implementation was copied. olcli credentials are only an optional input to the integration test.
Available Tools
26 toolsaccept_changesAccept tracked changes by idA
Permanently accepts the specified tracked-change suggestions. The text stays in the doc; the pending-change metadata is cleared. Pass the change_id values from list_tracked_changes. Changes that span multiple docs are grouped automatically. Irreversible.
Inputs: change_ids (required).
add_commentA
Create a native anchored comment on unique selected text. expected_version must come from read_file. Refuses stale versions. Does not change document text.
Inputs: path (required), content (required), selected_text (required), expected_version (required).
compileCompile the open Overleaf projectA
Triggers a LaTeX compile on Overleaf's CLSI, then fetches output.log and returns a unified summary: status, whether a PDF was produced, error_count (parsed ! -prefixed log lines), warning_count, first error lines, output file list, timings. Note: Overleaf returns status:"success" even when LaTeX has errors (PDF is still generated under nonstopmode). The truthful 'did it build cleanly?' check is error_count === 0. Use read_log for the full log when more context is needed.
Inputs: draft, root_doc, stop_on_first_error.
create_fileA
Create an empty text document. Use edit_file for tracked content insertion.
Inputs: path (required).
create_folderA
Create one folder in the open project. Parent must exist.
Inputs: path (required).
delete_entityADestructive
Delete a file or folder. Requires explicit confirmation; recursive folder deletion is refused.
Inputs: path (required), confirm (required).
download_fileC
Download a document snapshot or binary file from the open project.
Inputs: path (required), output_path (required).
download_outputA
Download an artifact from the last compile. Run compile first. Defaults to output.pdf.
Inputs: output_path (required), artifact.
download_projectB
Download the open project as a ZIP archive (no extraction).
Inputs: output_path (required).
edit_fileEdit a .tex doc in the open Overleaf projectA
Replaces the contents of a doc by computing a minimal diff and submitting it as an OT operation over the live Socket.IO connection. The change lands in the web editor in real time. By default the edit appears as a pending suggestion in the Review panel (track:'on'); pass track:'off' to write directly. If path is omitted, defaults to the project's root doc. Only .tex / .bib / .md / similar text docs are editable — binary files are not.
Inputs: new_content (required), path, track, strict_version, +1 more.
find_and_replaceSurgical find-and-replace in an Overleaf docA
Replace one occurrence — or all, with replace_all: true — of old_string with new_string in a doc, without re-emitting the rest of the file. By default old_string must be unique; ambiguous matches are returned with line:column locations so you can extend the match. Submits the minimal OT operation through the same pathway as edit_file, so by default it lands as a pending suggestion in Overleaf's Review panel (track:'on'). If path is omitted, defaults to the project's root doc. USE WHEN: a SINGLE targeted edit (one typo, one label rename, one heading change) in a large doc — saves tokens vs. re-emitting the body and avoids accidental whitespace drift. AVOID FOR BATCH WORK: for multiple substitutions (e.g. converting many words, applying a style guide across a chapter) prefer ONE edit_file call with all changes computed client-side. Each find_and_replace is its own round-trip with its own race window, its own tracked-change entry, and its own cache-sync cycle — calling it N times for N small changes amplifies the failure modes that one batched edit_file would avoid.
Inputs: new_string (required), old_string (required), path, track, +3 more.
list_commentsList review-panel comment threadsARead-only
Returns all review-panel comment threads in the open project, sorted by most recently updated. Each entry includes the thread id, the doc path it's anchored on, the quoted text it refers to, the latest message preview, and whether it's resolved. Use read_comment_thread for full content.
Inputs: full, path_contains, include_resolved.
list_filesList files in the open Overleaf projectARead-onlyIdempotent
Returns the file tree of the currently open project as a flat list of project-relative paths. Cheap — uses cached data from open_project, no network. Each entity has a path (e.g. 'chapters/intro.tex'), an id, and a kind ('doc' | 'file' | 'folder').
Inputs: kind, path_contains.
list_projectsList Overleaf projectsARead-onlyIdempotent
Lists projects on the configured Overleaf account, sorted by most recently updated. Returns each project's id, name, last update time, and owner. Use the returned id with open_project to start working on a project.
Inputs: limit, name_contains, include_trashed, include_archived.
list_tracked_changesList pending tracked changes across the open projectARead-only
Enumerates every pending tracked-change suggestion in the open project (across all docs), with author name + email, doc path, op kind ('insert' | 'delete'), position, inserted/deleted text, and a stable change_id. Use this to plan an accept_changes or reject_changes call: filter the result by author / doc / kind / text, collect the matching change_id values, then pass them. Tracked changes only — review-panel comments are listed by list_comments.
Inputs: kind, limit, full_text, author_email, +3 more.
open_projectOpen Overleaf projectA
Joins the project's real-time Socket.IO session and caches its file tree. Must be called before list_files / read_file / edit_file. Switching projects automatically closes the previous session.
Inputs: project_id (required).
pingPingARead-onlyIdempotent
Health check. Returns 'pong' and the server version. Does not contact Overleaf.
Inputs: no named parameters.
read_comment_threadRead a single comment thread's messagesARead-only
Fetches the full message history of one thread (all replies with author + timestamp). Use this when list_comments shows a thread that looks relevant.
Inputs: thread_id (required).
read_fileRead a file from the open Overleaf projectARead-only
Reads the contents of a file by project-relative path. For text docs (.tex, .bib, .md, etc.) the full text appears in both the content array and structuredContent.text; metadata (version, line/byte counts, ranges, tracked-change/comment counts) is in structuredContent. For binary files (images, PDFs) base64 is in content and structuredContent.base64, with MIME type alongside.
Inputs: path.
read_logRead the last compile's output.logARead-only
Returns the full LaTeX log from the most recent compile call. compile already includes the error count + first few errors in its response — use this only when you need more context (full log, line numbers, package warnings, etc.). The content array shows a summary of !-prefixed error lines at the top, then the log truncated to the last 8000 chars for display. structuredContent.log contains the FULL untruncated log so programmatic callers can grep / parse it.
Inputs: no named parameters.
reject_changesReject tracked changes by idA
Rejects the specified tracked-change suggestions. For tracked inserts the inserted text is removed; for tracked deletes the strikethrough is cleared and the text stays. Implemented as an OT update with u:true flags on the inverse ops — same pathway Overleaf's web client uses. Pass the change_id values from list_tracked_changes. Irreversible.
Inputs: change_ids (required).
rename_entityADestructive
Rename a file or folder within its current parent; refuses existing targets.
Inputs: path (required), new_name (required).
reopen_commentReopen a resolved comment threadB
Reopens a previously-resolved thread.
Inputs: thread_id (required).
reply_commentPost a reply to a comment threadA
Adds a new message to an existing comment thread. Threads come from list_comments. The message appears immediately in Overleaf's review panel for collaborators.
Inputs: content (required), thread_id (required).
resolve_commentResolve a comment threadA
Marks a thread as resolved. Use after addressing the comment (e.g. by editing the doc and replying).
Inputs: thread_id (required).
upload_fileA
Upload a NEW binary asset only. Existing targets and text files are refused; use create_file and OT edits for text. Do not run concurrently with other tree changes.
Inputs: path (required), local_path (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 26 tools
Each tool has a clearly distinct purpose. Comment operations (list, read, reply, resolve, reopen, add), tracked changes (list, accept, reject), file operations (create, read, edit, delete, rename, upload), downloads (file, project, output), and compile/log functions are all non-overlapping. Even similar-sounding tools like edit_file and find_and_replace are clearly differentiated.
Tool names follow a consistent verb_noun pattern throughout (read_comment_thread, list_projects, open_project, list_files, read_file, edit_file, compile, read_log, list_comments, reply_comment, resolve_comment, reopen_comment, list_tracked_changes, accept_changes, reject_changes, download_file, download_project, download_output, create_folder, create_file, upload_file, rename_entity, delete_entity, add_comment). The slight deviation of find_and_replace and ping does not break the overall pattern.
With 26 tools, this server is above the typical 3-15 range but is justified by the breadth of Overleaf's feature set. The tools cover project management, editing, comments, tracked changes, compilation, and downloads, each earning its place. It could be trimmed slightly (e.g., consolidating download_* tools) but is reasonably scoped.
The tool surface covers the full lifecycle of working with an Overleaf project: listing/opening projects, navigating and editing files, creating and managing entities, compiling and reading logs, handling comments and tracked changes, and downloading artifacts. No obvious gaps exist for typical agent workflows; the only missing operations would be administrative tasks like sharing or project deletion, which are out of scope for an MCP server.
Maintenance
Related MCP Connectors
Collaborative LaTeX editor: edit, compile and share PDFs, with full version history.
Edit your Overleaf LaTeX projects from Claude and ChatGPT; every change is a real Git commit.
Overleaf alternative online LaTeX editor. AI agents edit, comment, and chat. Keep or revert edits.
MCP-native collaborative markdown editor with real-time AI document editing
Related MCP Servers
- AlicenseAqualityCmaintenanceAn MCP server for Overleaf that allows Claude or other agents to navigate projects, read and edit .tex files, compile, and interact with review-panel comments via Overleaf's real-time Socket.IO API, with seamless support for tracked changes as pending suggestions.1759 npm7AGPL 3.0
- AlicenseAqualityDmaintenanceMCP server for managing academic LaTeX projects in Overleaf: create projects, transfer files, compile documents, inspect compiler output, and download PDFs.1611 npmMIT
- AlicenseAqualityCmaintenanceEnables AI agents to read, write, compile, and manage Overleaf projects through MCP, including file operations, project administration, and LaTeX compilation diagnostics.169 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to read, edit, upload, compile, and manage projects in a self-hosted Overleaf Community Edition via MCP, while also providing a git remote for cloning and pushing changes.1MIT