Skip to content

Configuration

Everything is configured through environment variables set where the MCP client starts the server, for example in the env block of the client's MCP configuration. Defaults suit www.overleaf.com.

Reference

Variable Default Purpose
OVERLEAF_BASE_URL https://www.overleaf.com Target Overleaf origin. Use the same value for login and serve.
OVERLEAF_COOKIE_JAR_FILE Platform configuration directory Saved-session path override
OVERLEAF_BROWSER_PATH Auto-detected Chrome-family executable used by login
OVERLEAF_BROWSER_PROFILE_DIR Platform configuration directory Dedicated login profile
OVERLEAF_LOGIN_TIMEOUT_MS 300000 Browser sign-in deadline, capped at 15 minutes
OVERLEAF_PROTOCOL_VERSIONS 2 Comma-separated accepted collaboration protocol versions
OVERLEAF_MAX_DOC_LENGTH 2097152 Fallback maximum UTF-16 document length
OVERLEAF_MAX_UPDATE_CHARS 7340032 Conservative serialized OT update limit
OVERLEAF_SOCKET_CACHE_SIZE 2 Maximum cached project sockets
OVERLEAF_SOCKET_IDLE_TTL_MS 90000 Idle project-socket lifetime
OVERLEAF_REQUEST_TIMEOUT_MS 30000 REST and collaboration-call timeout
OVERLEAF_APPLY_TIMEOUT_MS 30000 OT acknowledgement and application timeout
OVERLEAF_RECOVERY_TIMEOUT_MS 30000 Ambiguous-mutation observation window
OVERLEAF_COMPILE_TIMEOUT_MS 120000 Default compile wait, capped at 15 minutes
HTTPS_PROXY, https_proxy Unset Proxy for an https:// base URL; see behind a proxy
HTTP_PROXY, http_proxy Unset Proxy for an http:// base URL
NO_PROXY, no_proxy Unset Hosts reached directly, bypassing the proxy
OVERLEAF_ALLOWED_PROJECTS Unset, every project Comma-separated project ids the server may touch; see access policy
OVERLEAF_LOCAL_READ_ROOTS Unset, anywhere Absolute folders local reads must stay inside, separated by : (; on Windows)
OVERLEAF_LOCAL_WRITE_ROOTS Unset, anywhere but the session Absolute folders local writes must stay inside, separated the same way
OVERLEAF_ALLOWED_EFFECTS Unset, every effect Comma-separated effects operations may have

An ol-maxDocLength value advertised by the Overleaf deployment takes precedence over the fallback. Content at or above the limit returns DOC_TOO_LARGE; an oversized serialized update returns UPDATE_TOO_LARGE and must be split into smaller, independently revisioned writes.

compile_project.timeoutMs accepts 1 second through 15 minutes. It changes only how long the MCP call waits, not the account's server-side compile allowance.

download_project_zip.timeoutMs (1 second to 15 minutes, default 5 minutes) bounds a whole-project download, the whole transfer included, in place of OVERLEAF_REQUEST_TIMEOUT_MS.

Where the session is stored

The login command uses a separate browser profile and never reads your normal browser profile. Session files live under overleaf-web-mcp in the platform configuration directory:

Platform Path
Linux ${XDG_CONFIG_HOME:-~/.config}/overleaf-web-mcp
macOS ~/Library/Application Support/overleaf-web-mcp
Windows %APPDATA%\overleaf-web-mcp

Only cookies applicable to OVERLEAF_BASE_URL are saved. On POSIX systems the directory is created with mode 0700 and the cookie jar with mode 0600; a group- or world-readable jar is rejected. Filesystems without meaningful POSIX modes continue with a permissionsUnchecked warning in auth_status.

Cookie refreshes received during normal use are merged under an advisory lock and written through a protected temporary file followed by an atomic replace. If the session expires, run npx overleaf-web-mcp login again; to stop that happening, see the next section.

Keeping the session alive

