commit-check-mcp 0.1.2__tar.gz → 0.1.4__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.
- commit_check_mcp-0.1.4/.github/dependabot.yml +23 -0
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/.github/workflows/main.yml +2 -2
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/.github/workflows/publish.yml +3 -3
- {commit_check_mcp-0.1.2/src/commit_check_mcp.egg-info → commit_check_mcp-0.1.4}/PKG-INFO +32 -8
- commit_check_mcp-0.1.2/PKG-INFO → commit_check_mcp-0.1.4/README.md +17 -20
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/pyproject.toml +17 -4
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/src/commit_check_mcp/server.py +58 -6
- commit_check_mcp-0.1.2/README.md → commit_check_mcp-0.1.4/src/commit_check_mcp.egg-info/PKG-INFO +44 -4
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/src/commit_check_mcp.egg-info/SOURCES.txt +2 -0
- commit_check_mcp-0.1.4/src/commit_check_mcp.egg-info/requires.txt +6 -0
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/tests/test_server.py +95 -1
- commit_check_mcp-0.1.4/uv.lock +1073 -0
- commit_check_mcp-0.1.2/src/commit_check_mcp.egg-info/requires.txt +0 -6
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/.github/workflows/labeler.yml +0 -0
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/.github/workflows/release-drafter.yml +0 -0
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/.gitignore +0 -0
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/LICENSE +0 -0
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/setup.cfg +0 -0
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/src/commit_check_mcp/__init__.py +0 -0
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/src/commit_check_mcp.egg-info/dependency_links.txt +0 -0
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/src/commit_check_mcp.egg-info/entry_points.txt +0 -0
- {commit_check_mcp-0.1.2 → commit_check_mcp-0.1.4}/src/commit_check_mcp.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# To get started with Dependabot version updates, you'll need to specify which
|
|
2
|
+
# package ecosystems to update and where the package manifests are located.
|
|
3
|
+
# Please see the documentation for all configuration options:
|
|
4
|
+
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
|
5
|
+
|
|
6
|
+
version: 2
|
|
7
|
+
updates:
|
|
8
|
+
- package-ecosystem: github-actions
|
|
9
|
+
directory: /
|
|
10
|
+
schedule:
|
|
11
|
+
interval: "monthly"
|
|
12
|
+
groups:
|
|
13
|
+
github-actions:
|
|
14
|
+
patterns:
|
|
15
|
+
- "*"
|
|
16
|
+
- package-ecosystem: pip
|
|
17
|
+
directory: /
|
|
18
|
+
schedule:
|
|
19
|
+
interval: "monthly"
|
|
20
|
+
groups:
|
|
21
|
+
pip:
|
|
22
|
+
patterns:
|
|
23
|
+
- "*"
|
|
@@ -39,7 +39,7 @@ jobs:
|
|
|
39
39
|
|
|
40
40
|
- name: Upload coverage reports to Codecov
|
|
41
41
|
if: matrix.python-version == '3.12'
|
|
42
|
-
uses: codecov/codecov-action@
|
|
42
|
+
uses: codecov/codecov-action@v6
|
|
43
43
|
with:
|
|
44
44
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
45
45
|
slug: commit-check/commit-check-mcp
|
|
@@ -65,7 +65,7 @@ jobs:
|
|
|
65
65
|
run: python -m twine check dist/*
|
|
66
66
|
|
|
67
67
|
- name: Upload distributions
|
|
68
|
-
uses: actions/upload-artifact@
|
|
68
|
+
uses: actions/upload-artifact@v7
|
|
69
69
|
with:
|
|
70
70
|
name: dist
|
|
71
71
|
path: dist/*
|
|
@@ -45,13 +45,13 @@ jobs:
|
|
|
45
45
|
commit-check-mcp --help
|
|
46
46
|
|
|
47
47
|
- name: Upload distributions
|
|
48
|
-
uses: actions/upload-artifact@
|
|
48
|
+
uses: actions/upload-artifact@v7
|
|
49
49
|
with:
|
|
50
50
|
name: python-package-distributions
|
|
51
51
|
path: dist/*
|
|
52
52
|
|
|
53
53
|
- name: Create attestations
|
|
54
|
-
uses: actions/attest-build-provenance@
|
|
54
|
+
uses: actions/attest-build-provenance@v4
|
|
55
55
|
with:
|
|
56
56
|
subject-path: dist/*
|
|
57
57
|
|
|
@@ -65,7 +65,7 @@ jobs:
|
|
|
65
65
|
id-token: write
|
|
66
66
|
steps:
|
|
67
67
|
- name: Download distributions
|
|
68
|
-
uses: actions/download-artifact@
|
|
68
|
+
uses: actions/download-artifact@v8
|
|
69
69
|
with:
|
|
70
70
|
name: python-package-distributions
|
|
71
71
|
path: dist
|
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: commit-check-mcp
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: MCP server exposing commit-check validation tools
|
|
5
|
-
Author:
|
|
5
|
+
Author-email: Xianpeng Shen <xianpeng.shen@gmail.com>
|
|
6
6
|
License: MIT
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Topic :: Software Development
|
|
7
18
|
Requires-Python: >=3.10
|
|
8
19
|
Description-Content-Type: text/markdown
|
|
9
20
|
License-File: LICENSE
|
|
10
|
-
Requires-Dist: commit-check<3,>=2.
|
|
21
|
+
Requires-Dist: commit-check<3,>=2.7.0
|
|
11
22
|
Requires-Dist: mcp<2,>=1.27.0
|
|
12
23
|
Provides-Extra: dev
|
|
13
24
|
Requires-Dist: pytest<10,>=9.0.0; extra == "dev"
|
|
14
|
-
Requires-Dist: pytest-cov<
|
|
25
|
+
Requires-Dist: pytest-cov<8,>=6.0.0; extra == "dev"
|
|
15
26
|
Dynamic: license-file
|
|
16
27
|
|
|
17
28
|
# commit-check-mcp
|
|
@@ -24,7 +35,7 @@ Dynamic: license-file
|
|
|
24
35
|
|
|
25
36
|
Model Context Protocol (MCP) server for [commit-check](https://github.com/commit-check/commit-check).
|
|
26
37
|
|
|
27
|
-
`commit-check-mcp` exposes `commit-check` as local MCP tools so an MCP client can validate commit messages, branch names, author info, and repository state.
|
|
38
|
+
`commit-check-mcp` exposes `commit-check` as local MCP tools so an MCP client can validate commit messages, branch names, author info, push safety, and repository state.
|
|
28
39
|
|
|
29
40
|
## Features
|
|
30
41
|
|
|
@@ -33,9 +44,10 @@ This MCP server exposes commit-check validations as MCP tools:
|
|
|
33
44
|
- `server_health` — returns server/sdk versions
|
|
34
45
|
- `validate_commit_message` — validates a commit message
|
|
35
46
|
- `validate_branch_name` — validates a branch name or the current repo branch
|
|
47
|
+
- `validate_push_safety` — validates that a push is not a force push
|
|
36
48
|
- `validate_author_info` — validates author name/email or the repo's git author config
|
|
37
49
|
- `validate_commit_context` — runs combined checks in one call
|
|
38
|
-
- `validate_repository_state` — validates latest commit, current branch,
|
|
50
|
+
- `validate_repository_state` — validates latest commit, current branch, author state, and optional push safety for a repo
|
|
39
51
|
- `describe_validation_rules` — returns the effective config and enabled rules after merging defaults and repo config
|
|
40
52
|
|
|
41
53
|
All validation tools return the same structured commit-check result shape:
|
|
@@ -122,9 +134,10 @@ After the client starts the server, it will expose these tools:
|
|
|
122
134
|
- `server_health`: returns server, SDK, and dependency versions
|
|
123
135
|
- `validate_commit_message(message, config?, repo_path?, config_path?)`
|
|
124
136
|
- `validate_branch_name(branch?, config?, repo_path?, config_path?)`
|
|
137
|
+
- `validate_push_safety(push_refs?, config?, repo_path?, config_path?)`
|
|
125
138
|
- `validate_author_info(author_name?, author_email?, config?, repo_path?, config_path?)`
|
|
126
139
|
- `validate_commit_context(message?, branch?, author_name?, author_email?, config?, repo_path?, config_path?)`
|
|
127
|
-
- `validate_repository_state(repo_path?, config?, config_path?, include_message?, include_branch?, include_author?)`
|
|
140
|
+
- `validate_repository_state(repo_path?, config?, config_path?, include_message?, include_branch?, include_author?, include_push?)`
|
|
128
141
|
- `describe_validation_rules(config?, repo_path?, config_path?)`
|
|
129
142
|
|
|
130
143
|
The common optional arguments are:
|
|
@@ -164,6 +177,15 @@ Validate the full repository state:
|
|
|
164
177
|
}
|
|
165
178
|
```
|
|
166
179
|
|
|
180
|
+
Validate push safety from git pre-push hook ref metadata:
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"repo_path": "/path/to/repo",
|
|
185
|
+
"push_refs": "refs/heads/main abc123 refs/heads/main def456"
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
167
189
|
Inspect the final merged rules that will be applied:
|
|
168
190
|
|
|
169
191
|
```json
|
|
@@ -189,6 +211,7 @@ Typical patterns:
|
|
|
189
211
|
|
|
190
212
|
- Validate an explicit message with a repository's rules
|
|
191
213
|
- Validate the current repository state without passing message/branch/author values manually
|
|
214
|
+
- Validate push safety using pre-push ref metadata, or check the current branch against its upstream
|
|
192
215
|
- Inspect which rules are actually enabled after config merging
|
|
193
216
|
|
|
194
217
|
Example payload for a repository-wide validation:
|
|
@@ -198,7 +221,8 @@ Example payload for a repository-wide validation:
|
|
|
198
221
|
"repo_path": "/path/to/repo",
|
|
199
222
|
"include_message": true,
|
|
200
223
|
"include_branch": true,
|
|
201
|
-
"include_author": true
|
|
224
|
+
"include_author": true,
|
|
225
|
+
"include_push": true
|
|
202
226
|
}
|
|
203
227
|
```
|
|
204
228
|
|
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: commit-check-mcp
|
|
3
|
-
Version: 0.1.2
|
|
4
|
-
Summary: MCP server exposing commit-check validation tools
|
|
5
|
-
Author: commit-check
|
|
6
|
-
License: MIT
|
|
7
|
-
Requires-Python: >=3.10
|
|
8
|
-
Description-Content-Type: text/markdown
|
|
9
|
-
License-File: LICENSE
|
|
10
|
-
Requires-Dist: commit-check<3,>=2.5.0
|
|
11
|
-
Requires-Dist: mcp<2,>=1.27.0
|
|
12
|
-
Provides-Extra: dev
|
|
13
|
-
Requires-Dist: pytest<10,>=9.0.0; extra == "dev"
|
|
14
|
-
Requires-Dist: pytest-cov<7,>=6.0.0; extra == "dev"
|
|
15
|
-
Dynamic: license-file
|
|
16
|
-
|
|
17
1
|
# commit-check-mcp
|
|
18
2
|
|
|
19
3
|
[](https://pypi.org/project/commit-check-mcp/)
|
|
@@ -24,7 +8,7 @@ Dynamic: license-file
|
|
|
24
8
|
|
|
25
9
|
Model Context Protocol (MCP) server for [commit-check](https://github.com/commit-check/commit-check).
|
|
26
10
|
|
|
27
|
-
`commit-check-mcp` exposes `commit-check` as local MCP tools so an MCP client can validate commit messages, branch names, author info, and repository state.
|
|
11
|
+
`commit-check-mcp` exposes `commit-check` as local MCP tools so an MCP client can validate commit messages, branch names, author info, push safety, and repository state.
|
|
28
12
|
|
|
29
13
|
## Features
|
|
30
14
|
|
|
@@ -33,9 +17,10 @@ This MCP server exposes commit-check validations as MCP tools:
|
|
|
33
17
|
- `server_health` — returns server/sdk versions
|
|
34
18
|
- `validate_commit_message` — validates a commit message
|
|
35
19
|
- `validate_branch_name` — validates a branch name or the current repo branch
|
|
20
|
+
- `validate_push_safety` — validates that a push is not a force push
|
|
36
21
|
- `validate_author_info` — validates author name/email or the repo's git author config
|
|
37
22
|
- `validate_commit_context` — runs combined checks in one call
|
|
38
|
-
- `validate_repository_state` — validates latest commit, current branch,
|
|
23
|
+
- `validate_repository_state` — validates latest commit, current branch, author state, and optional push safety for a repo
|
|
39
24
|
- `describe_validation_rules` — returns the effective config and enabled rules after merging defaults and repo config
|
|
40
25
|
|
|
41
26
|
All validation tools return the same structured commit-check result shape:
|
|
@@ -122,9 +107,10 @@ After the client starts the server, it will expose these tools:
|
|
|
122
107
|
- `server_health`: returns server, SDK, and dependency versions
|
|
123
108
|
- `validate_commit_message(message, config?, repo_path?, config_path?)`
|
|
124
109
|
- `validate_branch_name(branch?, config?, repo_path?, config_path?)`
|
|
110
|
+
- `validate_push_safety(push_refs?, config?, repo_path?, config_path?)`
|
|
125
111
|
- `validate_author_info(author_name?, author_email?, config?, repo_path?, config_path?)`
|
|
126
112
|
- `validate_commit_context(message?, branch?, author_name?, author_email?, config?, repo_path?, config_path?)`
|
|
127
|
-
- `validate_repository_state(repo_path?, config?, config_path?, include_message?, include_branch?, include_author?)`
|
|
113
|
+
- `validate_repository_state(repo_path?, config?, config_path?, include_message?, include_branch?, include_author?, include_push?)`
|
|
128
114
|
- `describe_validation_rules(config?, repo_path?, config_path?)`
|
|
129
115
|
|
|
130
116
|
The common optional arguments are:
|
|
@@ -164,6 +150,15 @@ Validate the full repository state:
|
|
|
164
150
|
}
|
|
165
151
|
```
|
|
166
152
|
|
|
153
|
+
Validate push safety from git pre-push hook ref metadata:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"repo_path": "/path/to/repo",
|
|
158
|
+
"push_refs": "refs/heads/main abc123 refs/heads/main def456"
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
167
162
|
Inspect the final merged rules that will be applied:
|
|
168
163
|
|
|
169
164
|
```json
|
|
@@ -189,6 +184,7 @@ Typical patterns:
|
|
|
189
184
|
|
|
190
185
|
- Validate an explicit message with a repository's rules
|
|
191
186
|
- Validate the current repository state without passing message/branch/author values manually
|
|
187
|
+
- Validate push safety using pre-push ref metadata, or check the current branch against its upstream
|
|
192
188
|
- Inspect which rules are actually enabled after config merging
|
|
193
189
|
|
|
194
190
|
Example payload for a repository-wide validation:
|
|
@@ -198,7 +194,8 @@ Example payload for a repository-wide validation:
|
|
|
198
194
|
"repo_path": "/path/to/repo",
|
|
199
195
|
"include_message": true,
|
|
200
196
|
"include_branch": true,
|
|
201
|
-
"include_author": true
|
|
197
|
+
"include_author": true,
|
|
198
|
+
"include_push": true
|
|
202
199
|
}
|
|
203
200
|
```
|
|
204
201
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["setuptools>=77", "setuptools-scm"
|
|
2
|
+
requires = ["setuptools>=77", "setuptools-scm"]
|
|
3
3
|
build-backend = "setuptools.build_meta"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
@@ -9,10 +9,23 @@ readme = "README.md"
|
|
|
9
9
|
requires-python = ">=3.10"
|
|
10
10
|
license = { text = "MIT" }
|
|
11
11
|
authors = [
|
|
12
|
-
{ name = "
|
|
12
|
+
{ name = "Xianpeng Shen", email = "xianpeng.shen@gmail.com" }
|
|
13
|
+
]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Programming Language :: Python :: 3.14",
|
|
25
|
+
"Topic :: Software Development",
|
|
13
26
|
]
|
|
14
27
|
dependencies = [
|
|
15
|
-
"commit-check>=2.
|
|
28
|
+
"commit-check>=2.7.0,<3",
|
|
16
29
|
"mcp>=1.27.0,<2"
|
|
17
30
|
]
|
|
18
31
|
dynamic = ["version"]
|
|
@@ -20,7 +33,7 @@ dynamic = ["version"]
|
|
|
20
33
|
[project.optional-dependencies]
|
|
21
34
|
dev = [
|
|
22
35
|
"pytest>=9.0.0,<10",
|
|
23
|
-
"pytest-cov>=6.0.0,<
|
|
36
|
+
"pytest-cov>=6.0.0,<8"
|
|
24
37
|
]
|
|
25
38
|
|
|
26
39
|
[project.scripts]
|
|
@@ -14,7 +14,7 @@ from commit_check import __version__ as commit_check_version
|
|
|
14
14
|
from commit_check.config_merger import deep_merge, get_default_config, load_toml_config
|
|
15
15
|
from commit_check.engine import ValidationContext, ValidationEngine, ValidationResult
|
|
16
16
|
from commit_check.rule_builder import RuleBuilder, ValidationRule
|
|
17
|
-
from commit_check.rules_catalog import BRANCH_RULES, COMMIT_RULES
|
|
17
|
+
from commit_check.rules_catalog import BRANCH_RULES, COMMIT_RULES, PUSH_RULES
|
|
18
18
|
from mcp.server.fastmcp import FastMCP
|
|
19
19
|
|
|
20
20
|
from . import __version__
|
|
@@ -22,8 +22,8 @@ from . import __version__
|
|
|
22
22
|
mcp = FastMCP(
|
|
23
23
|
"commit-check-mcp",
|
|
24
24
|
instructions=(
|
|
25
|
-
"Use these tools to validate commit messages, branch names,
|
|
26
|
-
"with commit-check."
|
|
25
|
+
"Use these tools to validate commit messages, branch names, author metadata, "
|
|
26
|
+
"and push safety with commit-check."
|
|
27
27
|
),
|
|
28
28
|
)
|
|
29
29
|
|
|
@@ -185,6 +185,28 @@ def _validate_branch(
|
|
|
185
185
|
)
|
|
186
186
|
|
|
187
187
|
|
|
188
|
+
def _validate_push(
|
|
189
|
+
push_refs: str | None = None,
|
|
190
|
+
*,
|
|
191
|
+
config: dict[str, Any] | None = None,
|
|
192
|
+
repo_path: Path | None = None,
|
|
193
|
+
config_path: str | None = None,
|
|
194
|
+
) -> dict[str, Any]:
|
|
195
|
+
"""Validate push ref updates against commit-check force-push protection."""
|
|
196
|
+
cfg = _merge_config(config, repo_path=repo_path, config_path=config_path)
|
|
197
|
+
cfg.setdefault("push", {})["allow_force_push"] = False
|
|
198
|
+
with _working_directory(repo_path):
|
|
199
|
+
return _run_checks(
|
|
200
|
+
["no_force_push"],
|
|
201
|
+
ValidationContext(
|
|
202
|
+
stdin_text=push_refs,
|
|
203
|
+
config=cfg,
|
|
204
|
+
push_upstream_fallback=push_refs is None,
|
|
205
|
+
),
|
|
206
|
+
cfg,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
188
210
|
def _validate_author(
|
|
189
211
|
name: str | None = None,
|
|
190
212
|
email: str | None = None,
|
|
@@ -373,6 +395,24 @@ def validate_author_info(
|
|
|
373
395
|
)
|
|
374
396
|
|
|
375
397
|
|
|
398
|
+
@mcp.tool()
|
|
399
|
+
def validate_push_safety(
|
|
400
|
+
push_refs: str | None = None,
|
|
401
|
+
config: dict[str, Any] | None = None,
|
|
402
|
+
repo_path: str | None = None,
|
|
403
|
+
config_path: str | None = None,
|
|
404
|
+
) -> dict[str, Any]:
|
|
405
|
+
"""Validate that a push is not a force push."""
|
|
406
|
+
normalized_push_refs = push_refs.strip() if isinstance(push_refs, str) else None
|
|
407
|
+
normalized_repo_path = _normalize_repo_path(repo_path)
|
|
408
|
+
return _validate_push(
|
|
409
|
+
normalized_push_refs,
|
|
410
|
+
config=_normalize_config(config),
|
|
411
|
+
repo_path=normalized_repo_path,
|
|
412
|
+
config_path=_normalize_config_path(config_path, normalized_repo_path),
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
|
|
376
416
|
@mcp.tool()
|
|
377
417
|
def validate_commit_context(
|
|
378
418
|
message: str | None = None,
|
|
@@ -423,9 +463,10 @@ def validate_repository_state(
|
|
|
423
463
|
include_message: bool = True,
|
|
424
464
|
include_branch: bool = True,
|
|
425
465
|
include_author: bool = True,
|
|
466
|
+
include_push: bool = False,
|
|
426
467
|
) -> dict[str, Any]:
|
|
427
|
-
"""Validate the latest commit,
|
|
428
|
-
if not any([include_message, include_branch, include_author]):
|
|
468
|
+
"""Validate the latest commit, branch, author, and optional push safety state."""
|
|
469
|
+
if not any([include_message, include_branch, include_author, include_push]):
|
|
429
470
|
raise ValueError("At least one validation target must be enabled")
|
|
430
471
|
|
|
431
472
|
normalized_repo_path = _normalize_repo_path(repo_path)
|
|
@@ -461,6 +502,15 @@ def validate_repository_state(
|
|
|
461
502
|
config_path=normalized_config_path,
|
|
462
503
|
)["checks"]
|
|
463
504
|
)
|
|
505
|
+
if include_push:
|
|
506
|
+
checks.extend(
|
|
507
|
+
_validate_push(
|
|
508
|
+
None,
|
|
509
|
+
config=normalized_config,
|
|
510
|
+
repo_path=normalized_repo_path,
|
|
511
|
+
config_path=normalized_config_path,
|
|
512
|
+
)["checks"]
|
|
513
|
+
)
|
|
464
514
|
|
|
465
515
|
return {
|
|
466
516
|
"status": "fail" if any(c["status"] == "fail" for c in checks) else "pass",
|
|
@@ -489,7 +539,9 @@ def describe_validation_rules(
|
|
|
489
539
|
"commit_check_version": commit_check_version,
|
|
490
540
|
"config": merged_config,
|
|
491
541
|
"supported_checks": list(
|
|
492
|
-
dict.fromkeys(
|
|
542
|
+
dict.fromkeys(
|
|
543
|
+
entry.check for entry in COMMIT_RULES + BRANCH_RULES + PUSH_RULES
|
|
544
|
+
)
|
|
493
545
|
),
|
|
494
546
|
"enabled_rules": rules,
|
|
495
547
|
}
|
commit_check_mcp-0.1.2/README.md → commit_check_mcp-0.1.4/src/commit_check_mcp.egg-info/PKG-INFO
RENAMED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: commit-check-mcp
|
|
3
|
+
Version: 0.1.4
|
|
4
|
+
Summary: MCP server exposing commit-check validation tools
|
|
5
|
+
Author-email: Xianpeng Shen <xianpeng.shen@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Topic :: Software Development
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: commit-check<3,>=2.7.0
|
|
22
|
+
Requires-Dist: mcp<2,>=1.27.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest<10,>=9.0.0; extra == "dev"
|
|
25
|
+
Requires-Dist: pytest-cov<8,>=6.0.0; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
1
28
|
# commit-check-mcp
|
|
2
29
|
|
|
3
30
|
[](https://pypi.org/project/commit-check-mcp/)
|
|
@@ -8,7 +35,7 @@
|
|
|
8
35
|
|
|
9
36
|
Model Context Protocol (MCP) server for [commit-check](https://github.com/commit-check/commit-check).
|
|
10
37
|
|
|
11
|
-
`commit-check-mcp` exposes `commit-check` as local MCP tools so an MCP client can validate commit messages, branch names, author info, and repository state.
|
|
38
|
+
`commit-check-mcp` exposes `commit-check` as local MCP tools so an MCP client can validate commit messages, branch names, author info, push safety, and repository state.
|
|
12
39
|
|
|
13
40
|
## Features
|
|
14
41
|
|
|
@@ -17,9 +44,10 @@ This MCP server exposes commit-check validations as MCP tools:
|
|
|
17
44
|
- `server_health` — returns server/sdk versions
|
|
18
45
|
- `validate_commit_message` — validates a commit message
|
|
19
46
|
- `validate_branch_name` — validates a branch name or the current repo branch
|
|
47
|
+
- `validate_push_safety` — validates that a push is not a force push
|
|
20
48
|
- `validate_author_info` — validates author name/email or the repo's git author config
|
|
21
49
|
- `validate_commit_context` — runs combined checks in one call
|
|
22
|
-
- `validate_repository_state` — validates latest commit, current branch,
|
|
50
|
+
- `validate_repository_state` — validates latest commit, current branch, author state, and optional push safety for a repo
|
|
23
51
|
- `describe_validation_rules` — returns the effective config and enabled rules after merging defaults and repo config
|
|
24
52
|
|
|
25
53
|
All validation tools return the same structured commit-check result shape:
|
|
@@ -106,9 +134,10 @@ After the client starts the server, it will expose these tools:
|
|
|
106
134
|
- `server_health`: returns server, SDK, and dependency versions
|
|
107
135
|
- `validate_commit_message(message, config?, repo_path?, config_path?)`
|
|
108
136
|
- `validate_branch_name(branch?, config?, repo_path?, config_path?)`
|
|
137
|
+
- `validate_push_safety(push_refs?, config?, repo_path?, config_path?)`
|
|
109
138
|
- `validate_author_info(author_name?, author_email?, config?, repo_path?, config_path?)`
|
|
110
139
|
- `validate_commit_context(message?, branch?, author_name?, author_email?, config?, repo_path?, config_path?)`
|
|
111
|
-
- `validate_repository_state(repo_path?, config?, config_path?, include_message?, include_branch?, include_author?)`
|
|
140
|
+
- `validate_repository_state(repo_path?, config?, config_path?, include_message?, include_branch?, include_author?, include_push?)`
|
|
112
141
|
- `describe_validation_rules(config?, repo_path?, config_path?)`
|
|
113
142
|
|
|
114
143
|
The common optional arguments are:
|
|
@@ -148,6 +177,15 @@ Validate the full repository state:
|
|
|
148
177
|
}
|
|
149
178
|
```
|
|
150
179
|
|
|
180
|
+
Validate push safety from git pre-push hook ref metadata:
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"repo_path": "/path/to/repo",
|
|
185
|
+
"push_refs": "refs/heads/main abc123 refs/heads/main def456"
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
151
189
|
Inspect the final merged rules that will be applied:
|
|
152
190
|
|
|
153
191
|
```json
|
|
@@ -173,6 +211,7 @@ Typical patterns:
|
|
|
173
211
|
|
|
174
212
|
- Validate an explicit message with a repository's rules
|
|
175
213
|
- Validate the current repository state without passing message/branch/author values manually
|
|
214
|
+
- Validate push safety using pre-push ref metadata, or check the current branch against its upstream
|
|
176
215
|
- Inspect which rules are actually enabled after config merging
|
|
177
216
|
|
|
178
217
|
Example payload for a repository-wide validation:
|
|
@@ -182,7 +221,8 @@ Example payload for a repository-wide validation:
|
|
|
182
221
|
"repo_path": "/path/to/repo",
|
|
183
222
|
"include_message": true,
|
|
184
223
|
"include_branch": true,
|
|
185
|
-
"include_author": true
|
|
224
|
+
"include_author": true,
|
|
225
|
+
"include_push": true
|
|
186
226
|
}
|
|
187
227
|
```
|
|
188
228
|
|
|
@@ -50,6 +50,83 @@ def test_validate_commit_context_requires_at_least_one_field() -> None:
|
|
|
50
50
|
server.validate_commit_context()
|
|
51
51
|
|
|
52
52
|
|
|
53
|
+
def test_validate_push_safety_forwards_normalized_values(
|
|
54
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
55
|
+
) -> None:
|
|
56
|
+
captured: dict[str, object] = {}
|
|
57
|
+
|
|
58
|
+
def fake_validate_push(
|
|
59
|
+
push_refs: str | None,
|
|
60
|
+
*,
|
|
61
|
+
config: dict | None,
|
|
62
|
+
repo_path: Path | None,
|
|
63
|
+
config_path: str | None,
|
|
64
|
+
):
|
|
65
|
+
captured["push_refs"] = push_refs
|
|
66
|
+
captured["config"] = config
|
|
67
|
+
captured["repo_path"] = repo_path
|
|
68
|
+
captured["config_path"] = config_path
|
|
69
|
+
return {"status": "pass", "checks": []}
|
|
70
|
+
|
|
71
|
+
monkeypatch.setattr(server, "_validate_push", fake_validate_push)
|
|
72
|
+
|
|
73
|
+
result = server.validate_push_safety(
|
|
74
|
+
" refs/heads/main abc refs/heads/main def ",
|
|
75
|
+
{"push": {"allow_force_push": True}},
|
|
76
|
+
repo_path=".",
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
assert result["status"] == "pass"
|
|
80
|
+
assert captured == {
|
|
81
|
+
"push_refs": "refs/heads/main abc refs/heads/main def",
|
|
82
|
+
"config": {"push": {"allow_force_push": True}},
|
|
83
|
+
"repo_path": Path.cwd().resolve(),
|
|
84
|
+
"config_path": None,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_validate_push_forces_no_force_push_rule(
|
|
89
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
90
|
+
) -> None:
|
|
91
|
+
captured: list[dict[str, object]] = []
|
|
92
|
+
|
|
93
|
+
def fake_run_checks(check_names, context, config):
|
|
94
|
+
captured.append(
|
|
95
|
+
{
|
|
96
|
+
"check_names": check_names,
|
|
97
|
+
"stdin_text": context.stdin_text,
|
|
98
|
+
"push_upstream_fallback": context.push_upstream_fallback,
|
|
99
|
+
"allow_force_push": config["push"]["allow_force_push"],
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
return {"status": "pass", "checks": []}
|
|
103
|
+
|
|
104
|
+
monkeypatch.setattr(server, "_run_checks", fake_run_checks)
|
|
105
|
+
|
|
106
|
+
result = server._validate_push(None, config={"push": {"allow_force_push": True}})
|
|
107
|
+
empty_refs_result = server._validate_push(
|
|
108
|
+
"",
|
|
109
|
+
config={"push": {"allow_force_push": True}},
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
assert result["status"] == "pass"
|
|
113
|
+
assert empty_refs_result["status"] == "pass"
|
|
114
|
+
assert captured == [
|
|
115
|
+
{
|
|
116
|
+
"check_names": ["no_force_push"],
|
|
117
|
+
"stdin_text": None,
|
|
118
|
+
"push_upstream_fallback": True,
|
|
119
|
+
"allow_force_push": False,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"check_names": ["no_force_push"],
|
|
123
|
+
"stdin_text": "",
|
|
124
|
+
"push_upstream_fallback": False,
|
|
125
|
+
"allow_force_push": False,
|
|
126
|
+
},
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
|
|
53
130
|
def test_validate_author_info_forwards_normalized_values(
|
|
54
131
|
monkeypatch: pytest.MonkeyPatch,
|
|
55
132
|
) -> None:
|
|
@@ -132,6 +209,7 @@ def test_validate_repository_state_requires_one_enabled_target() -> None:
|
|
|
132
209
|
include_message=False,
|
|
133
210
|
include_branch=False,
|
|
134
211
|
include_author=False,
|
|
212
|
+
include_push=False,
|
|
135
213
|
)
|
|
136
214
|
|
|
137
215
|
|
|
@@ -158,16 +236,31 @@ def test_validate_repository_state_combines_requested_checks(
|
|
|
158
236
|
assert branch is None
|
|
159
237
|
return {"status": "pass", "checks": [{"check": "branch", "status": "pass"}]}
|
|
160
238
|
|
|
239
|
+
def fake_validate_push(
|
|
240
|
+
push_refs: str | None,
|
|
241
|
+
*,
|
|
242
|
+
config: dict | None,
|
|
243
|
+
repo_path: Path | None,
|
|
244
|
+
config_path: str | None,
|
|
245
|
+
):
|
|
246
|
+
assert push_refs is None
|
|
247
|
+
return {
|
|
248
|
+
"status": "pass",
|
|
249
|
+
"checks": [{"check": "no_force_push", "status": "pass"}],
|
|
250
|
+
}
|
|
251
|
+
|
|
161
252
|
monkeypatch.setattr(server, "_validate_message", fake_validate_message)
|
|
162
253
|
monkeypatch.setattr(server, "_validate_branch", fake_validate_branch)
|
|
254
|
+
monkeypatch.setattr(server, "_validate_push", fake_validate_push)
|
|
163
255
|
|
|
164
|
-
result = server.validate_repository_state(include_author=False)
|
|
256
|
+
result = server.validate_repository_state(include_author=False, include_push=True)
|
|
165
257
|
|
|
166
258
|
assert result == {
|
|
167
259
|
"status": "pass",
|
|
168
260
|
"checks": [
|
|
169
261
|
{"check": "message", "status": "pass"},
|
|
170
262
|
{"check": "branch", "status": "pass"},
|
|
263
|
+
{"check": "no_force_push", "status": "pass"},
|
|
171
264
|
],
|
|
172
265
|
}
|
|
173
266
|
|
|
@@ -192,5 +285,6 @@ allow_branch_names = ["develop"]
|
|
|
192
285
|
assert result["config"]["commit"]["require_body"] is True
|
|
193
286
|
assert result["config"]["branch"]["allow_branch_names"] == ["develop"]
|
|
194
287
|
assert "message" in result["supported_checks"]
|
|
288
|
+
assert "no_force_push" in result["supported_checks"]
|
|
195
289
|
assert result["supported_checks"].count("ignore_authors") == 1
|
|
196
290
|
assert any(rule["check"] == "require_body" for rule in result["enabled_rules"])
|