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

A Model Context Protocol (MCP) server that spans **every project on your Overleaf
account**. It auto-discovers your project list, then reads and edits files across
any of them from Claude Code — with a review-before-push local-workspace flow.

Design rationale, trade-offs, and the ToS discussion live in
[`OVERLEAF_MCP_ARCHITECTURE.md`](./OVERLEAF_MCP_ARCHITECTURE.md). This README is
just setup + usage.

## How it works (two auth paths)

| Concern | Mechanism | Where |
|---|---|---|
| **Content I/O** (read/commit/push/history) | `olp_` git token over the sanctioned Git integration | `git.overleaf.com` |
| **Discovery** (listing your projects) | `overleaf_session2` session cookie → internal JSON | `overleaf.com/user/projects` |

The token does all file work. The cookie is used **only** to list projects — never
for content. See the architecture doc's §6 for the ToS caveat around the cookie call.

## Prerequisites

- Node.js ≥ 18 (uses global `fetch`)
- The `git` binary on `PATH`

## Install

```bash
cd /Users/longngo/IdeaProjects/overleaf-mcp
npm install
```

## Configure auth

All state lives in `~/.config/overleaf-mcp/` (override with `OVERLEAF_CONFIG_DIR`).

### 1. Git token (required — content)

Overleaf → **Account Settings → Git Integration** → generate a token (`olp_…`).
The same token works for every project you own.

```bash
mkdir -p ~/.config/overleaf-mcp
printf '%s' 'olp_your_token_here' > ~/.config/overleaf-mcp/token.txt
chmod 600 ~/.config/overleaf-mcp/token.txt
```

(Or set `OVERLEAF_TOKEN` in the environment.)

### 2. Session cookie (optional — discovery only)

Only needed for `sync_projects` / `list_projects`. In a logged-in browser:
DevTools → Application → Cookies → `https://www.overleaf.com` → copy the
`overleaf_session2` value.

```bash
printf '%s' 'overleaf_session2=s:...' > ~/.config/overleaf-mcp/session.txt
chmod 600 ~/.config/overleaf-mcp/session.txt
```

The file may hold either the full `overleaf_session2=s:…` string or just the value.
Cookies expire (~30 days) — when `sync_projects` reports an expiry, refresh this file.
(Or set `OVERLEAF_SESSION`.) Without a cookie the server still works for any project
you reference by ID or set up as a workspace; you just can't auto-list.

## Register with Claude Code

Add to your `.mcp.json` (kept alongside the old single-project entry during
transition, per the architecture doc):

```json
{
  "mcpServers": {
    "overleaf-multi": {
      "command": "node",
      "args": ["/Users/longngo/IdeaProjects/overleaf-mcp/src/server.js"],
      "env": {
        "OVERLEAF_WORKSPACE_ROOT": "/Users/longngo/IdeaProjects/Overleaf"
      }
    }
  }
}
```

Then restart Claude Code. On start the server auto-syncs the project list if a
cookie is present (non-fatal if not).

## Environment variables

| Var | Default | Purpose |
|---|---|---|
| `OVERLEAF_TOKEN` | (reads `token.txt`) | Git token for content I/O |
| `OVERLEAF_SESSION` | (reads `session.txt`) | Session cookie for discovery |
| `OVERLEAF_WORKSPACE_ROOT` | `process.cwd()` | Where `setup_local` puts folders |
| `OVERLEAF_DEFAULT_PROJECT` | — | Name/ID used when `projectName` is omitted |
| `OVERLEAF_CONFIG_DIR` | `~/.config/overleaf-mcp` | State directory |
| `OVERLEAF_BASE_URL` | `https://www.overleaf.com` | Dashboard host (self-hosted CE) |
| `OVERLEAF_GIT_BASE` | `https://git.overleaf.com` | Git host (self-hosted CE) |
| `OVERLEAF_GIT_AUTHOR_NAME` / `_EMAIL` | `Overleaf MCP` / `overleaf-mcp@localhost` | Commit identity |

## Tools (17)

**Discovery** — `sync_projects`, `find_project`, `session_status`, `list_projects`

**Workspace** — `setup_local`, `pull_local`, `diff_local`, `push_local`,
`list_version_history`, `rollback_to_version`

**Content** (workspace-aware) — `list_files`, `read_file`, `get_sections`,
`get_section_content`, `status_summary`, `write_file`, `write_section`

### The core flow: review before push

1. `sync_projects` → `find_project "VCaiLuong"`
2. `setup_local "VCaiLuong"` → clones to `<workspace-root>/VCaiLuong/`
3. `write_section main.tex "Abstract" "…"` → **writes only, no push**
4. `diff_local "VCaiLuong"` (or your IDE Source Control) to review
5. `push_local "VCaiLuong" "Rewrite abstract"` → commits + pushes

Projects **without** a workspace fall back to legacy behavior: `write_file` /
`write_section` clone to a temp dir and commit + push immediately (a `commitMessage`
is required in that mode).

### Rollback

```
list_version_history "VCaiLuong" limit:10
rollback_to_version "VCaiLuong" commitSha:"def5678" paths:["main.tex"] mode:"restore"
# → uncommitted changes; review with diff_local, then push_local
```

`restore` = `git checkout <sha> -- <paths>`; `revert` = undo commits since `<sha>`.
Both leave changes **uncommitted** (nothing is force-pushed). Rollback refuses if the
workspace is dirty unless `force:true`.

## Security notes

- The git token is never placed in argv, in a workspace's `.git/config`, or in error
  output. Remotes are stored clean; credentials are supplied per-command via an inline
  credential helper reading the token from the child process env.
- Keep `token.txt` and `session.txt` at `chmod 600`.

## Layout

```
src/
├── server.js     MCP entry: stdio transport, tool schemas, dispatch, content routing
├── config.js     paths, auth, cache.json, workspaces.json, name/ID resolution
├── git.js        child_process git wrappers with token masking
├── overleaf.js   session-cookie discovery (the only network-JSON module)
└── latex.js      \section{…} parsing + section splicing
```

TDQS

A3.7/5.0

Scored across 17 tools

Disambiguation5/5

Each tool has a clearly distinct role: project sync/search/status, workspace setup and git operations, file and LaTeX section access, and version management. Even similar-sounding tools like sync_projects and list_projects are differentiated by description (refresh vs. view cached data).

Naming Consistency4/5

Most tools follow a clear verb_noun snake_case pattern (sync_projects, list_files, write_section). Two status tools (session_status, status_summary) are noun_noun and setup_local is slightly awkward, but the overall style is consistent and readable.

Tool Count4/5

At 17 tools, this is on the higher end but within reason given the server's dual focus on Overleaf project management and local git-synced workspaces. Each tool covers a distinct need, though a few could potentially be merged (e.g., status_summary and session_status) without significant loss.

Completeness4/5

The tool surface covers the essential lifecycle: project discovery, workspace setup, local editing, diff/push, version history/rollback, and LaTeX-aware reading/writing. Missing operations like project creation/deletion are likely outside the intended scope (session-based account sync), so the core workflows are well-supported.

Maintenance

ActivitySlowing
ResponsivenessNo issues