mcp-gitlab-crunchtools 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. mcp_gitlab_crunchtools-0.1.0/.github/workflows/ci.yml +53 -0
  2. mcp_gitlab_crunchtools-0.1.0/.github/workflows/container.yml +67 -0
  3. mcp_gitlab_crunchtools-0.1.0/.github/workflows/publish.yml +29 -0
  4. mcp_gitlab_crunchtools-0.1.0/.github/workflows/security.yml +140 -0
  5. mcp_gitlab_crunchtools-0.1.0/.gitignore +90 -0
  6. mcp_gitlab_crunchtools-0.1.0/CLAUDE.md +153 -0
  7. mcp_gitlab_crunchtools-0.1.0/Containerfile +44 -0
  8. mcp_gitlab_crunchtools-0.1.0/LICENSE +661 -0
  9. mcp_gitlab_crunchtools-0.1.0/PKG-INFO +291 -0
  10. mcp_gitlab_crunchtools-0.1.0/README.md +265 -0
  11. mcp_gitlab_crunchtools-0.1.0/SECURITY.md +221 -0
  12. mcp_gitlab_crunchtools-0.1.0/pyproject.toml +75 -0
  13. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/__init__.py +60 -0
  14. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/__main__.py +6 -0
  15. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/client.py +239 -0
  16. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/config.py +133 -0
  17. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/errors.py +66 -0
  18. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/models.py +231 -0
  19. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/server.py +992 -0
  20. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/tools/__init__.py +87 -0
  21. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/tools/groups.py +119 -0
  22. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/tools/issues.py +254 -0
  23. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/tools/merge_requests.py +296 -0
  24. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/tools/pipelines.py +251 -0
  25. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/tools/projects.py +164 -0
  26. mcp_gitlab_crunchtools-0.1.0/src/mcp_gitlab_crunchtools/tools/search.py +89 -0
  27. mcp_gitlab_crunchtools-0.1.0/tests/__init__.py +1 -0
  28. mcp_gitlab_crunchtools-0.1.0/tests/test_tools.py +812 -0
  29. mcp_gitlab_crunchtools-0.1.0/tests/test_validation.py +232 -0
