overleaf-mcp

overleaf-mcp

An MCP server for self-hosted Overleaf Community Edition that lets coding agents create projects, write LaTeX, compile, and receive structured diagnostics while humans edit the same document in the browser.

Category
访问服务器

README

overleaf-mcp

An MCP server for self-hosted Overleaf Community Edition. Lets a coding agent create projects, write LaTeX, compile, and read back structured diagnostics — while a human edits the same document in the browser.

compile → {
  "verdict": "FAILED with 1 fixable LaTeX error(s)",
  "errors": [{
    "file": "./main.tex", "line": 4,
    "message": "Is \\usepackage{natbib} missing?",
    "fixable": true
  }]
}

The raw log said ! Undefined control sequence.


Why this exists

Existing Overleaf MCP servers target overleaf.com and authenticate one of two ways:

  • Git bridge — the most popular ones. Unusable on Community Edition: the git bridge is a Server Pro feature. The CE image neither builds nor starts it (absent from server-ce/services.js, server-ce/runit/, and the Dockerfile), and Features.mjs gates it on Settings.enableGitBridge, which CE never sets.
  • Session cookies / headless browser — works, but sessions expire, CSRF has to be handled, and login-flow changes break it.

Self-hosting opens a third door that overleaf.com users cannot reach, because it is an internal interface there: Overleaf's own privateApiRouter, authenticated with plain HTTP Basic. No session, no CSRF, no browser.

What it does differently

Structured diagnostics, not raw logs. Vendors Overleaf's own log parser and its 1200-line ruleset — years of accumulated knowledge translating cryptic TeX messages into actionable ones, including a command→package map (\citep → natbib, \toprule → booktabs).

Separates "fix your LaTeX" from "fix your server." A missing package is not something an agent can solve by editing source. Conflating the two is what makes agents loop until they run out of context — the failure mode The AI Scientist reports as a central bottleneck. Compare:

verdict: FAILED with 1 fixable LaTeX error(s) — see errors[] for file/line.

verdict: BLOCKED: the server environment cannot build this document —
         missing package/class file hyperxmp.sty. Install it on the server
         (tlmgr install ...); the agent cannot fix this in source.
         Do not retry without changing the server.

Both are "compile produced no PDF." Only one is worth another attempt.

Architecture

Two backends, because neither alone suffices:

Concern Backend Why
Project CRUD api process :3000 Stable HTTP Basic interface — the one Dropbox/GitHub sync uses
Compilation CLSI :3013 Returns output.log. The web API's compile endpoint obtains a buildId internally and never exposes it, so diagnostics are unreachable through it

Writes enter through EditorController.upsertDocWithPath — the same entry point the web UI uses. For an existing document that reaches DocumentUpdaterHandler.setDocument, which diffs old against new and applies the result as an operational transform. An agent write is merged into the live document exactly like a keystroke: a human with the project open sees it immediately, their cursor survives, and it lands in project history.

Verified against a live instance: with the document loaded in document-updater, an agent write moved it from version 0 to version 1 — an incremental operation, not a reload.

Requirements

  • Self-hosted Overleaf Community Edition (Server Pro works too)
  • Shell access to the host running it
  • Node.js ≥ 20 wherever the MCP server runs
  • Overleaf reachable over HTTPS

Setup

1. Enable agent access on the server

git clone https://github.com/lintheyoung/overleaf-mcp
cd overleaf-mcp

# Kubernetes / k3s (Zeabur, Coolify, ...)
bash deploy/setup.sh --k8s --namespace <ns> --deployment <name>

# docker compose — not yet verified end to end, see Caveats
bash deploy/setup.sh --docker --container sharelatex

Find the namespace and deployment with kubectl get deploy -A | grep -i overleaf; for compose it is the service name in docker-compose.yml (usually sharelatex).

This generates secrets under /etc/overleaf-agent, injects them so Overleaf uses them, and installs an nginx reverse proxy exposing two prefixes:

Path Upstream Guard
/agent-api/ Overleaf api :3000 HTTP Basic (app) + path allow-list (nginx)
/agent-clsi/ CLSI :3013, artifacts :8080 X-Agent-Token (nginx)

It mounts at /etc/nginx/vhost-extras/overleaf/, an include directory the stock Overleaf vhost already provides — no vendor file is overwritten.

[!CAUTION] CLSI has no authentication of its own. It runs arbitrary LaTeX, which on Community Edition means arbitrary code execution inside the container with filesystem and network access. The token gate is not optional hardening; it is the only thing standing in front of it. Never expose :3013 directly.

The allow-list matters too: privateApiRouter also carries endpoints for user expiry and project deactivation. Only what an agent needs is routed; everything else under /agent-api/ returns 404 even with valid credentials.

2. Survive redeploys (managed platforms)

Platforms like Zeabur own the Deployment. A restart keeps the configuration above; a redeploy rebuilds from the platform's spec and silently drops it — the API starts answering 401 and the routes 404.