Overleaf issues its session cookie with a five-day lifetime and re-issues it, with a fresh five days, on every response. The server merges each refreshed cookie into the jar, so a session used at least once every five days never expires, and one left untouched for five days is gone for good. Nothing on your machine can extend that: editing the expiry in cookies.txt only keeps sending a cookie Overleaf has already forgotten. What closes the gap is a request every few days.

npx overleaf-web-mcp keepalive

The command runs the same startup bootstrap as serve, merges the refreshed cookie into the jar, prints when the session will now expire, and exits:

{
  "refreshed": true,
  "baseUrl": "https://www.overleaf.com",
  "sessionExpiresAt": "2026-09-19T22:25:37.520Z",
  "userId": "..."
}

Against a session that has already lapsed it exits with status 1, prints the usual error JSON (AUTH_EXPIRED) to stderr and nothing to stdout, so a scheduler can alert on it. A keepalive cannot revive a dead session; a machine that stays off for more than five days still needs login. auth_status reports the same sessionExpiresAt, so an assistant can tell you how long is left.

Schedule it once a day. Any interval under five days works; daily leaves four days of slack for a laptop that was asleep. Schedulers do not source your login shell, so give them the absolute path of a Node 20 or newer binary and of the installed package rather than npx. With the right Node active, command -v node and npm root -g print the two paths used below; adjust them to yours.

macOS, launchd. Save as ~/Library/LaunchAgents/com.overleaf-web-mcp.keepalive.plist, then launchctl load ~/Library/LaunchAgents/com.overleaf-web-mcp.keepalive.plist.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>com.overleaf-web-mcp.keepalive</string>
  <key>ProgramArguments</key>
  <array>
    <string>/opt/homebrew/bin/node</string>
    <string>/opt/homebrew/lib/node_modules/overleaf-web-mcp/dist/cli.js</string>
    <string>keepalive</string>
  </array>
  <key>StartCalendarInterval</key>
  <dict><key>Hour</key><integer>9</integer><key>Minute</key><integer>0</integer></dict>
  <key>StandardErrorPath</key><string>/tmp/overleaf-web-mcp-keepalive.log</string>
</dict>
</plist>

Linux, cron. Run crontab -e and add one line:

0 9 * * * /usr/local/bin/node /usr/local/lib/node_modules/overleaf-web-mcp/dist/cli.js keepalive >/dev/null 2>>"$HOME/.overleaf-web-mcp-keepalive.log"

Windows, Task Scheduler. From a Command Prompt:

schtasks /Create /SC DAILY /ST 09:00 /TN "overleaf-web-mcp keepalive" /TR "\"C:\Program Files\nodejs\node.exe\" \"%APPDATA%\npm\node_modules\overleaf-web-mcp\dist\cli.js\" keepalive"

Running a keepalive while an MCP client has the server open is safe. Cookie refreshes are merged under the jar's advisory lock, and the jar is re-read under that lock before it is written, so neither process can overwrite the other's refresh.

Behind a proxy

When outbound traffic must go through an HTTP proxy, set the conventional proxy variables in the same env block as the others:

"env": {
  "HTTPS_PROXY": "http://proxy.example.org:3128",
  "NO_PROXY": "localhost,.internal.example.org"
}

The server makes one routing decision for OVERLEAF_BASE_URL at startup and applies it to every connection: REST requests, the Socket.IO handshake, and the collaboration WebSocket always take the same route, as the handshake's load-balancer cookie requires. It does not rely on Node's own proxy support, so it works on Node 20 and needs no NODE_USE_ENV_PROXY.

  • The variable follows the scheme of OVERLEAF_BASE_URL: HTTPS_PROXY for an https:// origin, HTTP_PROXY for an http:// one, with no fallback from one to the other. A lowercase name takes precedence over the uppercase one, and an empty value counts as unset.
  • The value is an http:// or https:// proxy URL, and a bare host:port means http://. Credentials go in the URL, percent-encoded where needed, as in http://user:p%40ss@proxy.example.org:3128. They are sent only to the proxy and never printed. SOCKS proxies are not supported.
  • NO_PROXY is a comma-separated list. An entry matches that host and its subdomains, with or without a leading . or *.; * matches every host; host:port matches only that port; an IP address matches only itself. CIDR ranges are not supported.
  • If the variable that applies is invalid, the server exits at startup with INVALID_ARGUMENT, naming the variable but not its value. A variable that does not apply, because of the scheme or NO_PROXY, is not checked.

