mcp-server-overleaf
This MCP server connects AI clients to Overleaf LaTeX projects so they can read, search, edit, compile, review, and deliberately publish changes while protecting co-authors' work.
Discover projects and files:
list_projects,list_files(grouped by kind, with extension filter and untracked files), andproject_summaryfor counts, main document, sections, and pending edits.Read content:
read_file(plain text, line ranges, revision-awarefull/smartdelta modes),list_sections,read_section(by title), andsearch_project(literal or regex across LaTeX/bib/text sources).Edit locally:
replace_text(exact, ambiguity-refusing),edit_section(rewrite a whole section),write_file(create/overwrite),delete_file, andmove_file— all staged in a local clone only.Review before publishing:
show_difffor all unpushed edits,project_statusfor sync state and history,sync_projectto pull from Overleaf, andcompile_projectvialatexmkto catch errors.Publish safely:
push_changescommits and pushes only on explicit request, re-checking Overleaf and refusing (not overwriting) when a collaborator touched the same lines;discard_local_changesabandons unpushed work.Guard against stale edits: pass a
expectedRevisionfromread_fileto any edit tool to refuse edits if the file changed since you read it.Optional tracked changes: with an Overleaf session cookie, three extra tools create tracked-change suggestions, list tracked changes and comments, and comment on selected text.
Provides access to Overleaf projects through the official Git bridge, enabling listing files, reading and searching sections, editing LaTeX documents, compiling, and safely pushing changes while detecting collaborator conflicts.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-server-overleafShow me the contents of main.tex in my paper project"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Overleaf MCP Server — Safe AI Editing for LaTeX Papers
Connect Claude Code, Claude Desktop, Codex, ChatGPT, Cursor, VS Code, or any MCP client to Overleaf. Read, search, edit, compile, and review real LaTeX projects without copy-pasting your paper into a chat window.
npx --yes mcp-server-overleaf@0.3.9 setupEdits stay in a local clone until you explicitly publish them. Before every read and every push, this Overleaf MCP server checks what your collaborators changed. If both of you touch the same lines, it stops the push and shows both versions instead of choosing a winner.
With an optional Overleaf session cookie, edits can also arrive as tracked-change suggestions for co-authors to accept or reject, and the existing review panel becomes readable. A plain Git push cannot express either.
Download the one-click Claude Desktop bundle or use the setup command above for Claude Code, Codex, Cursor, and other local AI clients.