sudo install -m 700 deploy/restore.sh /usr/local/sbin/overleaf-agent-restore.sh
sudo install -m 644 deploy/systemd/* /etc/systemd/system/
sudo systemctl enable --now overleaf-agent-restore.timer

Runs 3 minutes after boot, then hourly. It is a no-op when nothing is missing — patching a Deployment triggers a rollout, so an unconditional timer would restart Overleaf every hour.

3. Build and register the server

npm install && npm run build

npm run vendor (invoked by build) fetches Overleaf's log parser from GitHub. See Licensing.

Find the Overleaf user id that should own agent-created projects — visible in the URL when viewing that user in the admin panel, or from the database.

{
  "mcpServers": {
    "overleaf": {
      "command": "node",
      "args": ["/path/to/overleaf-mcp/dist/index.js"],
      "env": {
        "OVERLEAF_BASE_URL": "https://overleaf.example.com",
        "OVERLEAF_API_USER": "overleaf",
        "OVERLEAF_API_PASS": "<from /etc/overleaf-agent/api_pass>",
        "OVERLEAF_CLSI_TOKEN": "<from /etc/overleaf-agent/clsi_token>",
        "OVERLEAF_OWNER_ID": "<overleaf user id>"
      }
    }
  }
}

4. Verify

node dist/dev/selftest.js   # offline — diagnostics layer only
node dist/dev/smoke.js      # end-to-end against the live instance

smoke creates a project, writes broken LaTeX, checks the diagnostic names natbib, applies the fix, and confirms a PDF comes out.

Configuration

Variable Required Default Meaning
OVERLEAF_BASE_URL yes e.g. https://overleaf.example.com
OVERLEAF_API_USER yes WEB_API_USER (usually overleaf)
OVERLEAF_API_PASS yes WEB_API_PASSWORD
OVERLEAF_OWNER_ID yes Overleaf user id owning created projects
OVERLEAF_CLSI_TOKEN for diagnostics Must match the nginx config
OVERLEAF_API_PATH no /agent-api
OVERLEAF_CLSI_PATH no /agent-clsi Empty disables diagnostics
OVERLEAF_TIMEOUT_MS no 120000 Raise for long bibliographies

Without OVERLEAF_CLSI_TOKEN the server still runs, but only get_pdf works — no diagnostics.

Tools

Tool Notes
create_project Returns id + web URL
list_files / read_file Reads back from Overleaf, so human edits are visible
write_file Whole-file replace, merged as an OT
delete_file
compile Structured diagnostics. Does not return the PDF
get_pdf Writes the PDF to disk, returns the path
get_log Raw log, tail-truncated. Last resort

compile withholds PDF bytes deliberately — base64 of a paper would swamp an agent's context for no benefit.

Working alongside a human

OT guarantees no data is lost, not that the result is what you wanted:

The agent reads intro.tex at T0. A human rewrites a paragraph at T1. The agent writes back its T0-derived text at T2. The human's edit is gone from the live document — recoverable from history, but they will not know to look.

Split the paper and give each file an owner:

main.tex              skeleton, rarely touched
sections/intro.tex    agent
sections/related.tex  human

Physical separation beats relying on merge semantics. See CLAUDE.md for rules to hand your agent.

TeX Live packages

deploy/tlget.sh installs packages into TEXMFHOME by unpacking tlnet archives directly, working around two tlmgr behaviours that bite containerised Overleaf:

  • "package X is not relocatable, cannot install it in user mode" — tlmgr refuses to place some packages under TEXMFHOME, the only TeX tree on the persistent volume. The system tree is inside the image and is wiped on every restart. hyperxmp, required by acmart, is one of these.
  • "tlmgr itself needs to be updated" — CTAN's tlnet only carries the current release, so once upstream moves on the tlmgr baked into the image cannot install anything at all.
bash deploy/tlget.sh <namespace> <deployment-substring> hyperxmp

A tlnet archive is just a tarball of a texmf-dist tree, so unpacking it into TEXMFHOME sidesteps both problems and lands the files on the volume.

Licensing

This project is MIT (see LICENSE).

src/vendor/ is not part of it and is not committed. npm run vendor fetches five files from overleaf/overleaf at build time; those remain AGPL-3.0 and belong to Overleaf. Keeping them out of the repository is what keeps the licences separate — otherwise AGPL's network-use clause would extend to everyone running this server.

To pin or audit the fetch:

OVERLEAF_REF=v5.5.4 npm run vendor      # pin to a tag
npm run vendor -- /path/to/overleaf     # use a local checkout

Overleaf is a trademark of Overleaf Inc. This project is not affiliated with or endorsed by them.

Caveats

  • Community Edition has no compile sandbox. Any logged-in user can read container environment variables through LaTeX. Upstream says as much. Only give accounts to people you trust, and do not open registration.
  • write_file replaces whole files. There is no patch/append tool yet.
  • Compilation is synchronous. A bibliography-heavy document takes 20 s+; CLSI's own ceiling is 600 s.
  • Verified against Overleaf CE 5.x on k3s. The --docker path in setup.sh is written but not yet tested end to end — it also cannot inject the environment variables automatically, so that step is manual. Reports welcome.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选