Contributing¶
Thanks for considering a contribution. This file is short on purpose, since the project is small and the conventions are easy.
Quick start¶
git clone https://github.com/amcheste/overleaf-mcp.git
cd overleaf-mcp
# Install dev environment
uv sync --extra dev
# Optional but recommended: install the pre-commit hooks
# (matches what CI checks, catches issues before push)
uv run pre-commit install
# Run the suite
uv run pytest
# Run the linter
uv run ruff check src/ tests/
# Run a single test file or test
uv run pytest tests/core/test_paths.py -v
uv run pytest tests/core/test_paths.py::test_absolute_path_rejected -v
# Acceptance suite (real Overleaf round-trips). Excluded from the default
# run; opt in with -m. Requires OVERLEAF_TEST_PROJECT_ID and
# OVERLEAF_TEST_TOKEN; skips cleanly without them.
uv run pytest -m acceptance -v
You'll need Python 3.11 or newer and uv.
Previewing the docs site locally¶
The documentation site (https://amcheste.github.io/overleaf-mcp/) is built with MkDocs Material. To work on it locally:
Build the static site (what CI deploys):
The --strict flag catches broken links and missing files. CI uses the
same flag, so if it builds locally it'll build in CI.
Branch model¶
developis the integration branch. PRs targetdevelop.mainis the release branch. Promoted fromdevelopvia CLI--no-ffmerge at release time, never via a GitHub PR.- Feature branches:
feat/<short-name>,fix/<short-name>,docs/<short-name>,test/<short-name>,chore/<short-name>. - Branch protection requires the
All tests passedandAll wheel-smoke tests passedaggregator checks before merge to eitherdevelopormain.
Commit messages¶
Conventional Commits, prefix-only:
feat(core): ...for new functionalityfix(tools): ...for bug fixesdocs: ...for documentationtest: ...for test additionschore: ...for tooling and release workrefactor: ...for non-behavior-changing structural changesci: ...for workflow changes
The body of the commit should explain why, not just what. The diff already shows the what.
What "done" looks like for a PR¶
Before opening a PR:
- [ ]
uv run pytestpasses - [ ]
uv run ruff check src/ tests/is clean - [ ] Coverage hasn't dropped (visible in pytest output; the bar is 80% but we hold 100% on the measured modules)
- [ ] If you added user-visible behavior, the README or CHANGELOG reflects it
- [ ] Pre-commit ran on every commit (or you ran
uv run ruff formatmanually)
Acceptance tests (uv run pytest -m acceptance) gate releases, not
PRs, so you don't need them to run them on every PR. They run on
every v*.*.* tag push (blocking PyPI publish if any fail) and once
nightly (opening an issue if anything breaks). See
tests/acceptance/README.md
for what's covered and how to add to the suite.
Code style¶
- Default to no comments. The code should explain itself; comments exist to document why a non-obvious decision was made, not to narrate what a line does.
- Test the behaviour, not the implementation. Mocks at module
boundaries; real subprocess + real git in
tests/core/test_git_client.py. - Prefer named exceptions over generic ones for things callers
might reasonably want to handle differently (
PathEscapeError,TokenNotFoundError,GitOperationError). - Error messages are UX. Include the actionable next step when you can. Error messages are the first thing users read when something fails.
Architecture overview¶
See CLAUDE.md for the in-repo design notes: what each subpackage owns, why git is the write API, why credentials never touch disk, why the server is single-process / single-user by design. That file is the one-stop overview for understanding the codebase.
Where to ask questions¶
- Bug? File an issue
- Idea? File a feature request
- General question? GitHub Discussions
- Security issue? Please report privately. See SECURITY.md.