@@ -0,0 +1,53 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.10", "3.11", "3.12"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v4
21
+ with:
22
+ version: "latest"
23
+
24
+ - name: Set up Python ${{ matrix.python-version }}
25
+ run: uv python install ${{ matrix.python-version }}
26
+
27
+ - name: Install dependencies
28
+ run: uv sync --all-extras
29
+
30
+ - name: Run linter
31
+ run: uv run ruff check src tests
32
+
33
+ - name: Run type checker
34
+ run: uv run mypy src
35
+
36
+ - name: Run tests
37
+ run: uv run pytest -v
38
+ env:
39
+ GITLAB_TOKEN: "test_token_for_ci"
40
+
41
+ build-container:
42
+ runs-on: ubuntu-latest
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+
46
+ - name: Build container image
47
+ run: |
48
+ docker build -f Containerfile -t mcp-gitlab:test .
49
+
50
+ - name: Verify container
51
+ run: |
52
+ # Just verify it starts (will fail due to no token, but should start)
53
+ timeout 5 docker run --rm mcp-gitlab:test || true
@@ -0,0 +1,67 @@
1
+ name: Container Build & Push
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ tags: ["v*"]
7
+ pull_request:
8
+ branches: [main]
9
+ workflow_dispatch:
10
+
11
+ env:
12
+ REGISTRY: quay.io
13
+ IMAGE_NAME: crunchtools/mcp-gitlab
14
+
15
+ jobs:
16
+ build-and-push:
17
+ runs-on: ubuntu-latest
18
+ permissions:
19
+ contents: read
20
+ packages: write
21
+
22
+ steps:
23
+ - name: Checkout repository
24
+ uses: actions/checkout@v4
25
+
26
+ - name: Set up Docker Buildx
27
+ uses: docker/setup-buildx-action@v3
28
+
29
+ - name: Log in to Quay.io
30
+ if: github.event_name != 'pull_request'
31
+ uses: docker/login-action@v3
32
+ with:
33
+ registry: ${{ env.REGISTRY }}
34
+ username: ${{ secrets.QUAY_USERNAME }}
35
+ password: ${{ secrets.QUAY_PASSWORD }}
36
+
37
+ - name: Extract metadata (tags, labels)
38
+ id: meta
39
+ uses: docker/metadata-action@v5
40
+ with:
41
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
42
+ tags: |
43
+ type=ref,event=branch
44
+ type=ref,event=pr
45
+ type=semver,pattern={{version}}
46
+ type=semver,pattern={{major}}.{{minor}}
47
+ type=raw,value=latest,enable={{is_default_branch}}
48
+
49
+ - name: Build and push container image
50
+ uses: docker/build-push-action@v6
51
+ with:
52
+ context: .
53
+ file: ./Containerfile
54
+ push: ${{ github.event_name != 'pull_request' }}
55
+ tags: ${{ steps.meta.outputs.tags }}
56
+ labels: ${{ steps.meta.outputs.labels }}
57
+ cache-from: type=gha
58
+ cache-to: type=gha,mode=max
59
+
60
+ - name: Run Trivy vulnerability scanner
61
+ if: github.event_name != 'pull_request'
62
+ uses: aquasecurity/trivy-action@master
63
+ with:
64
+ image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
65
+ format: "table"
66
+ exit-code: "0"
67
+ severity: "CRITICAL,HIGH"
@@ -0,0 +1,29 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ id-token: write # Required for trusted publishing
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@v4
19
+ with:
20
+ version: "latest"
21
+
22
+ - name: Set up Python
23
+ run: uv python install 3.12
24
+
25
+ - name: Build package
26
+ run: uv build
27
+
28
+ - name: Publish to PyPI
29
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,140 @@
1
+ name: Security Scan
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ schedule:
9
+ # Run every Monday at 9 AM UTC
10
+ - cron: "0 9 * * 1"
11
+ workflow_dispatch:
12
+
13
+ permissions:
14
+ contents: read
15
+ issues: write
16
+ pull-requests: write
17
+ security-events: write
18
+
19
+ jobs:
20
+ dependency-audit:
21
+ name: Dependency CVE Scan
22
+ runs-on: ubuntu-latest
23
+
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+
27
+ - name: Install uv
28
+ uses: astral-sh/setup-uv@v4
29
+ with:
30
+ version: "latest"
31
+
32
+ - name: Set up Python
33
+ run: uv python install 3.12
34
+
35
+ - name: Install dependencies
36
+ run: uv sync
37
+
38
+ - name: Install pip-audit
39
+ run: uv pip install pip-audit
40
+
41
+ - name: Run pip-audit
42
+ id: audit
43
+ continue-on-error: true
44
+ run: |
45
+ uv run pip-audit --format=json --output=audit-results.json || true
46
+ uv run pip-audit --format=markdown --output=audit-results.md || true
47
+
48
+ # Check if there are vulnerabilities
49
+ if [ -f audit-results.json ]; then
50
+ VULN_COUNT=$(cat audit-results.json | python -c "import sys,json; data=json.load(sys.stdin); print(len([d for d in data if d.get('vulns', [])]))" 2>/dev/null || echo "0")
51
+ echo "vuln_count=$VULN_COUNT" >> $GITHUB_OUTPUT
52
+ else
53
+ echo "vuln_count=0" >> $GITHUB_OUTPUT
54
+ fi
55
+
56
+ - name: Upload audit results
57
+ if: always()
58
+ uses: actions/upload-artifact@v4
59
+ with:
60
+ name: security-audit-results
61
+ path: |
62
+ audit-results.json
63
+ audit-results.md
64
+ retention-days: 30
65
+
66
+ - name: Create issue for vulnerabilities
67
+ if: steps.audit.outputs.vuln_count != '0' && github.event_name == 'schedule'
68
+ uses: actions/github-script@v7
69
+ with:
70
+ script: |
71
+ const fs = require('fs');
72
+ let body = '## Security Vulnerabilities Detected\n\n';
73
+ body += 'The weekly security scan found vulnerabilities in project dependencies.\n\n';
74
+
75
+ if (fs.existsSync('audit-results.md')) {
76
+ body += fs.readFileSync('audit-results.md', 'utf8');
77
+ }
78
+
79
+ body += '\n\n### Action Required\n';
80
+ body += '1. Review the vulnerabilities listed above\n';
81
+ body += '2. Update affected dependencies\n';
82
+ body += '3. Run `uv sync` and test\n';
83
+ body += '4. Create a PR with the fixes\n';
84
+
85
+ await github.rest.issues.create({
86
+ owner: context.repo.owner,
87
+ repo: context.repo.repo,
88
+ title: `Security Alert: CVEs found in dependencies (${new Date().toISOString().split('T')[0]})`,
89
+ body: body,
90
+ labels: ['security', 'dependencies']
91
+ });
92
+
93
+ - name: Fail on vulnerabilities (PRs only)
94
+ if: steps.audit.outputs.vuln_count != '0' && github.event_name == 'pull_request'
95
+ run: |
96
+ echo "::error::Security vulnerabilities found in dependencies. See audit results."
97
+ exit 1
98
+
99
+ container-scan:
100
+ name: Container Security Scan
101
+ runs-on: ubuntu-latest
102
+
103
+ steps:
104
+ - uses: actions/checkout@v4
105
+
106
+ - name: Build container image
107
+ run: |
108
+ docker build -f Containerfile -t mcp-gitlab:scan .
109
+
110
+ - name: Run Trivy vulnerability scanner
111
+ uses: aquasecurity/trivy-action@master
112
+ with:
113
+ image-ref: "mcp-gitlab:scan"
114
+ format: "sarif"
115
+ output: "trivy-results.sarif"
116
+ severity: "CRITICAL,HIGH"
117
+
118
+ - name: Upload Trivy scan results
119
+ uses: github/codeql-action/upload-sarif@v3
120
+ if: always()
121
+ with:
122
+ sarif_file: "trivy-results.sarif"
123
+
124
+ codeql:
125
+ name: CodeQL Analysis
126
+ runs-on: ubuntu-latest
127
+
128
+ steps:
129
+ - uses: actions/checkout@v4
130
+
131
+ - name: Initialize CodeQL
132
+ uses: github/codeql-action/init@v3
133
+ with:
134
+ languages: python
135
+ queries: security-extended
136
+
137
+ - name: Perform CodeQL Analysis
138
+ uses: github/codeql-action/analyze@v3
139
+ with:
140
+ category: "/language:python"
@@ -0,0 +1,90 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Installer logs
34
+ pip-log.txt
35
+ pip-delete-this-directory.txt
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .nox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ *.py,cover
48
+ .hypothesis/
49
+ .pytest_cache/
50
+ cover/
51
+
52
+ # Translations
53
+ *.mo
54
+ *.pot
55
+
56
+ # Environments
57
+ .env
58
+ .venv
59
+ env/
60
+ venv/
61
+ ENV/
62
+ env.bak/
63
+ venv.bak/
64
+
65
+ # IDE
66
+ .idea/
67
+ .vscode/
68
+ *.swp
69
+ *.swo
70
+ *~
71
+
72
+ # mypy
73
+ .mypy_cache/
74
+ .dmypy.json
75
+ dmypy.json
76
+
77
+ # ruff
78
+ .ruff_cache/
79
+
80
+ # uv
81
+ .uv/
82
+ uv.lock
83
+
84
+ # Local development
85
+ .envrc
86
+ .direnv/
87
+
88
+ # OS files
89
+ .DS_Store
90
+ Thumbs.db
@@ -0,0 +1,153 @@
1
+ # Claude Code Instructions
2
+
3
+ This is a secure MCP server for GitLab projects, merge requests, issues, pipelines, and search. Works with any GitLab instance (gitlab.com, self-hosted, or enterprise).
4
+
5
+ ## Quick Start
6
+
7
+ ### Option 1: Using uvx (Recommended)
8
+
9
+ ```bash
10
+ claude mcp add mcp-gitlab-crunchtools \
11
+ --env GITLAB_TOKEN=your_token_here \
12
+ -- uvx mcp-gitlab-crunchtools
13
+ ```
14
+
15
+ ### Option 2: Using Container
16
+
17
+ ```bash
18
+ claude mcp add mcp-gitlab-crunchtools \
19
+ --env GITLAB_TOKEN=your_token_here \
20
+ -- podman run -i --rm -e GITLAB_TOKEN quay.io/crunchtools/mcp-gitlab
21
+ ```
22
+
23
+ ### Option 3: Self-Hosted GitLab
24
+
25
+ ```bash
26
+ claude mcp add mcp-gitlab-crunchtools \
27
+ --env GITLAB_TOKEN=your_token_here \
28
+ --env GITLAB_URL=https://gitlab.example.com \
29
+ -- uvx mcp-gitlab-crunchtools
30
+ ```
31
+
32
+ ### Option 4: Local Development
33
+
34
+ ```bash
35
+ cd ~/Projects/crunchtools/mcp-gitlab
36
+ claude mcp add mcp-gitlab-crunchtools \
37
+ --env GITLAB_TOKEN=your_token_here \
38
+ -- uv run mcp-gitlab-crunchtools
39
+ ```
40
+
41
+ ## Creating a GitLab Personal Access Token
42
+
43
+ ### Step-by-Step Instructions
44
+
45
+ 1. **Log in to your GitLab instance**
46
+ - Go to https://gitlab.com (or your self-hosted URL)
47
+ - Sign in with your account
48
+
49
+ 2. **Navigate to Access Tokens**
50
+ - Click your avatar (top left)
51
+ - Select "Preferences"
52
+ - Click "Access Tokens" in the left sidebar
53
+ - Or go directly to: https://gitlab.com/-/user_settings/personal_access_tokens
54
+
55
+ 3. **Create a new token**
56
+ - **Token name**: `mcp-gitlab-crunchtools`
57
+ - **Expiration date**: Set an appropriate expiry (recommended: 90 days)
58
+ - **Scopes**: Select the scopes you need (see below)
59
+
60
+ 4. **Copy Your Token**
61
+ - **IMPORTANT: Copy the token immediately!**
62
+ - The token starts with `glpat-` and is only shown once
63
+ - Store it securely (password manager recommended)
64
+
65
+ ### Scope Selection
66
+
67
+ #### Read-Only (safest)
68
+ - `read_api` — Read access to projects, issues, MRs, pipelines
69
+
70
+ #### Full Management (all MCP server features)
71
+ - `api` — Full API access for creating/updating issues, MRs, and notes
72
+
73
+ ### Security Best Practices
74
+
75
+ - **Principle of least privilege**: Use `read_api` if you only need to read
76
+ - **Set expiration**: Always set an expiry date on tokens
77
+ - **Rotate regularly**: Create new tokens periodically and revoke old ones
78
+ - **Never commit tokens**: Don't put tokens in code or config files in git
79
+
80
+ ## Environment Variables
81
+
82
+ | Variable | Required | Default | Description |
83
+ |----------|----------|---------|-------------|
84
+ | `GITLAB_TOKEN` | Yes | — | Personal Access Token (starts with `glpat-`) |
85
+ | `GITLAB_URL` | No | `https://gitlab.com` | GitLab instance URL |
86
+
87
+ ## Available Tools (27 tools)
88
+
89
+ ### Project Management (5 tools)
90
+ - `list_projects` - List projects with filtering and search
91
+ - `get_project` - Get project details by ID or path
92
+ - `list_project_branches` - List repository branches
93
+ - `get_project_branch` - Get a single branch
94
+ - `list_project_commits` - List commits with date/path filtering
95
+
96
+ ### Group Management (3 tools)
97
+ - `list_groups` - List groups with filtering
98
+ - `get_group` - Get group details by ID or path
99
+ - `list_group_projects` - List projects in a group (with subgroup support)
100
+
101
+ ### Merge Requests (7 tools)
102
+ - `list_merge_requests` - List MRs by state, labels, milestone
103
+ - `get_merge_request` - Get MR details
104
+ - `create_merge_request` - Create a new MR
105
+ - `update_merge_request` - Update MR title, description, state, assignees
106
+ - `list_mr_notes` - List comments on an MR
107
+ - `create_mr_note` - Add a comment to an MR
108
+ - `get_mr_changes` - Get the diff for an MR
109
+
110
+ ### Issues (6 tools)
111
+ - `list_issues` - List issues by state, labels, milestone, assignee
112
+ - `get_issue` - Get issue details
113
+ - `create_issue` - Create a new issue
114
+ - `update_issue` - Update issue title, description, state, labels
115
+ - `list_issue_notes` - List comments on an issue
116
+ - `create_issue_note` - Add a comment to an issue
117
+
118
+ ### Pipelines (4 tools)
119
+ - `list_pipelines` - List CI/CD pipelines with status filtering
120
+ - `get_pipeline` - Get pipeline details
121
+ - `list_pipeline_jobs` - List jobs in a pipeline
122
+ - `get_job_log` - Get job log output
123
+
124
+ ### Search (2 tools)
125
+ - `search_global` - Search across all accessible GitLab resources
126
+ - `search_project` - Search within a specific project
127
+
128
+ ## Example Usage
129
+
130
+ ```
131
+ User: List my GitLab projects
132
+ User: Show open merge requests for group/project
133
+ User: Create an issue in my-org/backend titled "Fix login timeout"
134
+ User: Get the diff for MR !42 in my-org/frontend
135
+ User: Show failed pipelines for my-org/api
136
+ User: Search for "authentication" in project my-org/backend
137
+ ```
138
+
139
+ ## Development
140
+
141
+ ```bash
142
+ # Install dependencies
143
+ uv sync --all-extras
144
+
145
+ # Run tests
146
+ uv run pytest
147
+
148
+ # Lint
149
+ uv run ruff check src tests
150
+
151
+ # Type check
152
+ uv run mypy src
153
+ ```
@@ -0,0 +1,44 @@
1
+ # MCP GitLab CrunchTools Container
2
+ # Built on Hummingbird Python image (Red Hat UBI-based) for enterprise security
3
+ #
4
+ # Build:
5
+ # podman build -t quay.io/crunchtools/mcp-gitlab .
6
+ #
7
+ # Run:
8
+ # podman run -e GITLAB_TOKEN=your_token quay.io/crunchtools/mcp-gitlab
9
+ #
10
+ # With Claude Code:
11
+ # claude mcp add mcp-gitlab-crunchtools \
12
+ # --env GITLAB_TOKEN=your_token \
13
+ # -- podman run -i --rm -e GITLAB_TOKEN quay.io/crunchtools/mcp-gitlab
14
+
15
+ # Use Hummingbird Python image (Red Hat UBI-based with Python pre-installed)
16
+ FROM quay.io/hummingbird/python:latest
17
+
18
+ # Labels for container metadata
19
+ LABEL name="mcp-gitlab-crunchtools" \
20
+ version="0.1.0" \
21
+ summary="Secure MCP server for GitLab projects, merge requests, issues, and pipelines" \
22
+ description="A security-focused MCP server for GitLab built on Red Hat UBI" \
23
+ maintainer="crunchtools.com" \
24
+ url="https://github.com/crunchtools/mcp-gitlab" \
25
+ io.k8s.display-name="MCP GitLab CrunchTools" \
26
+ io.openshift.tags="mcp,gitlab,devops"
27
+
28
+ # Set working directory
29
+ WORKDIR /app
30
+
31
+ # Copy project files
32
+ COPY pyproject.toml README.md ./
33
+ COPY src/ ./src/
34
+
35
+ # Install the package and dependencies
36
+ RUN pip install --no-cache-dir .
37
+
38
+ # Verify installation
39
+ RUN python -c "from mcp_gitlab_crunchtools import main; print('Installation verified')"
40
+
41
+ # Default: stdio transport (use -i with podman run)
42
+ # HTTP: --transport streamable-http (use -d -p 8015:8015 with podman run)
43
+ EXPOSE 8015
44
+ ENTRYPOINT ["python", "-m", "mcp_gitlab_crunchtools"]