mcpbeat

Gitlab

microsoft/gitlab

Manage GitLab merge requests and pipelines with a Python CLI

46k tokens
context cost
the whole folder, loaded on every use
54
files
ships runnable scripts
0
copies elsewhere
how many repositories repackaged it
1313
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/microsoft/hve-core --skill gitlab

What comes with it

57 416 bytes besides the instruction
SECURITY.md
pyproject.toml
scripts/gitlab.py
tests/conftest.py
tests/corpus/0814fd5a169c01a1448b1817d8ac617d6f277db8
tests/corpus/0_empty
tests/corpus/0_large
tests/corpus/0_no_suffix
tests/corpus/0_remote_path
tests/corpus/0_unicode
tests/corpus/0_with_suffix
tests/corpus/1_empty
tests/corpus/1_float
tests/corpus/1_large
tests/corpus/1_negative
tests/corpus/1_numeric_id
tests/corpus/1_valid_id
tests/corpus/2_deeply_nested
tests/corpus/2_empty
tests/corpus/2_field_path
tests/corpus/2_nested_json
tests/corpus/2_unicode
tests/corpus/3_empty
tests/corpus/3_json_payload
tests/corpus/3_large
tests/corpus/3_malformed
tests/corpus/3_trailing
tests/corpus/3_valid_json
tests/corpus/4_empty
tests/corpus/4_float
tests/corpus/4_large
tests/corpus/4_negative
tests/corpus/4_positive_int
tests/corpus/4_unicode
tests/corpus/4_zero
tests/corpus/5_empty
tests/corpus/5_field_flag
tests/corpus/5_large
tests/corpus/5_mr_list
tests/corpus/5_multi_field

The instruction itself

12 sections, as written by the author

GitLab Skill

Overview

Use this skill to inspect and update GitLab merge requests, notes, pipelines,

and job logs against GitLab.com or self-managed GitLab instances.

This skill is the repository-local Python workflow for GitLab tasks. It is not

the official GitLab MCP server integration surface.

This first hve-core implementation is Python-only. Run the CLI through

python scripts/gitlab.py and prefer --fields for read operations to keep

output concise.

Prerequisites

The skill requires Python 3.11 or later.

Set these environment variables before running any command:

| Variable | Required | Example | Purpose |

|------------------|----------|----------------------|-----------------------------------------------|

| GITLAB_URL | Yes | https://gitlab.com | GitLab instance URL |

| GITLAB_TOKEN | Yes | glpat-... | Personal access token sent as PRIVATE-TOKEN |

| GITLAB_PROJECT | No | group/project | Project path or numeric project ID |

If GITLAB_PROJECT is not set, the script attempts to detect the project from

git remote get-url origin. Set the variable explicitly when you are not in a

git repository or when you want to target a different project.

Operational Variables

| Variable | Required | Purpose |

|----------------------|----------|-----------------------------------------------------------------------------------------|

| GITLAB_AUDIT_LOG | No | Path to a JSON Lines audit log. When set, every request is audited (see Audit Logging). |

| GITLAB_AUDIT_ACTOR | No | Overrides the recorded actor identity (for example, a CI service principal). |

Audit Logging

When GITLAB_AUDIT_LOG is set, the script writes a structured JSON Lines audit trail for every API request. Auditing is fail-closed and write-ahead:

  • An attempt record is written before the request is sent. If the audit log cannot be written, the operation is aborted and nothing is sent to GitLab.
  • An outcome record (success or error, with HTTP status on failure) is written after the request completes.

Each record includes a UTC timestamp, the actor (from GITLAB_AUDIT_ACTOR, otherwise gitlab-token), the operation, HTTP method, and the request path. Tokens, authorization headers, and query strings are never written. Audit failures after the request emit a warning without altering the result.

Credential Rotation

The script reads GITLAB_TOKEN from the environment on every invocation, so an external rotator can swap it between calls without code changes. A 401 or 403 response indicates the token may be expired or revoked; rotate the personal access token in GitLab user settings. Full OAuth-style refresh flows are out of scope for this CLI.

Quick Start

Export your environment variables, then run a read command with --fields.

export GITLAB_URL="https://gitlab.com"
export GITLAB_TOKEN="glpat-..."
export GITLAB_PROJECT="group/project"

python scripts/gitlab.py mr-list opened --fields iid,title,author.name

Read pipeline jobs for a known pipeline:

python scripts/gitlab.py pipeline-jobs 12345 --fields id,name,status,stage

Parameters Reference

Common Option

| Parameter | Applies To | Example | Description |

|------------|------------------------------------------------------------------|----------------------------|-----------------------------------------------------------------------------------------|

| --fields | mr-list, mr-get, mr-notes, pipeline-get, pipeline-jobs | --fields iid,title,state | Extract specific fields with dot notation and print concise tabular or key-value output |

Commands

| Command | Arguments | Description |

|-----------------|----------------------------|------------------------------------------------------------------------|

| mr-list | [state] [max] | List merge requests, defaulting to all states and 20 results |

| mr-get | <mr-iid> | Get one merge request by project-scoped IID |

| mr-create | <json> or stdin | Create a merge request from a JSON payload |

| mr-update | <mr-iid> <json> or stdin | Update merge request fields from a JSON payload |

| mr-comment | <mr-iid> <body> or stdin | Add a comment to a merge request |

| mr-notes | <mr-iid> [max] | List merge request notes, excluding system notes when using --fields |

| pipeline-get | <pipeline-id> | Get one pipeline by numeric ID |

| pipeline-run | <branch-or-tag> | Trigger a pipeline for a branch or tag |

| pipeline-jobs | <pipeline-id> | List jobs for a pipeline |

| job-log | <job-id> | Print raw log output for a job |

Script Reference

List recent open merge requests:

python scripts/gitlab.py mr-list opened --fields iid,title,author.name,user_notes_count

Get one merge request:

python scripts/gitlab.py mr-get 42 --fields iid,title,state,source_branch,target_branch

Create a merge request from inline JSON:

python scripts/gitlab.py mr-create '{
  "source_branch": "feature/add-auth",
  "target_branch": "main",
  "title": "feat(auth): add OAuth login"
}'

Add a merge request comment from standard input:

echo "CI passed. Ready for review." | python scripts/gitlab.py mr-comment 42

Inspect a failed pipeline:

python scripts/gitlab.py pipeline-get 12345 --fields id,status,web_url
python scripts/gitlab.py pipeline-jobs 12345 --fields id,name,status,stage
python scripts/gitlab.py job-log 67890

Troubleshooting

| Symptom | Cause | Resolution |

|--------------------------------------------------|-----------------------------------------------|-------------------------------------------------------------|

| GITLAB_URL is not set | Required environment variable missing | Export GITLAB_URL before running the script |

| GITLAB_TOKEN is not set | Missing personal access token | Create a token with API access and export GITLAB_TOKEN |

| cannot parse git remote URL | Project autodetection failed | Set GITLAB_PROJECT explicitly |

| HTTP 401 or HTTP 403 | Token is invalid or lacks access | Verify token scope and project permissions |

| HTTP 404 | Wrong project, MR IID, pipeline ID, or job ID | Verify GITLAB_PROJECT and confirm the numeric identifiers |

| expected numeric ID | Non-numeric value passed to an ID argument | Use project MR IID values and numeric pipeline or job IDs |

| python3 is required or syntax errors on launch | Unsupported interpreter | Run the script with Python 3.11 or later |

GitLab uses MR IIDs such as !42 inside a project. This skill expects the

numeric IID, not the global merge request ID.

How to use it

Copy the folder

Take microsoft/gitlab from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.