login signs in through Chrome, which applies its own proxy settings. The check that follows sign-in uses the proxy above, as serve and keepalive do.

Access policy

Four variables limit what the server may touch. Each one is unset by default, which allows everything of its kind, and the server checks every operation against all four before it sends anything, so a refused call costs no request. A misconfigured value, such as a relative root or a root that does not exist, stops the server at startup with INVALID_ARGUMENT naming the variable.

Variable Limits Refusal
OVERLEAF_ALLOWED_PROJECTS Which projects any tool may read or change, by id. list_projects and auth_status show and count only these. A project created by this process (create_project, clone_project, import_project_zip) is allowed for the rest of the process. POLICY_DENIED
OVERLEAF_LOCAL_READ_ROOTS Which local files and folders may be read: write_file and upload_file with localPath, batch_upload, import_project_zip, plan_sync, and sync_directory. PATH_OUTSIDE_ROOT, details.kind: "outside_read_roots"
OVERLEAF_LOCAL_WRITE_ROOTS Where download_file and download_project_zip may write. PATH_OUTSIDE_ROOT, details.kind: "outside_write_roots"
OVERLEAF_ALLOWED_EFFECTS Which kinds of change any operation may make. POLICY_DENIED, details.effect

Roots are resolved with realpath when the server starts, and a path is judged by where it leads, the way the file system resolves it: a symbolic link inside a root that points outside it is refused, a link is followed before the .. after it, and a link to a file that does not exist yet is judged by where it would create one. Whatever the policy, no tool reads or writes the cookie jar, its lock and temporary files, or the browser profile login uses, and a folder that holds them cannot be synced (PATH_OUTSIDE_ROOT, details.kind: "session_files").

The effects are:

Effect What it covers
overleaf-read Reading project data
overleaf-write Changing content, comments, or the tree without removing anything
overleaf-delete Removing an entity, or permanently deleting a project
project-lifecycle Creating, cloning, importing, renaming, trashing, archiving, or configuring a project
compile Starting or stopping a compile
local-read Reading a file or folder on the server's disk
local-write Creating or replacing a file on the server's disk
unchecked-replace Replacing a text document with no revision check, by upload_file or batch_upload

Nearly every operation reads project data, writes included, so overleaf-read belongs in any useful list. An operation that reads after it changes something, such as create_project reading the new project's tree, needs every effect it will use before it starts, so a refusal never lands after the change.

For example, an assistant that may only read one project and save copies of its files into one folder:

{
  "mcpServers": {
    "overleaf": {
      "command": "npx",
      "args": ["-y", "overleaf-web-mcp", "serve"],
      "env": {
        "OVERLEAF_ALLOWED_PROJECTS": "64b7f1c2e4b0a1b2c3d4e5f6",
        "OVERLEAF_ALLOWED_EFFECTS": "overleaf-read,local-write",
        "OVERLEAF_LOCAL_WRITE_ROOTS": "/home/me/overleaf-drafts"
      }
    }
  }
}

The policy keeps an assistant inside what it was given; it is not a sandbox against a malicious process on the same machine. The safety model says exactly where it stops.

Presence

While a project socket is open, the account may appear online to collaborators in the Overleaf editor. By default at most two project sockets are cached, active sockets are never evicted, and idle sockets disconnect after 90 seconds. Lower OVERLEAF_SOCKET_IDLE_TTL_MS to shorten that window at the cost of reconnecting more often.