Independent community project; not affiliated with or endorsed by Overleaf.
Why choose this Overleaf MCP server?
Several Overleaf MCP servers exist. Of the ones built on Overleaf's official Git bridge, this is the most complete, and it is the only one that stops instead of overwriting when a co-author has already changed the lines you are editing.
A conflict ends the push, not your co-author's paragraph. Every read and every push first checks what changed on Overleaf. When two edits touch the same lines,
push_changesrefuses and shows you both versions.18 tools, and nothing reaches Overleaf until you say so. Read, search, and edit by section or by exact text, add, rename and remove files, compile locally, inspect the diff, then publish deliberately.
An edit can arrive as a suggestion, not as finished text. Three optional tools talk to Overleaf's editor rather than the Git bridge, so a change lands in the review panel for a co-author to accept or reject. A Git push cannot express that. Tracked changes
No terminal, if you do not want one. Claude Desktop installs it from a downloaded bundle; Claude Code and Codex install it as a plugin.
The token is written once, to one file, at mode 600. No client configuration holds it, and the published plugin declares no environment variables at all.
Related projects compares the alternatives tool by tool, and is equally direct about the things this server cannot do.
Common workflows include revising an academic paper by section, searching a large LaTeX project, checking a bibliography, compiling before publication, reviewing the exact diff, and sending an edit to Overleaf as a tracked suggestion.
Related MCP server: Overleaf MCP Server
Where it installs
Every route below reaches the same server and the same 18 tools, and every one of them keeps edits local until an explicit push. Pick the row for your client. The three tracked-changes tools are extra, and appear only once a session cookie is configured.
Client | How to install it |
Claude Desktop | Download the bundle and double-click it. One click |
Claude Code | Add this repository as a plugin marketplace. Two commands |
Codex CLI, desktop, and IDE extension | The same, with the Codex commands. Two commands |
Cursor |
|
Visual Studio Code | A |
ChatGPT on the web and desktop | An outbound-only Secure MCP Tunnel, no public endpoint and no open port. Guide |
A catalogue that reads the MCP registry | Already listed as |
Any other MCP client |
|
A machine you are developing on | A source checkout. From source |
Claude Desktop takes a packaged bundle; Claude Code and Codex each take a plugin.
Everywhere else setup does the equivalent. All four routes end the same way: the token is
verified against Overleaf, written to one file at mode 600, and no client configuration
holds the secret.
Guides
Project configuration and efficient reads covers independent credentials, sparse checkout, revision reads, and guarded edits.
Related projects describes existing alternatives and this project's focus on collaborator safety and recovery.
Release process and verification describes the tested artifact, provenance, first publication, and subsequent trusted publishing.
Install the Claude Desktop bundle covers the one-click
.mcpbextension: what is inside it, how to build it, and how to remove it.Install the Claude Code and Codex plugins covers the two marketplace entries: what the plugin contains, how it gets a token without holding one, and how to update, remove, or build it.
Connect local MCP clients to Overleaf covers Codex desktop and CLI, Claude Code, Claude Desktop, Cursor, Visual Studio Code, local stdio, verification, and troubleshooting.
Connect ChatGPT to Overleaf with Secure MCP Tunnel covers the complete private connection from a local stdio server to ChatGPT desktop and web, including workspace association, least-privilege credentials, validation, and troubleshooting.
What you are installing
An MCP server exposing 18 tools over stdio or Streamable HTTP, plus 3 more when a session
cookie turns on tracked changes. One core, two transports;
the tool implementations are identical and only the framing differs. setup connects it
to the AI clients on this computer and is the only command most people need.
Requires Node 22.14+ and git on PATH; Node 24 LTS is recommended. compile_project additionally needs latexmk and a TeX
distribution; every other tool works without them.
The release test matrix covers macOS and Linux. Windows Git and TeX workflows are not yet validated. This server is a command-line application, not an importable JavaScript library.
Git integration has to be available for the project. Overleaf documents it as a premium feature gated on the project owner's subscription, so a free account invited to a project owned by someone with a subscription can still use it, and that subscription can be individual, group, or institutional. Do not tell a user their own plan disqualifies them. Verify it directly in step 3 instead.
Install into Claude Desktop with one click
Download mcp-server-overleaf.mcpb and double-click it. Claude Desktop opens an install panel, asks for the two values below, and starts the server itself. No terminal, no Node installation, no build.
Overleaf project address — open the project in Overleaf and copy the whole URL from the address bar.
Overleaf Git token — generate one at https://www.overleaf.com/user/settings under Git integration. Claude Desktop stores it in the operating system keychain.
The bundle carries the same server npm publishes, with its locked runtime dependencies and nothing else. It is macOS and Windows only, because that is where Claude Desktop runs. For any other client, use the command below. Details in Install the Claude Desktop bundle.
Install as a Claude Code or Codex plugin
Store the token once:
npx --yes mcp-server-overleaf@0.3.9 setup --clients noneThen, in Claude Code:
claude plugin marketplace add yangzichao/mcp-server-overleaf
claude plugin install overleaf@mcp-server-overleafOr in Codex:
codex plugin marketplace add yangzichao/mcp-server-overleaf
codex plugin add overleaf@mcp-server-overleafRestart the client, then ask it to list the files in your project.
Until this local MCP server is accepted into a public directory, both clients install it
from this repository's marketplace: Claude Code reads .claude-plugin/marketplace.json and
Codex reads .agents/plugins/marketplace.json, and both point at the same
plugins/overleaf directory. That plugin holds no token and sets no environment variable,
because the first command writes the token to ~/.config/overleaf-mcp/projects.json and the
server finds it there. Public directory review is separate from this repository-based
installation. Details in
Install the Claude Code and Codex plugins.
Install with one command
npx --yes mcp-server-overleaf@0.3.9 setupIt checks Node and git, asks for the project and a token, proves the token reaches Overleaf before writing anything, and registers the server with the clients it finds on this computer: Claude Code, Codex, Claude Desktop and Cursor. A failed run leaves no half-configuration behind, because nothing is written until Overleaf accepts the token.
Two things are needed, both from the browser:
The project address. Open the project in Overleaf and copy the whole URL from the address bar. A read-only share link is a different thing, and setup says so rather than failing later.
A git authentication token, generated at https://www.overleaf.com/user/settings under Git integration. It is not echoed as you type.
The token is written to ~/.config/overleaf-mcp/projects.json at mode 600 and nowhere
else. The server finds that file on its own, so no client configuration holds the secret,
a path to it, or any environment variable. Clients are registered with an absolute Node
path and an absolute entry point rather than npx, because a desktop application starts
with a much smaller PATH than a terminal.
Restart Claude Desktop, Cursor, or Codex afterwards; Claude Code picks it up on the next run. Then ask the assistant to list the files in the project.
Setup can also run unattended:
printf '%s' "$OVERLEAF_TOKEN" | npx --yes mcp-server-overleaf@0.3.9 setup \
--project paper=https://www.overleaf.com/project/64a1b2c3d4e5f6a7b8c9d0e1 \
--token-stdin --yes--clients claude-code,codex limits which clients are touched, and --clients none
writes the configuration without registering anything. Run it again to add another
project or to replace an expired token; the previous file is kept alongside it.
Find it in the MCP registry
The server is listed in the official Model Context Protocol registry as
io.github.yangzichao/mcp-server-overleaf. The listing names the npm package and the Claude
Desktop bundle, and clients and catalogues that read the registry pick it up from there. The
release workflow publishes the listing itself, so it can never point at a version npm does
not have.
Claude Code and Codex do not read that registry. They have their own plugin marketplaces, which is the section above, or the server can be added by hand:
claude mcp add --transport stdio --scope user overleaf -- npx --yes mcp-server-overleaf@0.3.9 --stdio
codex mcp add overleaf -- npx --yes mcp-server-overleaf@0.3.9 --stdioBoth forms need OVERLEAF_GIT_TOKEN and OVERLEAF_PROJECT_ID in the environment, which is
why setup writes a projects.json instead and registers an absolute path.
Install from npm by hand
Use this when you want to see every step, or to configure a client setup does not cover.
The commands below select version 0.3.9 explicitly so a client restart does not silently
upgrade the server. If that version has not been published yet, use the source installation
below. npm installs compiled JavaScript and locked runtime dependencies; no local build is needed.
npx --yes mcp-server-overleaf@0.3.9 --versionKeep configuration outside the npm installation and npx cache. Create a private file:
mkdir -p "$HOME/.config/overleaf-mcp"
touch "$HOME/.config/overleaf-mcp/env"
chmod 600 "$HOME/.config/overleaf-mcp/env"Edit that file locally to contain your token and project ID:
OVERLEAF_GIT_TOKEN=olp_your_token_here
OVERLEAF_PROJECTS=paper=64a1b2c3d4e5f6a7b8c9d0e1For clients using the mcpServers JSON format:
{
"mcpServers": {
"overleaf": {
"command": "npx",
"args": ["--yes", "mcp-server-overleaf@0.3.9", "--stdio"],
"env": {
"OVERLEAF_MCP_ENV_FILE": "/absolute/path/to/.config/overleaf-mcp/env"
}
}
}
}Replace the file path with its actual absolute path; JSON does not expand ~ or $HOME.
Clients with another configuration format should launch the same command and arguments with
the same environment variable. If a desktop app cannot find npx, use its absolute path
from command -v npx. See the client guide for source
installation examples and client-specific configuration locations.
Alternatively, set both OVERLEAF_GIT_TOKEN and OVERLEAF_PROJECTS in the client's env.
With OVERLEAF_MCP_ENV_FILE, environment variables override individual file values; an
unreadable or relative explicit file path is an error. Without it, the install's .env is
used only when the client supplies no project or credential settings (including file paths).
A JSON projects file can provide independent credentials; see the configuration guide.
The current working directory is never searched for configuration.
After restarting the client, call list_projects to check configuration and list_files
to verify access to the real project. Tool discovery alone does not prove Overleaf access.
Install from a source checkout
Step 1: build
npm ci && npm run buildConfirm dist/index.js exists before continuing. Record the absolute path of the
repository root; every client configuration below needs it, and relative paths will not
work because clients spawn the server from an arbitrary working directory.
Step 2: collect two values from the user
The git authentication token. Generated at https://www.overleaf.com/user/settings,
under Git integration. One token covers all their projects and expires after a year. It
starts with olp_.
Ask the user to paste it into .env themselves rather than into the chat, using the
command in step 3. A token pasted into a conversation is in the transcript permanently and
has to be rotated. If they paste it anyway, tell them plainly to rotate it, and continue.
One or more project ids. The last path segment of a project URL:
https://www.overleaf.com/project/<projectId>. A project id is exactly 24 hexadecimal
characters. Anything else is not a project id, and you should ask again rather than guess.
Step 3: write .env and verify the token works
cp .env.example .env && chmod 600 .envThen have the user fill in:
OVERLEAF_GIT_TOKEN=olp_...
OVERLEAF_PROJECTS=paper=64a1b2c3d4e5f6a7b8c9d0e1OVERLEAF_PROJECTS is a comma-separated list of name=projectId pairs. The names are
arbitrary labels the user picks. A bare project id with no name is also accepted and
registers under its own id. With exactly one project registered it becomes the default; with
several, set OVERLEAF_DEFAULT_PROJECT, use an alias named default, or name the project in each call.
Verify the credentials reach Overleaf before configuring any client:
git ls-remote https://git@git.overleaf.com/<projectId>Git will prompt for a password. That is the token. Refs printed means it works. 403 or
Repository not found means either the token is wrong or that account's plan does not
include Git integration; resolve this before continuing, because every tool depends on it.
The server reads .env itself, because MCP clients spawn it without a shell. This keeps the
token in one file whose permissions the user controls, instead of copied into every client's
config. Anything the client sets in the environment explicitly still wins.
Step 4: register with the client
Use the absolute path from step 1. Configure only the client the user actually asked for. For client-specific configuration locations, verification, and troubleshooting, see the local MCP client guide.
Claude Code
claude mcp add overleaf -s user -- node /absolute/path/to/mcp-server-overleaf/dist/index.js --stdioThen run claude mcp list and confirm it reports ✔ Connected. Do not report success
until you have seen that.
Claude Desktop or Cursor — add to the client's MCP config file. The file location and restart steps differ by client; the local MCP client guide lists both.
{
"mcpServers": {
"mcp-server-overleaf": {
"command": "node",
"args": ["/absolute/path/to/mcp-server-overleaf/dist/index.js", "--stdio"]
}
}
}Codex desktop, CLI, or IDE extension — the clients on one Codex host share
~/.codex/config.toml:
[mcp_servers.mcp-server-overleaf]
command = "node"
args = ["/absolute/path/to/mcp-server-overleaf/dist/index.js", "--stdio"]Add default_tools_approval_mode = "writes" inside the server table if the user wants
reads to run freely while every write asks first.
ChatGPT desktop local MCP settings can start the same stdio command directly on the computer that holds this repository. This local configuration is shared with Codex clients on the same host; the local MCP client guide includes the UI and CLI paths.
ChatGPT web or a workspace-shared ChatGPT app — use OpenAI Secure MCP Tunnel without
exposing the server to the public internet. ChatGPT connects to an OpenAI-hosted tunnel
endpoint while tunnel-client forwards requests to dist/index.js --stdio. Follow the
step-by-step Secure MCP Tunnel guide; it
includes the required Platform organization and ChatGPT workspace association, runtime key,
developer-mode app setup, and end-to-end verification.
Remote clients over HTTP
node dist/index.js --http --port 3017--http refuses to start without OVERLEAF_MCP_HTTP_AUTH_TOKEN, since anyone who reaches
the port could otherwise read and rewrite the user's papers. --allow-anonymous overrides
this and should only be used when the port is genuinely unreachable from outside the
machine. Do not pass it to work around a missing token.
Step 5: verify end to end
Call list_files. A file listing means the whole path works: configuration, token, clone,
and the client connection. If it fails, the error text says which.
The tools
Every tool takes an optional project: a project's Overleaf address, its raw 24-character
id, or a name from OVERLEAF_PROJECTS. Omit it to use the default. The address is accepted
because it is the form you already have, so a paper that was never configured can be reached
by pasting it. An unregistered project requires a default Git token; registered ones use
their configured project credentials.
Tool | What it does |
| The projects this server can reach |
| Files grouped by kind; extension filter and optional new local files |
| Text or line ranges; optional revision-aware full/unchanged/delta reads |
| Sectioning commands in a |
| The body of one section, found by title |
| Search tracked text files |
| Replace an exact snippet, refusing ambiguous matches |
| Replace one section wholesale |
| Overwrite or create a file |
| Remove a file, local until pushed |
| Move or rename a file, refusing to overwrite the destination |
| The diff of everything not yet pushed |
| Throw away unpushed edits and commits, back to Overleaf's version |
| Sync state, pending edits, recent history |
| JSON file counts, main document, sections and pending changes |
| Pull from Overleaf |
| Compile with latexmk and report errors |
| Commit and publish, with the collaborator check |
How to use the tools safely
Edits are local until push_changes. This is the whole design, not an implementation
detail, and it is what lets a bad edit be thrown away instead of published.
Read show_diff before calling push_changes. Push once, with a real commit message; the
user sees it in Overleaf's history next to their co-authors' entries.
push_changes can return conflict-with-collaborator. This means someone edited the same
lines while you were working. Nothing was published and both versions are intact. Do not
retry, do not force, and do not attempt to merge the two yourself. Report the conflict and
let the user decide.
A refused push leaves its commit in the clone, so the clone is then both ahead of and
behind Overleaf and every later sync conflicts on the same lines. discard_local_changes
is the way out: it drops unpushed commits as well as uncommitted edits and returns the
clone to what Overleaf holds. Tell the user what is being thrown away before calling it,
because their edit is what goes.
replace_text refuses a snippet that appears more than once rather than silently changing
the first. Add surrounding context to make it unique, or pass replaceAll deliberately.
Prefer replace_text and edit_section over write_file. write_file replaces an entire
file, so a partial reconstruction of a document silently deletes the rest of it.
delete_file and move_file are local until push_changes like every other edit, so a
removal can be undone with discard_local_changes right up to the push. Neither rewrites
LaTeX references: after a move, search_project for the old path and fix any \input,
\include or \includegraphics that still names it, or the paper stops compiling. Before
deleting, check the file is genuinely unused — a co-author's \input is enough to break
their build.
For a read–edit cycle, request read_file with mode: "full" or "smart" and pass its
revision as expectedRevision to any edit tool. The edit then refuses to overwrite a
file changed by a collaborator or another client since that read. See the
revision protocol.
Compilation is optional and is not a gate. push_changes never checks that the document
builds, so a broken document can be published if you do not check first.
Configuration reference
Variable | Meaning |
| Default credential; required unless supplied by a token file or per project. |
| Absolute path to a default token file. |
| Absolute path to a JSON projects file with independent credentials. |
| Single-project alternative to |
| Absolute path to an external config file; recommended for npm/npx. |
|
|
| Which registered name to use when a call omits |
|
|
| Where clones live. Default |
| Default |
| Compile timeout. Must be a positive integer. |
| Bearer token required by |
| Port for |
| Overleaf session cookie. Turns on the three tracked-changes tools. |
| Absolute path to a file holding the same value. Preferred over the variable. |
| Overleaf's web address for those tools. Default |
Why it behaves the way it does
Overleaf's git bridge is not a general git remote. Each project has exactly one branch with one linear history, force pushes are refused, and there are no tags, submodules or LFS. Everything here stays inside that envelope.
The real risk is not a failed push, it is silently overwriting a co-author, so writing and publishing are separate:
Every read and every edit synchronizes with Overleaf first. If local work prevents synchronization, the call fails and preserves that work. Review it with
show_diff, then publish it or explicitly discard it before continuing; stale reads and edits are refused.Edits land in the local clone only. Nothing reaches Overleaf until
push_changes.push_changesre-checks Overleaf immediately before pushing and rebases onto anything that landed in the meantime. If that cannot be applied cleanly the push is refused and the conflict reported, rather than resolved by guessing.
Git credentials are handed to git through a credential helper, so authentication tokens
are absent from argv and .git/config. Git diagnostics redact the selected credential;
tool errors redact every configured project credential. Keep secrets out of project files,
which are intentionally readable by the connected client.
Compilation writes outside the clone, so .aux, .log and .pdf files are never staged
and pushed back. Clones also carry a local exclude list, so a .DS_Store never reaches a
co-author's project.
Tool calls are serialized per project, first by an in-process queue and then by a lock directory under the workspace, so a second server process, such as the same server registered in two clients, waits instead of racing.
Client-supplied paths are checked twice: once as a path, and once against the filesystem
after symbolic links are resolved, so a link inside a clone cannot reach outside it or into
.git.
Layout
src/
config/ environment parsing, secret redaction
overleaf/ git command runner, repository operations, project registry, path safety
latex/ section parsing, file categorization
workflow/ sync-before-edit, publish-with-conflict-check, compile
tools/ MCP tool definitions
transport/ stdio and Streamable HTTP
server/ server factory shared by both transports
tests/
config/ latex/ overleaf/ unit tests, run in-process
features/ Gherkin specifications, bound to the server over stdio
integration/ spawn the built server and speak MCP to it over stdio or HTTPDevelopment
npm run checkRuns the type checker, Biome, the build, and the tests in one pass.
The type checker includes test code. Every Vitest invocation builds the server first,
including focused runs and coverage, so the subprocess tests cannot use an old dist.
Command | What it does |
| Type-check source, tests and Vitest configuration |
| Biome lint and format check |
| Biome, applying fixes |
| Build, then Vitest, whole suite |
| Build twice, compare tarballs, install as a user would, and test the installed server |
| Source checks, package checks, and dependency audit |
| Build, then Vitest with v8 coverage |
The suites cover the same tool contract over stdio and HTTP, including schemas, error
flags, reading, editing, reviewing and publishing. Recovery tests exercise dirty-tree
sync, conflict recovery, remote rejection and reconnection, process restarts, a killed
lock holder, and simultaneous clients. New files and unpushed commits must remain
visible in show_diff. Deterministic subprocess fixtures test Git and compiler timeouts
without needing a network connection or TeX installation.
tests/features/ states the publishing contract as a Gherkin feature file: plain sentences
about what a co-author sees, each one bound to a real call against the server over stdio.
A sentence with no binding fails the run, so the document cannot drift away from the
behaviour it describes. Add a scenario by writing it in the .feature file and binding its
new steps in the .test.ts beside it; steps are shared across the scenarios of a feature,
so most new scenarios need no new bindings at all.
TeX-dependent tests share one availability check. Set OVERLEAF_TEST_TEX=skip to run
without TeX, or OVERLEAF_TEST_TEX=required to fail if latexmk or pdflatex is missing.
The default, auto, runs those tests when both executables are available. GitHub Actions
runs core checks on Linux and macOS with Node 22.14, 24, and 26, plus a Linux job that installs
TeX and requires the compilation tests to run.
npm-shrinkwrap.json is the canonical dependency lock. Update it with npm and commit it with
package.json. The copy inside the published package is the runtime half of that file:
prepack removes the development entries and postpack restores the full lock, because npm
builds a dependency's tree from the shipped lock and would otherwise install the compiler,
the linter and the test runner on every user's machine. The package check fails if the
shrinkwrap inside the tarball still describes development dependencies.
Release package tests reuse the integration suites against an installed tarball from an
unrelated working directory, covering stdio, HTTP, edits, conflicts, and recovery.
That install resolves the declared ranges freshly against the registry rather than reading
the archive's own shrinkwrap, so the tree it tests is the newest one those ranges allow, and
it is compared against the lock by shape rather than by version. A package in one tree and
not the other fails the check, and so does a major version apart (a minor, for a 0.x
package) — an unpinned peer dependency can put one there without any direct dependency
changing. A newer patch or minor is only printed, and npm update brings the lock level:
both trees are tested, and requiring the versions to match turned every upstream patch
release red on branches that had not touched a dependency.
Tests never touch the real Overleaf. tests/integration/fakeOverleafRemote.ts stands up a
bare git repository plus a second clone acting as a co-author, which reproduces everything
the safety contract depends on: fetch, rebase, and a rejected push.
Coverage under-reports. The integration tests spawn node dist/index.js as a separate
process, and v8 cannot instrument a child, so src/tools/ and src/server/ report 0% while
being driven end to end over the real MCP wire protocol.
Frequently asked questions
Can Claude Code or Claude Desktop edit an Overleaf project?
Yes. Claude Desktop can install the one-click .mcpb bundle, while Claude Code can install
the repository as a plugin or run the npm package over stdio. Both expose the same safe
read, edit, compile, diff, and push workflow.
Can Codex, ChatGPT, Cursor, or VS Code connect to Overleaf?
Yes. Codex can install the included plugin, Cursor and other local clients can run the npm
package, VS Code can use .vscode/mcp.json, and ChatGPT can connect through an outbound-only
Secure MCP Tunnel. Start with the client table for the shortest route.
Will an AI edit overwrite my co-author's work?
Not silently. The server synchronizes before reads and writes, keeps edits local until an
explicit push_changes, and checks Overleaf again immediately before publishing. If a
co-author changed the same lines, the push is refused and both versions are preserved.
Does this work with a free Overleaf account?
The 16 Git-backed tools require Git integration on the project. Overleaf gates that feature on the project owner's qualifying subscription, so an invited free account can use it when the project owner has access through an individual, group, or institutional plan.
Can it compile LaTeX and show tracked changes?
Yes. compile_project runs locally when latexmk and a TeX distribution are installed.
With an optional Overleaf session cookie, three additional review tools can create tracked
suggestions, list tracked changes and comments, and comment on selected text.
Privacy Policy
The server runs entirely on your computer. It has no analytics, no telemetry, and no
service behind it. Its only outbound traffic is Git over HTTPS to Overleaf. Your token is
stored either in the operating system keychain, when Claude Desktop installs the bundle, or
in a mode 600 file written by setup, and it is redacted from error output.
Whatever a tool returns becomes part of the conversation with the MCP client you connected, and is handled under that client's own policy.
Full text: docs/privacy-policy.md.
License
MIT
Available Tools
18 toolscompile_projectCompile the projectARead-only
Compile one project locally with latexmk -pdf and report the errors and warnings, so a broken paper is caught before collaborators see it. Call it after editing and before push_changes. It compiles the clone as it stands, local edits included, without pulling, and halts at the first error. Without mainTexFile it tries main.tex, paper.tex, manuscript.tex, root.tex, thesis.tex and article.tex at the root, then the shallowest .tex file, and stops with a message if that file has no \begin{document}. Build artifacts go to a directory outside the clone, so they are never pushed, and only the log comes back, never a PDF. Without latexmk and a TeX distribution installed locally it says so instead of compiling; a run past the configured timeout, 180 seconds by default, is reported as an error. It also restores any files sparse checkout was holding back, since figures must be on disk to compile.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. | |
| mainTexFile | No | Path to the root .tex file, the one containing \begin{document}. Omitted, the server guesses it from the project layout and says so if the guess has no document environment. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnlyHint/openWorldHint annotations: halts at first error, build artifacts written outside the clone so they are never pushed, only the log is returned (never a PDF), missing latexmk/TeX is reported rather than silently failing, 180s default timeout reported as error, and sparse-checkout files are restored so figures exist on disk. This is unusually rich behavioral disclosure for a compile tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads purpose and sequencing before diving into fallbacks and environment caveats, and nearly every clause carries distinct information. It is a dense single paragraph that could be broken into structure, but little is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by specifying what comes back (the log only, no PDF) and what a timeout or missing TeX distribution yields. With only two optional params, nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds real meaning the schema lacks: the ordered fallback list (main.tex, paper.tex, manuscript.tex, root.tex, thesis.tex, article.tex, then the shallowest .tex) and the failure condition when the guess has no \begin{document}.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource ('Compile one project locally with latexmk -pdf') plus the outcome ('report the errors and warnings'), and names the sibling it precedes (push_changes). An agent can distinguish it from sync_project, project_status, or edit tools without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit sequencing: 'Call it after editing and before push_changes,' and the scope exclusion 'It compiles the clone as it stands... without pulling' implicitly directs pull/sync work to sync_project. Both when-to-use and what it does not do are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_fileDelete a project fileADestructive
Delete a file from the project. The file is removed from the local clone only: it stays in Overleaf, and co-authors keep seeing it, until push_changes publishes the removal. Until then discard_local_changes brings it back, and show_diff shows the pending deletion. Deleting a file a co-author still cites or includes will break their compile, so confirm it is unused first with search_project on its path or label. To replace a file's contents instead, use write_file. path is relative to the project root, as list_files prints it; a directory is refused, and a file sparse checkout keeps off disk is still deleted from the project. Pulls from Overleaf first. Returns a confirmation, or says the path is not in the project and deletes nothing.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path of the file to delete, relative to the project root, e.g. sections/old-draft.tex. Directories cannot be deleted, only files. | |
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds rich context beyond the annotations: removal is local-only until push_changes, is reversible via discard_local_changes, runs a pull first, refuses directories, still deletes sparse-checkout files, and returns a not-in-project message deleting nothing. Annotations cover destructive/openWorld; the description carries the real behavioral burden and does it well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and its local-only scope, then layered with undo, sibling routing, safety warning, and return behavior. Slightly dense and long, but each sentence carries distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive mutation with no output schema, it covers scope of effect, reversibility, publishing dependency, preconditions, edge cases (directories, sparse checkout, missing path), and return behavior. Nothing an agent needs to call safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and already documents path (relative to project root, directories refused) and the project selector. The description reinforces 'relative to the project root, as list_files prints it' but adds no syntax or format detail beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (delete a file from the project) and immediately scopes the semantics: local clone only, latent until push_changes. The 'To replace a file's contents instead, use write_file' clause distinguishes it from the nearest sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear precondition (confirm the file is unused via search_project on path or label) and names alternatives (write_file to replace, discard_local_changes to undo, show_diff to inspect). No explicit when-NOT-to-use framing, but the routing to siblings is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
discard_local_changesDiscard local editsADestructiveIdempotent
Permanently throw away every local edit, new file and unpushed commit in one project's clone, fetching Overleaf first so the clone ends up matching its current version. The discarded work cannot be recovered from this server. Call show_diff first, and only call this once the user has said the work should be abandoned. Its main use is after push_changes refuses a conflicting change: the clone cannot be pushed again until the conflicting local commits are either published or discarded here. Only the chosen project is reset; pending work in other projects is untouched. Returns how many edited files and unpushed commits were discarded, or that there was nothing to discard.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and idempotentHint=true, but the description adds non-obvious behavior: it fetches Overleaf first, the discarded work 'cannot be recovered from this server', the reset is scoped to one project, and it returns discard counts. That is meaningful context beyond the annotation flags.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the destructive action and its scope, then prerequisites and the push_changes use case; each sentence carries distinct, load-bearing information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the key gaps for a destructive no-output-schema tool: irreversibility, scope, prerequisite, and a summary of the return value. Slightly less complete on failure modes (e.g., what happens if the fetch or reset fails mid-way), but otherwise sufficient to call correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single 'project' parameter is fully documented in the schema (address, id, or name, with a default). The description only adds scoping semantics ('Only the chosen project is reset'), so the baseline 3 for schema-complete params applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific destructive verb and resource ('permanently throw away every local edit, new file and unpushed commit in one project's clone') and clarifies the resulting state ('clone ends up matching its current version'). An agent can distinguish it from siblings like delete_file or push_changes without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit preconditions ('Call show_diff first', 'only call this once the user has said the work should be abandoned') and an explicit use case ('after push_changes refuses a conflicting change'), naming the siblings involved. This is exactly the when/when-not guidance the dimension asks for.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edit_sectionRewrite one LaTeX sectionADestructive
Replace one whole section of a .tex file, located by its title. Use replace_text for a smaller change and this to rewrite a section wholesale. The section runs from its heading to the next heading of the same or a shallower level, never swallowing trailing matter such as \end{document} or the bibliography. newContent replaces that range line for line, so it must start with the \section{...} command itself or the heading is lost, and should end with a newline to keep the blank line before the next heading. sectionTitle is compared case-insensitively with the title in braces: an exact match wins, otherwise the first heading in document order that contains it. Pulls from Overleaf first, then edits only the local clone; push_changes publishes it. Returns the heading replaced and its former line range; if no title matches, nothing changes and the reply lists the titles.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the .tex file relative to the project root. | |
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. | |
| newContent | Yes | The section's full replacement text, starting with its own sectioning command, e.g. \section{Introduction} followed by the new body. | |
| sectionTitle | Yes | Title of the section to replace, as it appears in the sectioning command. Matched case-insensitively, with a substring fallback. Call list_sections if unsure. | |
| expectedRevision | No | Optional guard: the 64-character revision hash returned by read_file with mode=full or mode=smart for this same file. When given, the edit is refused if the file changed since that read — for example because pulling from Overleaf brought in a collaborator's version. Pass it whenever the edit depends on content you read earlier. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only flag it as destructive/non-idempotent/open-world; the description adds substantial behavior beyond that: exact section-boundary semantics (heading to next same-or-shallower heading, never swallowing \end{document} or the bibliography), the requirement that newContent start with the sectioning command, Overleaf-pull-then-local-edit ordering, and the no-match fallback of listing titles. This is exactly the behavioral context annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and dense with no filler, but the single paragraph is long and packs boundary rules, parameter contracts, and return behavior into one run-on block. Slightly more structure would improve scanability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly explains the return (heading replaced and former line range) and the no-match behavior, and it discloses the Overleaf-pull/local-edit/push workflow. Nothing needed to invoke this destructive edit safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds genuine semantics beyond the schema: exact-match-wins-then-first-containing-heading-in-document-order for sectionTitle, and the line-for-line replacement contract plus newline requirement for newContent. Only slight repetition of what the schema already states keeps it from a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (replace/rewrite) and resource (one whole section of a .tex file, located by title), and explicitly distinguishes itself from the sibling replace_text for smaller changes. An agent can tell exactly what this does versus the other edit tools without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternative ('Use replace_text for a smaller change and this to rewrite a section wholesale') and the condition that selects each. It also routes the follow-up publishing step to push_changes, so the whole workflow is covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_filesList project filesARead-only
List every file in the project, grouped by kind (LaTeX sources, bibliographies, figures, other), after pulling the latest commits from Overleaf. Use it to find exact paths before reading or editing; use project_summary when counts are enough, and search_project to find which file mentions something. Files sparse checkout keeps off disk are listed too, since they are still part of the project. extension keeps only paths ending in that suffix, case-insensitively, and filters untracked files as well; includeUntracked adds files created locally that push_changes has not committed yet, marked (untracked). Returns the file count and the likely main document, then the paths under each kind. If the pull conflicts with unpushed local work, it fails, keeps that work, and says how to resolve it.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. | |
| extension | No | Case-insensitive extension, e.g. tex or .bib; omitted lists all kinds. | |
| includeUntracked | No | Also list files created locally and not yet pushed to Overleaf, excluding ignored build artifacts (default false). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description adds the crucial implicit network behavior (pulls latest Overleaf commits first), the sparse-checkout caveat that off-disk files are still listed, the untracked-file marking convention, and the failure mode when the pull conflicts with unpushed work (fails, preserves work, explains resolution) — directly consistent with readOnly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose before the routing advice, and nearly every sentence carries information (grouping, alternatives, params, return shape, failure mode). It is dense and the extension/untracked clause reads run-on, costing a point, but nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description still describes the return shape (file count, likely main document, then paths per kind), the disk/network side effects, and the conflict failure path. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real semantics beyond the schema: extension matching is case-insensitive on path suffixes and also applies to untracked entries, and includeUntracked files are flagged '(untracked)'. The phrase 'filters untracked files as well' is slightly ambiguous about how extension interacts with untracked entries.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List every file in the project'), plus the grouping scheme (LaTeX sources, bibliographies, figures, other) and the precondition that it pulls latest commits first. An agent can distinguish it from list_sections, project_summary, and search_project without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes: use this to find exact paths before reading/editing, use project_summary when counts suffice, use search_project to find which file mentions something. This is textbook when-to-use and when-to-use-a-sibling guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_projectsList Overleaf projectsARead-only
List the Overleaf projects this server is configured to reach, marking which one is the default. Reads local configuration only, so it answers without contacting Overleaf and proves nothing about access. Call this when a request is ambiguous about which paper it means, or when another tool reports an unknown project. Returns one line per registered name, marked (default) where it applies and followed by its display name when one is configured. Any project not listed can still be reached by passing its Overleaf address as project.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint=true / openWorldHint=false annotations, it discloses a non-obvious behavioral trait: it reads local configuration only, 'answers without contacting Overleaf and proves nothing about access.' That caveat prevents the agent from misreading a successful listing as evidence of connectivity or permissions, and the return format is described too.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then usage triggers, then the local-only caveat and return format. Four sentences, each carrying distinct information with no restatement of the name or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by explaining the return format ('one line per registered name, marked (default)'). Combined with the annotations covering the safety profile, an agent has everything needed to call and interpret this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4. The description does add cross-tool context by noting the `project` argument on other tools accepts an Overleaf address for unlisted projects, but that is not a parameter of this tool itself.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource: 'List the Overleaf projects this server is configured to reach, marking which one is the default.' It is clearly distinct from sibling tools like project_summary and project_status, which operate on a single project rather than enumerating registered ones.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit triggers are given: 'when a request is ambiguous about which paper it means, or when another tool reports an unknown project.' It also covers the negative case — a project absent from the list is still reachable by passing its Overleaf address as `project` — so the agent knows the list is not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_sectionsList LaTeX sectionsARead-only
List the sectioning commands in one .tex file, \part down to \subparagraph including starred forms, with their nesting depth and line ranges. Call it before read_section or edit_section to get the exact titles they match, and to address part of a paper by title instead of line numbers that shift with every edit. path names a single file: \input and \include are not followed, so list each included file separately, and commented-out headings are skipped. Pulls from Overleaf first. Returns one line per heading, indented by depth, as \section{Title} [lines start-end], or says the file has none; a missing, binary or out-of-project path fails.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the .tex file relative to the project root, e.g. main.tex. | |
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint=true and openWorldHint=true already covering safety, the description adds substantial behavior: it does not follow includes, skips commented-out headings, pulls from Overleaf first, and enumerates failure modes (missing, binary, out-of-project path). This goes well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose, then usage, then file-scoping constraints, then return format. Every sentence carries distinct information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description fully specifies the return shape (one indented line per heading as \section{Title} [lines start-end] or a 'none' message) plus failure behavior. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented, setting a baseline of 3. The description still adds meaning by clarifying that path addresses exactly one file and that includes are not traversed, which shapes how the agent uses the parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (sectioning commands in one .tex file) and pins the exact scope (\part down to \subparagraph, including starred forms). It is immediately distinguishable from siblings like read_file and project_summary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to call it before read_section or edit_section and explains why (to get the exact titles they match and to address by title rather than shifting line numbers). It also states the constraint that path names a single file and \input/\include are not followed, so the agent knows when to call it again per file.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
move_fileMove or rename a project fileADestructive
Move or rename a file inside one project, creating any missing parent directories. The move happens in the local clone only; nothing changes in Overleaf until push_changes. LaTeX references are not rewritten: an \input, \include or \includegraphics naming the old path will break, so search_project for it afterwards and fix the references with replace_text before pushing. Both paths are relative to the same project's root; to move a text file between projects, read_file it from one and write_file it into the other. Pulls from Overleaf first. If fromPath is not a file in the project or a file already exists at toPath, nothing moves and the reply says why.
| Name | Required | Description | Default |
|---|---|---|---|
| toPath | Yes | New path for the file, relative to the project root, e.g. sections/intro.tex. Must stay inside the project and must not already exist. | |
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. | |
| fromPath | Yes | Current path of the file, relative to the project root, e.g. intro.tex. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations flag destructive=true and non-idempotent, and the description adds substantially beyond them: the move only touches the local clone, Overleaf is untouched until push_changes, a pull happens first, references are not rewritten, and the failure path is described (nothing moves, reply explains why).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and the local-vs-remote distinction are front-loaded, and the subsequent sentences each carry distinct operational information (reference breakage, cross-project workaround, pull behavior, failure semantics). It is dense and runs long, but no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description covers the return/behavior semantics an agent needs: the pull-first behavior, the local-only mutation, and what the reply reports on failure. Nothing required to invoke this mutation correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: both paths are relative to the same project's root and must stay inside the project, and fromPath must be an existing file. It does not restate the format examples already in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb pair (move or rename) on a precisely scoped resource (a file inside one project), and clarifies it also creates missing parent directories. An agent can distinguish it from write_file, delete_file and cross-project transfers without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to alternatives and preconditions: cross-project moves should use read_file plus write_file, and stale LaTeX references must be found with search_project and repaired with replace_text before pushing. It also names the step that follows (push_changes).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
project_statusProject statusARead-only
Report where one project's local clone stands against Overleaf: branch and head commit, commits just pulled, commits still unmerged, local commits waiting to be pushed, files edited but not committed, and the last ten commits. Call it to learn whether there is anything to push or anything new from a collaborator; use show_diff to read the pending edits themselves. It pulls as part of answering, and that pull only updates the local clone: nothing changes on Overleaf and no local edit is dropped. A conflicting pull does not fail the call; the reply adds a WARNING with the conflict and the clone is left as it was. For a project not opened before, the clone is made first, so that first report shows nothing pulled. Returns plain name: value lines.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses behavior well beyond the readOnlyHint/openWorldHint annotations: the call performs a pull, that pull only updates the local clone, nothing changes on Overleaf, no local edit is dropped, a conflicting pull does not fail but adds a WARNING and leaves the clone unchanged, and first-time projects get an initial clone so the first report shows nothing pulled. These are exactly the non-obvious side effects an agent must know before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose and the report contents, then layers usage, side effects, conflict handling, and return format with no filler sentences. Each clause carries distinct information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description still describes the return shape ('plain name: value lines'), and it covers the pull side effect, conflict outcome, and cold-start clone case. An agent has everything needed to call it correctly and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single 'project' parameter already documents the accepted forms (Overleaf address, 24-character id, registered name, omit for default). The description adds no parameter-level detail, so the baseline 3 applies; the first-time-clone note is behavioral, not parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Report where one project's local clone stands against Overleaf') and enumerates the exact contents of the report: branch and head commit, pulled commits, unmerged commits, unpushed local commits, uncommitted edits, and the last ten commits. It is clearly distinguishable from siblings and even names show_diff as the tool for reading pending edits themselves.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ('Call it to learn whether there is anything to push or anything new from a collaborator') and routes the adjacent need to a named alternative ('use show_diff to read the pending edits themselves'). The only thing not spelled out is an outright when-not case, but the alternative tool covers the main ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
project_summaryProject summaryARead-only
Summarize one project in a single structured result (file counts by kind, the likely main document and its section count, pending local work) to orient at the start of a task. Use list_files for every path, list_sections for a document's outline, and project_status for commit-level sync state. mainFile is a guess: main.tex, paper.tex, manuscript.tex, root.tex, thesis.tex or article.tex at the root, otherwise the shallowest .tex file, so check it for \begin{document} before relying on it. Pulls from Overleaf first; if that pull conflicts with unpushed local work, it fails and keeps the work. project can name any project the default token reaches, registered or not; the first call on a project clones it, so it is slower than later calls.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. |
Output Schema
| Name | Required | Description |
|---|---|---|
| files | Yes | The first ten file paths, sorted. Call list_files for all of them. |
| mainFile | Yes | Best guess at the root document, from conventional names and content; null when the project has no .tex file. Verify before relying on it. |
| categories | Yes | File counts by kind, keyed by category. A category with no files is absent rather than zero. |
| totalFiles | Yes | Files in the project: tracked files plus local files not yet pushed. |
| localChanges | Yes | git diff --stat for edits not yet pushed to Overleaf; empty string when there are none. |
| trackedFiles | Yes | Files Overleaf already has. |
| totalSections | Yes | Sectioning commands in mainFile only, not across every .tex file. 0 when mainFile is null. |
| untrackedFiles | Yes | Files created locally that Overleaf does not have yet, excluding ignored build artifacts. |
| sectionCountScope | Yes | States what totalSections counted, so the number is not read as a project-wide total. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnly/openWorld safety; the description adds substantial behavioral context beyond them: mainFile is only a heuristic guess with the exact candidate list and a caution to verify \begin{document}; the Overleaf pull is attempted first and aborts on conflict with unpushed local work while preserving that work; the first call clones the project and is therefore slower.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and contents, then usage routing, then caveats; every sentence carries distinct information. It is dense and slightly long for one paragraph, but there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return shape need not be re-explained, yet the description still covers the main applicable risks: the guess-based mainFile, clone-on-first-call latency, and the pull-conflict failure mode. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% so the parameter is already documented, but the description adds meaning the schema lacks: the project may be any project the default token reaches, registered or not, extending beyond the schema's 'registered project name' wording.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (summarize) and resource (one project), then enumerates the exact return contents (file counts by kind, likely main document and section count, pending local work) and the intent (orient at task start). It is immediately distinguishable from read-oriented siblings like list_files and project_status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: use list_files for every path, list_sections for a document's outline, project_status for commit-level sync state, and this tool to orient at the start of a task. When-to-use and when-to-use-something-else are both stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
push_changesPush changes to OverleafADestructive
Publish every pending local edit to Overleaf as one commit. This is the only tool that changes the project collaborators see, and the change is immediate and public. Call show_diff first, and compile_project when the edit could break the build. Before pushing, the server re-checks Overleaf and rebases onto whatever collaborators pushed in the meantime. If two edits touch the same lines the push is refused, both versions are reported, and no local work is lost: nothing is overwritten and no winner is chosen. commitMessage labels the one commit made from the pending edits; commits already waiting from an earlier refused push keep their own messages and go out with it. Only the chosen project is pushed. Returns the new commit hash and the diff that was published, or reports that there was nothing to push.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. | |
| commitMessage | Yes | Message describing the change, shown in the project's Overleaf history. One line, written for a co-author, e.g. "Rewrite Section 4 discussion". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only flag it as non-read-only, destructive, non-idempotent and open-world; the description adds substantial context beyond that: the server re-checks and rebases onto collaborator pushes, conflicting edits are refused with both versions reported and no work lost, and pending commits from an earlier refused push ride along. It also discloses that the effect is immediate and public and that only the chosen project is pushed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then prerequisites, then conflict behavior, then return values. Nearly every sentence carries load, though the multi-clause sentences make it denser than strictly necessary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no output schema, the description covers the essentials: prerequisites (show_diff, compile_project), conflict/refusal semantics, what is preserved on failure, scoping, and the return value ('the new commit hash and the diff that was published, or reports that there was nothing to push'). Nothing an agent needs to invoke it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema: commitMessage labels the single commit formed from pending edits, while commits already queued from an earlier refused push keep their own messages and go out with it. It also implies project scoping via 'Only the chosen project is pushed.'
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Publish every pending local edit to Overleaf as one commit') and explicitly positions itself against siblings with 'the only tool that changes the project collaborators see.' An agent can distinguish it from sync_project, replace_text, and write_file without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names prerequisites and ordering explicitly: 'Call show_diff first, and compile_project when the edit could break the build.' It also describes the conflict outcome that tells the agent when a push will be refused, giving both when-to-use and what-happens-next guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_fileRead a project fileARead-only
Read one text file from the project after pulling the latest commits from Overleaf. Plain calls return the text, line-numbered when startLine or endLine is given; startLine alone reads to the end, and endLine is clamped to the file. mode=full returns JSON with the content and a revision hash for a guarded edit; mode=smart with previousRevision returns kind unchanged, a delta, or full content when this server process does not know that revision or a delta would be no smaller. Use a line range to sample a large file, mode=full before an edit that passes expectedRevision, and mode=smart to re-read a file already read. Apply a delta only to its exact baseline: split on newline, replace deleteLineCount lines at the 1-based startLine with change.lines, and join on newline. Plain text is cut off after 60,000 characters; in a revision mode, a file too large to return whole comes back truncated with no revision. Fails without reading for a missing or binary file, a path outside the project, a line range combined with mode, or startLine after endLine.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Return revision-aware JSON instead of plain text: "full" for whole content plus a revision, "smart" for a delta against previousRevision. Cannot be combined with startLine/endLine. | |
| path | Yes | Path to the file relative to the project root, e.g. sections/intro.tex. | |
| endLine | No | Last line to return, inclusive. Cannot be combined with mode. | |
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. | |
| startLine | No | First line to return, 1-indexed. Cannot be combined with mode. | |
| previousRevision | No | A 64-character revision hash this server returned for this same file earlier in this session. Requires mode=smart. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover the safety profile (readOnlyHint, openWorldHint); the description adds substantial behavioral context beyond them — the pre-read commit pull, the 60,000-character plain-text cutoff, truncation-without-revision in revision modes, and the exact failure conditions (missing/binary file, out-of-project path, mode+line-range conflict, startLine after endLine).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a dense single block, but front-loaded with the core action and ordered sensibly (modes, then edit workflow, then truncation, then failures). The delta-application recipe is arguably reference material rather than selection guidance, which slightly dilutes conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and a complex multi-mode tool, the description carries the full burden and does so: return format (plain text vs revision JSON), revision/hash semantics, truncation behavior, and all documented failure paths. An agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real semantics the schema omits: startLine alone reads to the end, endLine is clamped, and it documents the exact delta-application algorithm (split on newline, replace deleteLineCount lines at 1-based startLine, join). It stops short of documenting every parameter (e.g. project resolution), so not a full 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a precise verb+resource ("Read one text file from the project") and adds the distinguishing behavior that it pulls the latest Overleaf commits first. It is clear what the tool does, but it never explicitly contrasts itself with the closely related sibling read_section, so the agent must infer the boundary from the resource wording.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states explicit selection rules for each mode: "Use a line range to sample a large file, mode=full before an edit that passes expectedRevision, and mode=smart to re-read a file already read." Each variant is tied to a concrete situation, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_sectionRead one LaTeX sectionARead-only
Read one section of a .tex file by its title: from its heading to the next heading at the same or a shallower level, stopping before trailing matter such as \appendix, the bibliography or \end{document}. Prefer it over read_file when revising one part of a paper, so the rest stays out of context. sectionTitle is compared case-insensitively with the title in braces, not an optional [short] title: an exact match wins, otherwise the first heading in document order that contains it, so a short fragment can pick an earlier section than intended. Pulls from Overleaf first. Returns the section's LaTeX source as stored, cut off after 60,000 characters; if nothing matches, the reply lists the titles that exist.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the .tex file relative to the project root, e.g. main.tex. | |
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. | |
| sectionTitle | Yes | Section title exactly as it appears inside the sectioning command, e.g. Introduction for \section{Introduction}. Call list_sections first if unsure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only give readOnlyHint/openWorldHint; the description adds substantial behavior: source resolution (Overleaf first), an explicit output cap of 60,000 characters with truncation, the boundary rule that stops before \appendix/bibliography/\end{document}, and the failure mode of returning existing titles. That is a lot of operational context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and free of filler, but it is dense: matching rules, truncation limit, source precedence and fallback behavior are packed into a few long multi-clause sentences, which would read better split out.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, and the description compensates fully: it says what is returned (the section's stored LaTeX, truncated at 60,000 chars) and what happens on no match. Combined with the boundary and source rules, an agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, yet the description goes past it by explaining that sectionTitle is matched case-insensitively against the brace title (not the [short] title), with exact match winning and otherwise first-containing match in document order — plus the concrete consequence that a short fragment may resolve to an earlier section. This is real added meaning for a required parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a precise verb+resource+scope: 'Read one section of a .tex file by its title', then defines the exact boundary (heading to next heading at same or shallower level). It explicitly contrasts itself with read_file, so an agent can separate it from sibling tools without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States the positive trigger ('when revising one part of a paper, so the rest stays out of context') and names the alternative to avoid ('Prefer it over read_file'). It also points to list_sections as the disambiguation step and records the 'Pulls from Overleaf first' source precedence.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
replace_textReplace exact text in a fileADestructive
Replace an exact snippet of text in a project file. Prefer it over write_file and edit_section for a targeted change: nothing outside the snippet is touched. findText must match exactly, whitespace and newlines included, and occur once unless replaceAll is set; replaceWith is inserted literally, so $$, $& and $1 stay as written. If the snippet is missing, or occurs several times without replaceAll, nothing changes and the reply gives the count; widen findText with surrounding text to make it unique. Pulls from Overleaf first, then edits only the local clone; push_changes publishes it. Returns how many occurrences were replaced.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path relative to the project root. | |
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. | |
| findText | Yes | Exact text to find, matched literally including whitespace and newlines. Not a regular expression. | |
| replaceAll | No | Replace every occurrence instead of requiring exactly one match (default false). Only set this when replacing all of them is intended. | |
| replaceWith | Yes | Text to put in its place. Empty string deletes the snippet. | |
| expectedRevision | No | Optional guard: the 64-character revision hash returned by read_file with mode=full or mode=smart for this same file. When given, the edit is refused if the file changed since that read — for example because pulling from Overleaf brought in a collaborator's version. Pass it whenever the edit depends on content you read earlier. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the safety profile (destructive, non-idempotent, open-world). The description goes well beyond: it explains that edits land only in the local clone until push_changes runs, that replaceWith is inserted literally with no $ substitution, that a failed match changes nothing and returns a count, and what the return value is. This is rich behavioral context an agent cannot get from structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads purpose and sibling preference, then failure modes, then the Overleaf/local/push lifecycle, then the return value. Dense but every sentence carries distinct information; no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-param destructive mutation with no output schema, the description covers the sync model, failure behavior, guard parameter intent, and return value. Nothing an agent needs to invoke it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline is 3, but the description adds real meaning beyond it: the literal-insertion rule for replaceWith ($$, $&, $1 stay as written), the exactness/uniqueness constraint on findText, and the remedy of widening findText. These go past the schema's phrasing.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Replace an exact snippet of text in a project file') and immediately differentiates from siblings by naming write_file and edit_section. An agent can distinguish this from the other mutating tools without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to prefer it over write_file and edit_section for a targeted change, and states the when-not condition (snippet missing or occurring several times without replaceAll). It also names the follow-up tool (push_changes) needed to publish.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_projectSearch the projectARead-only
Search the project's text sources for a literal string or a regular expression, returning matching lines as path:line: text. Use it to find where a term, citation key, label or command appears when you do not know which file holds it; once you do, use read_file or read_section, and use list_files to find a file by name. Only .tex, .ltx, .bib, .cls, .sty, .bst, .txt and .md files are searched, and a file created locally is not searched until push_changes commits it. Both modes are case-insensitive and match one line at a time, so a pattern cannot span lines. A regular expression uses JavaScript syntax, sees the first 4,000 characters of each line, and is abandoned with an error after 10 seconds; an invalid one fails with its syntax error. maximumMatches counts matching lines, taken in path order. Pulls from Overleaf first.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | What to look for. Literal text by default, so LaTeX backslashes need no escaping; a regular expression when isRegularExpression is true. | |
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. | |
| maximumMatches | No | Stop after this many matches, between 1 and 500 (default 100). | |
| isRegularExpression | No | Treat query as a regular expression instead of literal text (default false). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description adds substantial context beyond that: the allowed file extensions, the fact that locally created files are invisible until push_changes, case-insensitivity, single-line matching, the 4,000-character line window, the 10-second regex timeout, and the Overleaf-first ordering.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Information is front-loaded: purpose and return format come first, then the routing advice, then the constraints. It is dense and somewhat run-on, but nearly every clause carries a distinct constraint, so there is little waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a search tool with no output schema, the description covers the return format, filtering limits, file-scope restrictions, error behavior and staleness caveats. An agent has everything needed to call it correctly and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all four parameters are already documented, making 3 the baseline. The description does add a little meaning (maximumMatches counts matching lines taken in path order, and both modes are case-insensitive), but most of the extra detail is behavioral rather than parameter-specific.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (search) and resource (the project's text sources), specifies both modes (literal string or regex), and gives the exact return shape (path:line: text). It also distinguishes itself from read_file, read_section and list_files by naming when each is appropriate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly frames the use case ('when you do not know which file holds it') and routes the agent to the right siblings once the location is known ('use read_file or read_section, and use list_files to find a file by name'). Both the when and the alternative are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
show_diffShow pending changesARead-only
Show a unified diff of everything in one project's clone that Overleaf does not have yet: uncommitted edits, new and deleted files, and commits left behind by a refused push. Call it before push_changes to see exactly what collaborators will receive, and after a refused push to inspect what is still pending; use project_status when counts are enough. It does not pull first, so the comparison is against Overleaf as last fetched; it contacts Overleaf only to clone a project not opened before. Covers only the chosen project. The diff is cut off after 60,000 characters, and "No local changes pending." means there is nothing to push.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond readOnlyHint=true, it discloses non-obvious behavior: it does not pull first (comparison is against Overleaf as last fetched), it contacts Overleaf only to clone an unopened project, it covers only the chosen project, the diff is truncated at 60,000 characters, and it explains the 'No local changes pending.' output. This is exactly the context an agent cannot get from annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Usage guidance is front-loaded and every sentence carries load-bearing information (scope, fetch semantics, truncation, empty-state message). It is dense and runs long, but there is little true filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description still explains the return form (unified diff), the truncation limit, and the empty-result message, plus the fetch/scope caveats an agent needs to interpret results correctly. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and there is a single optional 'project' parameter already fully documented with address/id/name forms. The description adds no parameter-level detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (show) and resource (unified diff of the project's clone vs Overleaf), and enumerates exactly what the diff contains: uncommitted edits, new/deleted files, and commits from a refused push. This clearly separates it from siblings like project_status and push_changes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use conditions (before push_changes to preview what collaborators receive; after a refused push to inspect pending work) and names the alternative for a lighter need: 'use project_status when counts are enough.' Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sync_projectPull from OverleafAIdempotent
Pull the latest commits from Overleaf into one project's local clone. Nothing is sent to Overleaf and no local edit is discarded. The read tools pull on their own, so this is rarely needed first; call it to check explicitly that the clone is current, or after a collaborator says they have pushed. Use project_status for the full picture. If the pull cannot complete cleanly it fails and leaves local work untouched, rather than resolving the conflict on its own. Only the chosen project is pulled; a project not opened before is cloned instead, and reports nothing pulled. Returns how many commits were pulled and how many local commits are still unpushed.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the annotations: it discloses that nothing is sent upstream, that local edits are never discarded, that a dirty pull fails without attempting conflict resolution, that an unopened project is cloned instead and reports nothing pulled, and that the response contains pulled/unpushed commit counts. That is exactly the conflict-safety and side-effect detail the readOnlyHint/destructiveHint flags cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and keeps every sentence load-bearing, but at six sentences it is denser than needed; the failure-mode and first-clone clauses could be tightened without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by stating what is returned (pulled commit count and remaining unpushed commits). Combined with the sibling pointer and conflict behavior, an agent has everything needed to call this correctly on the first attempt.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds behavior for the project argument that the schema does not: 'Only the chosen project is pulled; a project not opened before is cloned instead, and reports nothing pulled.' It maps the parameter to a distinct outcome rather than restating its format.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with directionality: 'Pull the latest commits from Overleaf into one project's local clone.' The direction is made unmistakable ('Nothing is sent to Overleaf'), which cleanly separates it from the sibling push_changes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use conditions ('call it to check explicitly that the clone is current, or after a collaborator says they have pushed') and when-not ('The read tools pull on their own, so this is rarely needed first'), plus a routing pointer to project_status for the broader picture.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
write_fileWrite a whole fileADestructiveIdempotent
Write a whole file: create it, with any missing parent directories, or overwrite it entirely. Use it to add a new file; for an existing one prefer replace_text or edit_section, which cannot drop text you did not mean to rewrite. content is written exactly as given, as UTF-8, with no trailing newline added. expectedRevision makes the call a guarded overwrite, refused if the file changed since that read or no longer exists, so leave it out when creating a file. path must be relative and stay inside the project; absolute paths, .. escapes and the .git directory are refused. Pulls from Overleaf first, then writes only the local clone; push_changes publishes it. Returns whether the file was created or overwritten.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path relative to the project root, e.g. sections/related-work.tex. Must stay inside the project. | |
| content | Yes | The complete new contents of the file, not a fragment to append. | |
| project | No | Which project to use: its Overleaf address, its 24-character id, or a registered project name. Omit to use the default project. | |
| expectedRevision | No | Optional guard: the 64-character revision hash returned by read_file with mode=full or mode=smart for this same file. When given, the edit is refused if the file changed since that read — for example because pulling from Overleaf brought in a collaborator's version. Pass it whenever the edit depends on content you read earlier. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint/openWorldHint/idempotentHint, but the description adds substantial non-obvious behavior: UTF-8 with no trailing newline added, exact-as-given content, path guards (absolute, .. escapes, .git refused), the Overleaf-pull-then-local-write ordering, and that the guarded overwrite is refused if the file changed or vanished. This is the kind of context an agent cannot get from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense paragraph, front-loaded with the operation and its two modes, then routing, then behavioral caveats. Every sentence carries information; nothing is padding or restated boilerplate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by stating the return value ('whether the file was created or overwritten'). Combined with the write semantics, path restrictions, and sync ordering, an agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all four parameters, and the description largely mirrors it for path and content. It does add meaning beyond the schema for expectedRevision — tying it to the Overleaf pull and stating when to omit it — which is genuinely useful call-selection guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (write a whole file) plus the two modes it covers: create with missing parents, or full overwrite. It explicitly names the sibling operations to prefer for existing files (replace_text, edit_section), so an agent can distinguish it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('add a new file') and when-not ('for an existing one prefer replace_text or edit_section, which cannot drop text you did not mean to rewrite'), plus the condition for including expectedRevision ('leave it out when creating a file') and a follow-up routing hint to push_changes.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
18 tool updates
v0.3.8- First observed
compile_project - First observed
delete_file - First observed
discard_local_changes - First observed
edit_section - First observed
list_files - First observed
list_projects - First observed
list_sections - First observed
move_file - First observed
project_status - First observed
project_summary - First observed
push_changes - First observed
read_file - First observed
read_section - First observed
replace_text - First observed
search_project - First observed
show_diff - First observed
sync_project - First observed
write_file
TDQS
Scored across 18 tools
Each tool has a distinct resource+action, and descriptions explicitly cross-reference alternatives (e.g. list_files vs project_summary vs search_project, read_file vs read_section). Some mild overlap exists between read_file/read_section and show_diff/project_status/sync_project, but the descriptions resolve the boundaries clearly.
Nearly all tools follow a verb_noun or verb pattern (read_file, list_files, edit_section, push_changes, compile_project). The only deviations are the noun_noun pair project_summary and project_status, which are still readable and predictable.
18 tools is slightly on the heavy side but each earns its place across the read/edit/sync/compile/publish lifecycle of a real Overleaf client. No obvious redundant tools inflate the count.
The surface covers the full editing lifecycle: discovery, read, search, edit, write, move, delete, diff, status, sync, compile, and push. Minor gaps remain (project creation, history/versioning, PDF export, collaborator management), but core workflows have no dead ends.
Maintenance
Related MCP Connectors
Edit your Overleaf LaTeX projects from Claude and ChatGPT; every change is a real Git commit.
Read and write KukGit repositories, files, issues and pull requests from an AI assistant.
Persistent AI LaTeX workspace: edit and compile multi-file projects, export publication-ready PDFs.
Overleaf alternative online LaTeX editor. AI agents edit, comment, and chat. Keep or revert edits.
Related MCP Servers
- AlicenseBqualityDmaintenanceProvides access to Overleaf projects via Git integration, allowing Claude and other MCP clients to read LaTeX files, analyze document structure, and extract content.6125 npm312MIT
- AlicenseAqualityAmaintenanceEnables access to Overleaf LaTeX projects through Git integration, allowing users to read files, analyze document structure, extract sections, and manage multiple projects through natural language commands.215 npm10MIT
- AlicenseBqualityBmaintenanceEnables MCP clients to manage Overleaf projects via Git sync, including listing, reading, writing, and syncing files.4153 PyPI64MIT
- AlicenseNot gradedqualityAmaintenanceConnects Claude/ChatGPT to Overleaf projects via the Git integration, enabling read, edit, write, and file management through natural language commands.2AGPL 3.0