Set up a dev environment & contribute
Contributions are welcome. This guide covers setting up your development environment, running the test suite, and submitting a pull request.
Prerequisites
Section titled “Prerequisites”- Go 1.26+ — install from go.dev/dl.
- golangci-lint v2.11 — the linter version pinned for this project.
Install golangci-lint to ~/go/bin/ (the go install path does not work for
v2.x — use the install script):
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh \ | sh -s -- -b ~/go/bin v2.11.0Verify:
~/go/bin/golangci-lint --version# golangci-lint has version v2.11.xClone and build
Section titled “Clone and build”git clone https://github.com/lmgarret/polar-flow-mcp.gitcd polar-flow-mcpmake buildThe binary is written to bin/polar-flow-mcp. The build uses CGO_ENABLED=0 so
no C toolchain is required.
Run the tests
Section titled “Run the tests”make testThis runs:
CGO_ENABLED=0 go test -tags=polartest -race -count=1 ./...The -tags=polartest flag is required — it enables test-only code that allows
redirecting HTTP requests to test servers. Omitting the flag will cause test
failures. All tests must pass before submitting a PR; CI runs the same command.
Run the linter
Section titled “Run the linter”make lintThis runs:
~/go/bin/golangci-lint run ./...The linter is configured in .golangci.yml at the repo root. Enabled linters
include gocyclo, godot, misspell, noctx, and errcheck (with type
assertion checking). Fix all lint errors before submitting a PR.
Pre-PR checklist
Section titled “Pre-PR checklist”-
make testpasses -
make lintpasses with zero errors - Documentation updated if you changed behaviour or added a feature
- Commit messages follow conventional commit format (see below)
Commit message format
Section titled “Commit message format”This project uses Conventional Commits:
<type>(<scope>): <short description>
[optional body]| Type | When to use |
|---|---|
feat | New feature or new MCP tool |
fix | Bug fix |
docs | Documentation only |
chore | Maintenance (deps, config) |
refactor | Code restructuring without behaviour change |
test | Test additions or changes |
ci | CI workflow changes |
Examples:
feat(mcp): add list_training_targets toolfix(oauth): handle expired CSRF state gracefullydocs(security): document key rotation planchore(deps): update mcp-go to v0.8.0Conventional commits feed the release notes. Pushing a v* tag runs the release
workflow, which uses an LLM to summarise the commits since the previous tag into
categorised, benefit-focused notes and publishes them on the GitHub Release
(alongside the Docker image ladder and the full commit log). Clear, well-scoped
commit messages therefore produce clearer release notes.
Running locally
Section titled “Running locally”To run the server locally for development you need a .env file (or exported
variables) with at minimum:
export POLAR_EMAIL=you+polartest@example.comexport POLAR_PASSWORD=correct-horse-battery-stapleexport COOKIE_JAR_PATH=./polar-cookies-dev.jsonexport LOG_LEVEL=debugThen:
make build./bin/polar-flow-mcpThe server binds to 127.0.0.1:8080 by default. Liveness check:
curl http://127.0.0.1:8080/healthzOn the first run the server performs the headless login chain against
auth.polar.com and writes polar-cookies-dev.json (mode 0600). Subsequent
runs re-use the jar and skip the password step.
Regenerating the OpenAPI client
Section titled “Regenerating the OpenAPI client”If you bump the upstream spec or the ogen version, regenerate
internal/flow/gen/:
python3 internal/flow/preprocess-spec.py \ ../polar-openapi-maker/dist/openapi.yaml \ internal/flow/openapi.yamlgo install github.com/ogen-go/ogen/cmd/ogen@latestogen --target internal/flow/gen --package gen --clean internal/flow/openapi.yamlThe preprocessor converts OpenAPI 3.1 nullable union syntax to the 3.0.3 form ogen accepts. No other semantic changes.
Documenting your changes
Section titled “Documenting your changes”These docs are built with Astro Starlight and
live under docs/. To preview locally:
cd docsnpm installnpm run devContent is organised by the Diátaxis framework — put new
pages under src/content/docs/{tutorials,guides,reference,explanation}/ depending
on whether they teach, solve a task, describe, or explain. Cross-page links are
relative (../../<group>/<page>/) so they stay correct under the site’s base
path.
Code style
Section titled “Code style”- Follow standard Go formatting (
gofmt). - Keep cyclomatic complexity below 15 per function (
gocyclowill catch violations). - End comments with a period (
godotwill catch violations). - Use
log/slogfor all logging — nofmt.Printlnorlog.Printf. - Context keys must use unexported struct types to prevent cross-package collisions.