Skip to content

Latest commit

 

History

History
226 lines (171 loc) · 10 KB

CONTRIBUTING.md

File metadata and controls

226 lines (171 loc) · 10 KB

Contributing to GitLab MCP Server

Thanks for your interest in improving @zereight/mcp-gitlab! This document explains how to set up the project locally, the conventions we follow, and how to get your change merged.

Quick links


Ways to contribute

  • Report a bug — open a GitHub issue with steps to reproduce, the client you're using (Claude Code, VS Code, Cursor, etc.), the transport (stdio / SSE / streamable HTTP), and the relevant environment variables.
  • Request a feature — open an issue describing the GitLab capability you want exposed and why it matters for your workflow.
  • Submit a fix or new tool — fork the repo and open a pull request (details below).
  • Improve the docs — the docs site is generated from docs/. PRs that clarify a setup guide, fix a broken link, or add a missing example are very welcome.

Development setup

Prerequisites

Tool Version Notes
Node.js 22.21.1 Pinned in .nvmrc. Use nvm use to match.
npm bundled with Node 22
Git any recent version
Python 3.10+ (only for docs) Required if you want to preview the docs site.
GitLab account optional Needed only for live integration tests.

Clone, install, build

git clone https://github.com/zereight/gitlab-mcp.git
cd gitlab-mcp
nvm use            # or: nvm install
npm install
npm run build      # compiles TypeScript to build/

Run the server locally

# Personal Access Token (stdio transport, the default for local clients)
GITLAB_PERSONAL_ACCESS_TOKEN=glpat-xxxx \
GITLAB_API_URL=https://gitlab.com/api/v4 \
  node build/index.js

Watch mode for faster iteration:

npm run watch      # tsc --watch in one terminal
node build/index.js   # restart this as needed in another

See Environment Variables for the complete list of flags the server understands.

Project structure

.
├── index.ts                    # Main MCP server entry point — tool dispatch
├── config.ts                   # Env var + CLI argument parsing
├── schemas.ts                  # Zod schemas for every tool's input
├── tools/registry.ts           # allTools[] + TOOLSET_DEFINITIONS (grouping)
├── auth-retry.ts               # OAuth token refresh on 401
├── oauth.ts                    # Local-browser OAuth2 flow
├── oauth-proxy.ts              # MCP OAuth proxy for remote clients
├── gitlab-client-pool.ts       # Dynamic API URL connection pool
├── stateless/                  # Multi-pod stateless OAuth helpers
├── utils/                      # Shared helpers (schema, tool-args, etc.)
├── test/                       # Mock + live test suites
├── docs/                       # MkDocs source — published to GitHub Pages
├── scripts/                    # Maintenance scripts (release, doc-gen)
└── .github/workflows/          # CI pipelines

When adding a new tool:

  1. Define the input schema in schemas.ts — use z.object({…}).describe(...) on each field; the generated docs depend on those descriptions.
  2. Register it in tools/registry.ts — add to allTools with a name, description, and inputSchema, then add the name to the appropriate TOOLSET_DEFINITIONS entry.
  3. Implement the dispatch case in index.ts under the relevant switch block.
  4. Add a test under test/ that actually calls the tool (callTool("name") or equivalent).
  5. Fork PRs can skip regenerating the tool docs and coverage page (make tools-docs); a bot syncs them after merge (see below).

Testing

npm run test:mock        # Fast unit + mock-server tests. Run these locally.
npm run test:consumer-smoke  # Pack + install smoke test (same as CI).
npm run test:all         # mock + live; live tests need a real GitLab token.
npm run test:schema      # JSON schema validation.
npm run test:oauth       # OAuth2 flow against the mock server.
npm run test:stateless   # Multi-pod / stateless OAuth helpers.

CI (.github/workflows/pr-test.yml) runs test:mock, test:consumer-smoke, and npx tsc --noEmit on every PR. Make sure those pass locally before pushing.

Live integration tests

GITLAB_PERSONAL_ACCESS_TOKEN=glpat-xxxx \
GITLAB_API_URL=https://gitlab.com/api/v4 \
TEST_PROJECT_ID=<sandbox project id> \
  npm run test:live

Live tests touch a real GitLab instance — use a throwaway sandbox project, not anything you care about.

Code style

Tool Command Purpose
Prettier npm run format Formats *.{js,ts,json,md}.
Prettier (check) npm run format:check CI gate.
ESLint npm run lint TypeScript lint.
ESLint (autofix) npm run lint:fix Auto-fix where possible.
TypeScript npx tsc --noEmit Type check.

Conventions enforced by CI:

  • No stray console.log in *.ts (test files are exempt). Use proper logging.
  • No TODO / FIXME / XXX comments in committed code — open an issue instead.
  • Strict TypeScript — npm run build emits with tsconfig.build.json (tests and scripts stay out of build/). tsc --noEmit still typechecks the full tsconfig.json, including tests.

Submitting changes

  1. Branch from main. Use a descriptive name:

    • feat/<short-description> for new features or new tools
    • fix/<short-description> for bug fixes
    • docs/<short-description> for docs-only changes
    • chore/<short-description> for refactors, deps, CI tweaks
  2. Commit messages — short, present-tense, lowercase prefix matching the branch type:

    feat: add list_dependency_proxy_blobs tool
    fix: handle 429 rate-limit on get_merge_request
    docs: clarify OAuth redirect URI for Cursor
    

    We don't enforce Conventional Commits strictly, but the changelog generator (npm run changelog) groups commits by these prefixes.

  3. Pull request — open against main. In the description, include:

    • What changed (one paragraph).
    • Why — link an issue if there is one.
    • How tested — which npm test commands ran, and any manual verification with a real MCP client (Claude Code, Cursor, etc.).
    • Breaking changes — call them out explicitly.
  4. CI must pass — pr-test.yml runs the mock test suite, type check, lint, Docker build, formatting check, and npm audit. Address all real failures; the existing "warning" steps (e.g., the TODO grep) are informational.

  5. Review — a maintainer will review. We try to respond within a few days. Small, focused PRs get merged fastest.

Documentation contributions

The docs at zereight.github.io/gitlab-mcp are generated from docs/ with MkDocs Material.

make serve         # preview locally at http://127.0.0.1:8000/gitlab-mcp/
make build         # strict build (same as CI)
make tools-docs    # regenerate tool pages + docs/reference/tool-coverage.md

When changing tools, schemas, or toolsets:

The per-group tool pages under docs/tools/ and docs/reference/tool-coverage.md are generated from tools/registry.ts, the Zod schemas, and the tests under test/. If your PR comes from a fork, you don't need to regenerate them:

  • On a PR from a fork, a generated-docs diff in the docs-build job is only a notice. It does not fail the job.
  • After merge, .github/workflows/tool-docs-sync.yml runs npm run docs:tools on main and, if the output changed, opens an automation/tool-docs PR as github-actions[bot].

To preview the pages locally, run make tools-docs. For a PR from a branch in this repository, docs-build still fails on drift, so commit the result.

The docs CI workflow (.github/workflows/docs.yml) regenerates the tool pages, then rebuilds and deploys the site on every push to main that touches docs/, mkdocs.yml, requirements-docs.txt, a .ts file, test/, or package.json / package-lock.json.

Hosted site (maintainers, one-time): GitHub Pages must use Build and deployment → Source: GitHub Actions, not deploy from main. See docs/reference/github-pages-setup.md.

When changing prose docs:

Just edit the markdown under docs/ and run make serve to preview. mkdocs build --strict (run by CI) will fail on broken internal links, so keep cross-references accurate.

Release process

Releases are cut by maintainers via scripts/release.sh and published to npm via npm-publish.yml. External contributors don't need to do anything for release — the maintainer will handle versioning and the changelog.

Getting help

  • Questions about usage — open a GitHub Discussion or a discussion-style issue.
  • Sensitive reports (security, conduct) — email the maintainers via the address listed in the repo's package.json / npm page rather than filing a public issue.

Thanks for contributing!