overleaf-bridge
by igotstatik
README.md
# overleaf-bridge
Agent access to a self-hosted Overleaf **Community Edition**: an MCP server and
a git remote, so any agent (Claude Code, OpenCode, Cursor, Codex, your own) can
read, edit, upload to and compile Overleaf projects. CE has no git-bridge and
no API; this fills that gap without patching Overleaf. See [DESIGN.md](DESIGN.md).
## How it works, in one paragraph
The bridge is an ordinary Overleaf user (`agent@…`). It sees only the projects
you **share with it**. Document edits go through Overleaf's own realtime
pipeline, so collaborators see them instantly and history shows the agent as
the author. Externally, one bearer token protects both the MCP endpoint and the
git remote. It runs as its own docker-compose project next to the
[Overleaf Toolkit](https://github.com/overleaf/toolkit) and never modifies it.
## Requirements
- Overleaf CE deployed with the Overleaf Toolkit (containers `sharelatex`,
`mongo`, network `overleaf_default`). Tested with CE 6.2.
- Docker Compose v2.
- A public hostname (or two) that reaches this host — e.g. via a Cloudflare
Tunnel, nginx, or Caddy — forwarding to `127.0.0.1:3900`.
## Deploy
1. **Create the agent user** in Overleaf (from the toolkit directory):
```bash
bin/run-script /overleaf/services/web/modules/server-ce-scripts/scripts/create-user.js \
--email=agent@overleaf.example.com
```
Open the activation link it prints and set a password.
2. **Configure and start the bridge:**
```bash
cp .env.example .env # fill in OVERLEAF_SITE_HOST, agent credentials, BRIDGE_TOKEN, BRIDGE_ALLOWED_HOSTS
bin/up # builds and starts `bridge` + `edge`
curl -s -H "Authorization: Bearer $BRIDGE_TOKEN" http://127.0.0.1:3900/health # -> ok
```
3. **Expose it.** Point your public hostname(s) at `http://127.0.0.1:3900`.
With a Cloudflare Tunnel, add to the tunnel's ingress:
```yaml
- hostname: mcp.example.com
service: http://127.0.0.1:3900
- hostname: git.example.com
service: http://127.0.0.1:3900
```
then `cloudflared tunnel route dns <tunnel> mcp.example.com` (same for
`git.`) and restart cloudflared. One hostname for both is fine too — the
bridge routes by path (`/mcp`, `/git/...`). Every hostname must be listed in
`BRIDGE_ALLOWED_HOSTS`.
## Give an agent access to a project
In Overleaf: open the project → **Share** → add the agent's email with
*Can edit*. Remove it from Share to revoke. That is the whole permission model.
Sharing creates an *invite*; the bridge accepts it itself (on startup, on
`list_projects`, and whenever a request hits a 403), so the project is usable
right after you click Share — no email delivery needed.
## Connect an agent
**Claude Code**
```bash
claude mcp add --transport http overleaf https://mcp.example.com/mcp \
--header "Authorization: Bearer <BRIDGE_TOKEN>"
```
**OpenCode** (`opencode.json`):
```json
{
"mcp": {
"overleaf": {
"type": "remote",
"url": "https://mcp.example.com/mcp",
"enabled": true,
"headers": { "Authorization": "Bearer <BRIDGE_TOKEN>" }
}
}
}
```
**Cursor / any MCP client** (`mcp.json`):
```json
{ "mcpServers": { "overleaf": {
"url": "https://mcp.example.com/mcp",
"headers": { "Authorization": "Bearer <BRIDGE_TOKEN>" } } } }
```
Tools: `list_projects`, `list_files`, `read_doc`, `edit_doc` (exact-fragment
patch; fails safely if the document changed), `write_doc` (create/rewrite),
`upload_file`, `download_file`, `delete_path`, `compile` (optionally
`root_doc="supplementary.tex"`), `get_compile_log`, `get_pdf`,
`get_messages` / `post_message` (project chat), `get_history` (who changed
what, with diffs).
**git**
```bash
git clone https://x:<BRIDGE_TOKEN>@git.example.com/git/<project_id>.git
# edit, commit, then:
git push
```
The username is ignored; the token is the password. `<project_id>` is the id
in the project's URL (`/project/<id>`) or from `list_projects`.
- `clone`/`pull` always reflect Overleaf as of that moment (a snapshot commit
is added when something changed).
- `push` applies your commits to Overleaf. If Overleaf changed since your last
pull, the push is **rejected** — pull, merge, push again. Only `main`,
fast-forward only.
- `.tex/.bib/.cls/.sty/.bst/.txt/.md/.csv` are written as documents; anything
else is uploaded as a file.
## Operating
| | |
|---|---|
| Logs | `bin/logs` |
| After an Overleaf upgrade | `bin/restart` (the bridge borrows the `sharelatex` network namespace) |
| Live end-to-end test | `bin/smoke <project_id>` on a throwaway project owned by/shared with the agent |
| Unit tests | `uv run pytest` |
| Rotate the token | edit `.env`, `bin/up`, update agents |
| New public hostname | add it to `BRIDGE_ALLOWED_HOSTS` (the MCP transport answers 421 to unknown `Host` headers) |
## What Community Edition does not have
Comments and track changes are a Server Pro feature; CE has no review panel
and no API for it, so the bridge cannot read them. Use the project chat
(`get_messages`/`post_message`) for remarks between people and agents, and
`get_history` to see what changed.
## Limits
One shared token for all agents; Overleaf's internal routes are not a public
API and may shift across major upgrades — `bin/smoke` catches that.
Login is rate-limited by Overleaf (10 per 2 minutes per user); the bridge
keeps one session, but many rapid git pushes each log in once.
## License
MIT.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues