Skip to content

Releases

v0.5.5 — per-user PATs and server hardening

Choose a tag to compare

@mshegolev mshegolev released this 04 Nov 06:54
94f82a7

Added

  • Opt-in Streamable HTTP transport for shared deployments. Every request uses
    the caller's GitLab PAT from X-GitLab-Token; stdio remains the default and
    continues to use GITLAB_TOKEN.
  • Per-user manager/session isolation keyed by GitLab URL, project, and an
    HMAC-only PAT fingerprint, with bounded cache eviction and session cleanup.
  • Release workflow runs pytest and Ruff against the exact tag commit before
    publishing through PyPI Trusted Publisher/OIDC.
  • Explicit update check: disabled by default and enabled only with
    MCP_GITLAB_UPDATE_CHECK_ENABLED=true.

Fixed

  • Pipeline health now distinguishes API failures, incomplete pagination,
    malformed dates, and insufficient comparison data.
  • Schedule variable failures and partial writes are reported instead of
    appearing successful.
  • Job log regex and output sizes are bounded; MR diff truncation is explicit.
  • GitLab tools require explicit project scope unless the legacy fallback is
    explicitly enabled.

v0.5.4 — documentation cleanup

Choose a tag to compare

@mshegolev mshegolev released this 04 Nov 06:54

Docs-only release: no change under src/ behaviour.

Changed

  • docs/claude-code.md: troubleshooting heading uses a generic *.example.com host instead of an internal domain.

v0.5.3 — CI and entrypoint coverage

Choose a tag to compare

@mshegolev mshegolev released this 04 Nov 06:54

Housekeeping release: no change under src/; adds CI and tests only.

Added

  • CI actually runs the tests. New .github/workflows/test.yml (pytest +
    ruff check on Python 3.10/3.11/3.12, on every push and PR to main). Until
    now the only workflow was publish.yml, which builds and uploads on a v*
    tag without ever invoking pytest or ruff — which is how 0.5.1 went out green
    while one mcp release away from never starting. ruff format --check is
    intentionally not in the workflow: it flags 5 files of pre-existing drift
    from a newer ruff, and a gate that is red on day one gets disabled on day two.
  • Entry-point smoke tests (tests/test_entrypoint.py, 8 tests). Covers the
    path a real MCP client walks and no other test touched: console_scripts
    metadata → gitlab_ci_mcp.server:main → mcp.run() → stdio → clean exit on
    EOF, plus protocol-level list_tools() / list_resources() and a check that
    the server builds with no credentials in the environment. Offline; no GitLab,
    no token. Verified mutationally: making main() fail at runtime leaves the
    previous 21 tests and ruff check green and turns only these red.

Changed

  • [tool.pytest.ini_options] in pyproject.toml anchors pytest's rootdir at
    the repo, so a stray pytest.ini in a parent directory can no longer inject
    its addopts and break collection before a test runs.

v0.5.2 — MCP SDK compatibility fix

Choose a tag to compare

@mshegolev mshegolev released this 04 Nov 06:54

Fixed

  • Pin mcp>=1.2,<2. mcp 2.0 removed mcp.server.fastmcp, which this
    server imports in six modules. Without an upper bound a clean
    pip install gitlab-ci-mcp resolved mcp 2.0 and the gitlab-ci-mcp
    console script died on import with
    ModuleNotFoundError: No module named 'mcp.server.fastmcp' — from an MCP
    client this looked like an opaque transport failure, easy to misread as a
    credentials or URL problem. Test collection failed for the same reason.
  • __version__ in gitlab_ci_mcp/__init__.py was stuck at 0.5.0 and is now
    back in sync with pyproject.toml and server.json.

v0.5.1 — MCP Registry metadata

Choose a tag to compare

@mshegolev mshegolev released this 04 Nov 06:54

Added

  • mcp-name: io.github.mshegolev/gitlab-ci-mcp marker in README —
    required for ownership verification when publishing to the official
    MCP Registry.

v0.5.0 — structured outputs and modular server

Choose a tag to compare

@mshegolev mshegolev released this 04 Nov 06:54

Big one. Every tool is now a fully typed MCP citizen: outputSchema,
structuredContent, and the markdown text block you liked are now all
present on every response.

Added

  • TypedDict output schemas for all 23 tools (new models.py) —
    FastMCP auto-generates an outputSchema from the return annotation
    and exposes the typed payload as structuredContent on every tool
    result.
  • Dual-channel responses via CallToolResult — the content
    block still carries the compact markdown rendering (context-efficient
    for agents), while structuredContent carries the full validated
    payload (for clients that can render / process structured data).
  • New output.py with ok() (builds the CallToolResult) and
    fail() (raises ToolError wrapping the actionable error
    message). All 23 tools share this pattern.

Changed

  • Server split into domain modules: the 1500-line server.py is
    now a thin composition point; tools live under tools/
    (pipelines.py, schedules.py, branches_tags.py, mrs.py,
    repo.py), MCP resources in resources.py, and shared FastMCP
    instance + lifespan + helpers in _mcp.py.
  • Shared helpers _get_ci / _ts / _is_secret_key /
    _mask_variables renamed without the leading underscore and moved
    to _mcp (they are no longer single-module private).
  • Error path is now uniform: tools raise ToolError(errors.handle(…))
    and FastMCP reports the result as isError=True — no more
    string-based error returns.

Removed

  • response_format parameter (breaking): no longer needed because
    every tool now returns both markdown and structured data. Existing
    callers that passed response_format='markdown' or 'json' must
    drop the argument — markdown remains the text content by default,
    structured data is on result.structuredContent.
  • Dead code from ci_manager.py: wait_for_pipeline,
    ScheduleCompareResult (unused from the MCP path).

Migration notes (v0.4.x → v0.5.0)

  • Tools no longer return plain strings. If you call them programmatically,
    inspect result.structuredContent for the typed payload and
    result.content[0].text for the markdown summary.
  • Module imports moved: from gitlab_ci_mcp.server import mcp still
    works, but tool functions now live under gitlab_ci_mcp.tools.*.

v0.4.0 — lifespan, MCP Context, Resources

Choose a tag to compare

@mshegolev mshegolev released this 17 Apr 12:43

Closes the last four optional items from the /mcp-builder best-practices checklist.

  • Lifespan management — asynccontextmanager hook cleans up python-gitlab HTTP sessions and the manager cache on shutdown.
  • MCP Context integration — gitlab_pipeline_health and gitlab_get_job_log are now async def and emit ctx.info / ctx.report_progress events. Clients with progress UIs (Claude Code, Cursor) will show a progress bar while the 30-day history is being fetched.
  • MCP Resources — two URI templates for clients that prefer Resources over tools:
    • gitlab://project/info — markdown snapshot of the default project
    • gitlab://project/ci-config — raw .gitlab-ci.yml
  • Threading model documented — FastMCP auto-runs sync tools in a worker thread (anyio.to_thread.run_sync), so not converting every tool to async def is an intentional choice, not an oversight. README has a new section spelling this out.

Package health: 16 tests (9 smoke + 7 mock), ruff clean, all 23 tools + 2 resources registered.

v0.3.1 — tool examples and usage guidance

Choose a tag to compare

@mshegolev mshegolev released this 04 Nov 06:54

Added

  • Examples section on every remaining tool docstring — all 23 tools now
    include "Use when / Don't use when" guidance for LLM tool-picking.
  • CHANGELOG.md.
  • README section on rate limits and connection reuse.

v0.3.0 — pagination, mock tests, evaluations

Choose a tag to compare

@mshegolev mshegolev released this 17 Apr 12:15

Closes four remaining gaps against the MCP server best-practices checklist.

Pagination

  • New pagination module with a uniform pagination block (page, per_page, total, total_pages, next_page, has_more) extracted from python-gitlab list results.
  • gitlab_list_pipelines, gitlab_list_branches, gitlab_list_tags, gitlab_list_merge_requests, gitlab_list_repository_tree now take page and return the pagination block.
  • Markdown formatters include a footer line with a next-page hint.

Docstring Examples

  • Added Examples: section to 14 tool docstrings — 'Use when … → args' / 'Don't use when … use <other_tool> instead'. Improves LLM tool-picking accuracy.

Mock tests

  • New tests/test_tools_mocked.py with 7 tests using the responses library — happy paths (JSON + markdown), pagination, 401, 404, missing env, project info. Guards against shape regressions in python-gitlab upgrades.

Evaluations

  • evaluations/questions.xml — 22 tool-picking QA pairs (one per tool) for agent evaluation.
  • evaluations/README.md — runner snippet + fixture-based evaluation notes.

Total: 13 tests (6 smoke + 7 mock). Ruff clean. 23 tools, 1 pagination helper, 2 test files.

v0.2.0 — best-practice refactor

Choose a tag to compare

@mshegolev mshegolev released this 17 Apr 11:48

Refactor pass aligning the server with the MCP server best practices checklist.

Highlights

  • Tool annotations on every tool — `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`. MCP clients can classify operations and ask for confirmation only where it matters (merge, delete, cancel, update-with-variables).
  • Dual response format — every read tool now accepts `response_format='markdown'` (default, compact) or `'json'` (full raw structure).
  • Actionable error messages — `errors.handle()` converts `GitlabAuthenticationError`, 404/403, rate-limits, config errors into messages that tell the agent what to do next (check `GITLAB_TOKEN` scope, verify project path, etc.) instead of raw tracebacks.
  • Pydantic input validation — all args use `typing.Annotated` + `pydantic.Field` with `description`, `min_length`/`max_length`, `ge`/`le`, `Literal[...]` for enums. JSON Schema auto-generated for MCP clients.
  • Markdown formatters for pipelines, jobs, schedules, branches, tags, MRs, MR changes, repo tree, file content, diff, project info.
  • Server name bumped from `'gitlab'` to `'gitlab_ci_mcp'` to match `{service}_mcp` convention.

Compatibility

  • Python `>=3.10` (unchanged)
  • Config env vars unchanged: `GITLAB_URL`, `GITLAB_TOKEN`, `GITLAB_PROJECT_PATH`, `GITLAB_SSL_VERIFY`, `GITLAB_NO_PROXY_DOMAINS`
  • All tool names unchanged, only new optional `response_format` parameter on read tools

Install

```bash
uvx --from gitlab-ci-mcp gitlab-ci-mcp

or

pipx install gitlab-ci-mcp
```