axiomlogicnexus/Overleaf-LaTeX-MCP-Server
If you are the rightful owner of Overleaf-LaTeX-MCP-Server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
The Overleaf LaTeX MCP Server is a TypeScript/Node.js server that facilitates communication between LLM clients and Overleaf's compilation and Git functionalities.
Overleaf LaTeX MCP Server
TypeScript/Node.js server that brokers between LLM clients and Overleaf compilation and Git surfaces.
- Primary control plane: HTTP endpoints (MCP tool registration will mirror these in upcoming work)
- Language/runtime: Node.js 20+ with TypeScript
- Security rails: no shell:true, path containment, per-project policies
See ROADMAP.md, ARCHITECTURE.md, API.md, PRD.md, DEVELOPMENT.md, and global_rules.md for details.
Build and Run
- Install
npm ci
- Build TypeScript to dist/
npm run build
- Run server
node dist/server.js
- Default port: 8080 (set PORT to override)
- Creates/uses top-level directories:
workspaces/
andartifacts/
Dev mode (watch):
npm run dev
Configuration (projects.json)
Place a projects.json
file in the repository root to define per-project policies and metadata.
Example (Cloud + local):
{
"defaultPolicy": {
"shellEscape": "off",
"allowedExtensions": [".tex", ".bib", ".png", ".jpg", ".jpeg", ".pdf", ".eps", ".svg", ".txt"],
"maxFileSizeBytes": 10485760,
"maxProjectSizeBytes": 209715200,
"allowedCompilers": ["pdflatex", "xelatex", "latexmk"]
},
"projects": {
"demo": {
"name": "Demo Project",
"projectId": "demo",
"gitUrl": "https://git.overleaf.com/<cloud-project-id>"
},
"local-only": {
"name": "Local Project",
"projectId": "local-only"
}
}
}
Notes:
- Do not store tokens in projects.json. For Overleaf Cloud, pass credentials via the remote URL when calling
/git/startSession
, or rely on a credential helper (recommended). - Self-hosted/local: no tokens required; copy files directly into
workspaces/<projectId>/
.
Overleaf Cloud vs Self-hosted
- Overleaf Cloud (Git):
- Use
/git/startSession
with a remote URL embedding credentials:https://<username>:<token>@git.overleaf.com/<project-id>
- Commit and push via
/git/commitPatch
and/git/pullPush
.
- Use
- Self-hosted/local:
- Work directly under
workspaces/<projectId>/
and compile locally. - If your Overleaf instance exposes Git, use its remote URL with
/git/startSession
.
- Work directly under
Insomnium Quickstart (copy/paste bodies)
Create an environment:
- base_url: http://localhost:8080
- projectId: demo
- remoteUrl_cloud (optional): https://
: @git.overleaf.com/
Prepare workspace (local flow):
- Create
workspaces/demo/main.tex
with:
\documentclass{article}
\begin{document}
Hello, Overleaf MCP Server.
\section{Intro}
This is a test.
\end{document}
A) Compile sync
- POST {{base_url}}/compile
- Body: { "projectId": "{{projectId}}", "rootResourcePath": "main.tex", "options": { "compiler": "latexmk" } }
- Expect diagnostics and artifact URLs (pdfUrl/logUrl/synctexUrl). GET the
pdfUrl
to download.
B) Compile async
- POST {{base_url}}/compileAsync
- Body: { "projectId": "{{projectId}}", "rootResourcePath": "main.tex", "options": { "compiler": "latexmk" } }
- Then GET {{base_url}}/compileStatus?operationId=
C) Text get
- POST {{base_url}}/text/get
- Body: { "projectId": "{{projectId}}", "filePath": "main.tex" }
D) Text patch (hash-validated)
- Compute expectedHash of the segment being replaced (see DEVELOPMENT.md for tips), then:
- POST {{base_url}}/text/patch
- Body:
{
"projectId": "{{projectId}}",
"filePath": "main.tex",
"baseHash": "
", "patches": [ { "startLine": 5, "endLine": 5, "expectedHash": " ", "newText": "This is an edited test." } ] }
E) Git start session
- POST {{base_url}}/git/startSession
- Body (Cloud): { "projectId": "{{projectId}}", "remoteUrl": "{{remoteUrl_cloud}}" }
F) Git commit
- POST {{base_url}}/git/commitPatch
- Body: { "projectId": "{{projectId}}", "message": "feat: test commit" }
- Policy blocks large files and LFS pointers.
G) Git pull/push
- POST {{base_url}}/git/pullPush
- Body: { "projectId": "{{projectId}}", "mode": "ff-only" }
H) Projects and status
- GET {{base_url}}/projects
- GET {{base_url}}/statusSummary?projectId={{projectId}}
I) Health, capabilities, metrics
- GET {{base_url}}/health
- GET {{base_url}}/capabilities
- GET {{base_url}}/metrics
J) Security checks
- Path traversal rejection:
- POST /text/get with { "projectId": "{{projectId}}", "filePath": "../outside.txt" } → expect error
- Disallowed extension in text ops:
- Ensure policy disallows extension (e.g., .sh), then POST /text/get with that file → expect error
LLM Integration (current state)
- The server currently exposes HTTP endpoints; a minimal MCP HTTP bridge is available.
- To exercise the same handlers via the bridge:
- GET /mcp/tools → lists tool names and descriptions
- POST /mcp/invoke with body
{ "tool": "<name>", "input": { ... } }
- For LLMs with function-calling, map tools to /mcp/invoke with JSON schema validation.
- Upcoming work: proper MCP transport so MCP-enabled clients can discover and invoke tools directly (no HTTP shim required).
Next Steps (high level)
- Register MCP tool handlers for: compile, artifacts, text patching, git session, projects, health/capabilities.
- Enhance diagnostics taxonomy (errors/warnings with codes) and file/line extraction.
- Add binary/LFS detection to pre-receive emulation for push.
- Add list_projects and status_summary MCP tools and auto-generate API docs from schemas.
Notes
- Authentication/SSO (Auth0) is out of scope. For Overleaf Cloud, pass username/token in the remote URL or use OS credential helper.
- For Windows, WSL/Docker is recommended for more consistent LaTeX toolchain behavior.