commit-check-mcp 0.1.1.post1.dev1__py3-none-any.whl

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.
@@ -0,0 +1,6 @@
1
+ """commit-check-mcp package."""
2
+
3
+ from importlib.metadata import version
4
+
5
+ __all__ = ["__version__"]
6
+ __version__ = version("commit-check-mcp")
@@ -0,0 +1,504 @@
1
+ """MCP server for commit-check validations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from contextlib import contextmanager
6
+ from contextlib import redirect_stderr, redirect_stdout
7
+ from importlib.metadata import version
8
+ import io
9
+ from pathlib import Path
10
+ import os
11
+ from typing import Any
12
+
13
+ from commit_check import __version__ as commit_check_version
14
+ from commit_check.config_merger import deep_merge, get_default_config, load_toml_config
15
+ from commit_check.engine import ValidationContext, ValidationEngine, ValidationResult
16
+ from commit_check.rule_builder import RuleBuilder, ValidationRule
17
+ from commit_check.rules_catalog import BRANCH_RULES, COMMIT_RULES
18
+ from mcp.server.fastmcp import FastMCP
19
+
20
+ from . import __version__
21
+
22
+ mcp = FastMCP(
23
+ "commit-check-mcp",
24
+ instructions=(
25
+ "Use these tools to validate commit messages, branch names, and author metadata "
26
+ "with commit-check."
27
+ ),
28
+ )
29
+
30
+
31
+ def _normalize_config(config: dict[str, Any] | None) -> dict[str, Any] | None:
32
+ """Ensure tool config input is JSON-object-like."""
33
+ if config is None:
34
+ return None
35
+ if not isinstance(config, dict):
36
+ raise ValueError("config must be an object/dictionary when provided")
37
+ return config
38
+
39
+
40
+ def _normalize_repo_path(repo_path: str | None) -> Path | None:
41
+ """Normalize and validate an optional repository path."""
42
+ if repo_path is None:
43
+ return None
44
+ if not isinstance(repo_path, str):
45
+ raise ValueError("repo_path must be a string when provided")
46
+ normalized = repo_path.strip()
47
+ if not normalized:
48
+ raise ValueError("repo_path cannot be empty when provided")
49
+
50
+ path = Path(normalized).expanduser().resolve()
51
+ if not path.exists():
52
+ raise ValueError(f"repo_path does not exist: {path}")
53
+ if not path.is_dir():
54
+ raise ValueError(f"repo_path must be a directory: {path}")
55
+ return path
56
+
57
+
58
+ def _normalize_config_path(config_path: str | None, repo_path: Path | None) -> str | None:
59
+ """Normalize and validate an optional config path."""
60
+ if config_path is None:
61
+ return None
62
+ if not isinstance(config_path, str):
63
+ raise ValueError("config_path must be a string when provided")
64
+ normalized = config_path.strip()
65
+ if not normalized:
66
+ raise ValueError("config_path cannot be empty when provided")
67
+
68
+ path = Path(normalized).expanduser()
69
+ if not path.is_absolute() and repo_path is not None:
70
+ path = repo_path / path
71
+
72
+ resolved = path.resolve()
73
+ if not resolved.exists():
74
+ raise ValueError(f"config_path does not exist: {resolved}")
75
+ if not resolved.is_file():
76
+ raise ValueError(f"config_path must be a file: {resolved}")
77
+ return str(resolved)
78
+
79
+
80
+ @contextmanager
81
+ def _working_directory(repo_path: Path | None):
82
+ """Temporarily switch working directory for repo-relative config and git checks."""
83
+ if repo_path is None:
84
+ yield
85
+ return
86
+
87
+ original_cwd = Path.cwd()
88
+ os.chdir(repo_path)
89
+ try:
90
+ yield
91
+ finally:
92
+ os.chdir(original_cwd)
93
+
94
+
95
+ def _merge_config(
96
+ config: dict[str, Any] | None,
97
+ *,
98
+ repo_path: Path | None = None,
99
+ config_path: str | None = None,
100
+ ) -> dict[str, Any]:
101
+ """Merge repository config and user config on top of commit-check defaults."""
102
+ merged = get_default_config()
103
+ with _working_directory(repo_path):
104
+ loaded_config = load_toml_config(config_path or "")
105
+ if loaded_config:
106
+ deep_merge(merged, loaded_config)
107
+ if config:
108
+ deep_merge(merged, config)
109
+ return merged
110
+
111
+
112
+ def _run_checks(
113
+ check_names: list[str],
114
+ context: ValidationContext,
115
+ config: dict[str, Any],
116
+ ) -> dict[str, Any]:
117
+ """Run commit-check rules and always return structured per-check results."""
118
+ rules = RuleBuilder(config).build_all_rules()
119
+ filtered: list[ValidationRule] = [r for r in rules if r.check in check_names]
120
+
121
+ checks: list[dict[str, Any]] = []
122
+ for rule in filtered:
123
+ with io.StringIO() as _out, io.StringIO() as _err:
124
+ with redirect_stdout(_out), redirect_stderr(_err):
125
+ status = ValidationEngine([rule]).validate_all(context)
126
+ passed = status == ValidationResult.PASS
127
+ checks.append(
128
+ {
129
+ "check": rule.check,
130
+ "status": "pass" if passed else "fail",
131
+ "value": context.stdin_text or "",
132
+ "error": "" if passed else (rule.error or ""),
133
+ "suggest": "" if passed else (rule.suggest or ""),
134
+ }
135
+ )
136
+
137
+ overall = "fail" if any(c["status"] == "fail" for c in checks) else "pass"
138
+ return {"status": overall, "checks": checks}
139
+
140
+
141
+ def _validate_message(
142
+ message: str,
143
+ *,
144
+ config: dict[str, Any] | None = None,
145
+ repo_path: Path | None = None,
146
+ config_path: str | None = None,
147
+ ) -> dict[str, Any]:
148
+ """Validate message using commit-check engine internals."""
149
+ cfg = _merge_config(config, repo_path=repo_path, config_path=config_path)
150
+ with _working_directory(repo_path):
151
+ return _run_checks(
152
+ [
153
+ "message",
154
+ "subject_imperative",
155
+ "subject_max_length",
156
+ "subject_min_length",
157
+ "subject_capitalized",
158
+ "require_signed_off_by",
159
+ "require_body",
160
+ "allow_merge_commits",
161
+ "allow_revert_commits",
162
+ "allow_empty_commits",
163
+ "allow_fixup_commits",
164
+ "allow_wip_commits",
165
+ ],
166
+ ValidationContext(stdin_text=message, config=cfg),
167
+ cfg,
168
+ )
169
+
170
+
171
+ def _validate_branch(
172
+ branch: str | None = None,
173
+ *,
174
+ config: dict[str, Any] | None = None,
175
+ repo_path: Path | None = None,
176
+ config_path: str | None = None,
177
+ ) -> dict[str, Any]:
178
+ """Validate branch name using commit-check engine internals."""
179
+ cfg = _merge_config(config, repo_path=repo_path, config_path=config_path)
180
+ with _working_directory(repo_path):
181
+ return _run_checks(
182
+ ["branch", "merge_base"],
183
+ ValidationContext(stdin_text=branch, config=cfg),
184
+ cfg,
185
+ )
186
+
187
+
188
+ def _validate_author(
189
+ name: str | None = None,
190
+ email: str | None = None,
191
+ *,
192
+ config: dict[str, Any] | None = None,
193
+ repo_path: Path | None = None,
194
+ config_path: str | None = None,
195
+ ) -> dict[str, Any]:
196
+ """Validate author info using commit-check engine internals."""
197
+ cfg = _merge_config(config, repo_path=repo_path, config_path=config_path)
198
+
199
+ with _working_directory(repo_path):
200
+ if name is not None and email is not None:
201
+ name_result = _run_checks(
202
+ ["author_name"],
203
+ ValidationContext(stdin_text=name, config=cfg),
204
+ cfg,
205
+ )
206
+ email_result = _run_checks(
207
+ ["author_email"],
208
+ ValidationContext(stdin_text=email, config=cfg),
209
+ cfg,
210
+ )
211
+ checks = name_result["checks"] + email_result["checks"]
212
+ return {
213
+ "status": "fail" if any(c["status"] == "fail" for c in checks) else "pass",
214
+ "checks": checks,
215
+ }
216
+
217
+ check_names: list[str] = []
218
+ stdin = None
219
+ if name is not None:
220
+ check_names.append("author_name")
221
+ stdin = name
222
+ if email is not None:
223
+ check_names.append("author_email")
224
+ stdin = email
225
+ if not check_names:
226
+ check_names = ["author_name", "author_email"]
227
+
228
+ return _run_checks(check_names, ValidationContext(stdin_text=stdin, config=cfg), cfg)
229
+
230
+
231
+ def _validate_all(
232
+ message: str | None = None,
233
+ branch: str | None = None,
234
+ author_name: str | None = None,
235
+ author_email: str | None = None,
236
+ *,
237
+ config: dict[str, Any] | None = None,
238
+ repo_path: Path | None = None,
239
+ config_path: str | None = None,
240
+ ) -> dict[str, Any]:
241
+ """Validate multiple commit-check contexts and combine outcomes."""
242
+ cfg = _merge_config(config, repo_path=repo_path, config_path=config_path)
243
+ checks: list[dict[str, Any]] = []
244
+
245
+ with _working_directory(repo_path):
246
+ if message is not None:
247
+ checks.extend(
248
+ _run_checks(
249
+ [
250
+ "message",
251
+ "subject_imperative",
252
+ "subject_max_length",
253
+ "subject_min_length",
254
+ "subject_capitalized",
255
+ "require_signed_off_by",
256
+ "require_body",
257
+ "allow_merge_commits",
258
+ "allow_revert_commits",
259
+ "allow_empty_commits",
260
+ "allow_fixup_commits",
261
+ "allow_wip_commits",
262
+ ],
263
+ ValidationContext(stdin_text=message, config=cfg),
264
+ cfg,
265
+ )["checks"]
266
+ )
267
+ if branch is not None:
268
+ checks.extend(
269
+ _run_checks(
270
+ ["branch", "merge_base"],
271
+ ValidationContext(stdin_text=branch, config=cfg),
272
+ cfg,
273
+ )["checks"]
274
+ )
275
+ if author_name is not None or author_email is not None:
276
+ if author_name is not None:
277
+ checks.extend(
278
+ _run_checks(
279
+ ["author_name"],
280
+ ValidationContext(stdin_text=author_name, config=cfg),
281
+ cfg,
282
+ )["checks"]
283
+ )
284
+ if author_email is not None:
285
+ checks.extend(
286
+ _run_checks(
287
+ ["author_email"],
288
+ ValidationContext(stdin_text=author_email, config=cfg),
289
+ cfg,
290
+ )["checks"]
291
+ )
292
+
293
+ return {
294
+ "status": "fail" if any(c["status"] == "fail" for c in checks) else "pass",
295
+ "checks": checks,
296
+ }
297
+
298
+
299
+ @mcp.tool()
300
+ def server_health() -> dict[str, str]:
301
+ """Return server and dependency versions."""
302
+ return {
303
+ "server": "commit-check-mcp",
304
+ "server_version": __version__,
305
+ "commit_check_version": commit_check_version,
306
+ "mcp_sdk_version": version("mcp"),
307
+ }
308
+
309
+
310
+ @mcp.tool()
311
+ def validate_commit_message(
312
+ message: str,
313
+ config: dict[str, Any] | None = None,
314
+ repo_path: str | None = None,
315
+ config_path: str | None = None,
316
+ ) -> dict[str, Any]:
317
+ """Validate a commit message against commit-check rules."""
318
+ if not isinstance(message, str) or not message.strip():
319
+ raise ValueError("message must be a non-empty string")
320
+ normalized_repo_path = _normalize_repo_path(repo_path)
321
+ return _validate_message(
322
+ message.strip(),
323
+ config=_normalize_config(config),
324
+ repo_path=normalized_repo_path,
325
+ config_path=_normalize_config_path(config_path, normalized_repo_path),
326
+ )
327
+
328
+
329
+ @mcp.tool()
330
+ def validate_branch_name(
331
+ branch: str | None = None,
332
+ config: dict[str, Any] | None = None,
333
+ repo_path: str | None = None,
334
+ config_path: str | None = None,
335
+ ) -> dict[str, Any]:
336
+ """Validate branch naming conventions with commit-check."""
337
+ normalized_branch = branch.strip() if isinstance(branch, str) else None
338
+ if isinstance(branch, str) and not normalized_branch:
339
+ raise ValueError("branch cannot be empty when provided")
340
+ normalized_repo_path = _normalize_repo_path(repo_path)
341
+ return _validate_branch(
342
+ normalized_branch,
343
+ config=_normalize_config(config),
344
+ repo_path=normalized_repo_path,
345
+ config_path=_normalize_config_path(config_path, normalized_repo_path),
346
+ )
347
+
348
+
349
+ @mcp.tool()
350
+ def validate_author_info(
351
+ author_name: str | None = None,
352
+ author_email: str | None = None,
353
+ config: dict[str, Any] | None = None,
354
+ repo_path: str | None = None,
355
+ config_path: str | None = None,
356
+ ) -> dict[str, Any]:
357
+ """Validate commit author name and/or email with commit-check."""
358
+ normalized_name = author_name.strip() if isinstance(author_name, str) else None
359
+ normalized_email = author_email.strip() if isinstance(author_email, str) else None
360
+
361
+ if isinstance(author_name, str) and not normalized_name:
362
+ raise ValueError("author_name cannot be empty when provided")
363
+ if isinstance(author_email, str) and not normalized_email:
364
+ raise ValueError("author_email cannot be empty when provided")
365
+ normalized_repo_path = _normalize_repo_path(repo_path)
366
+
367
+ return _validate_author(
368
+ normalized_name,
369
+ normalized_email,
370
+ config=_normalize_config(config),
371
+ repo_path=normalized_repo_path,
372
+ config_path=_normalize_config_path(config_path, normalized_repo_path),
373
+ )
374
+
375
+
376
+ @mcp.tool()
377
+ def validate_commit_context(
378
+ message: str | None = None,
379
+ branch: str | None = None,
380
+ author_name: str | None = None,
381
+ author_email: str | None = None,
382
+ config: dict[str, Any] | None = None,
383
+ repo_path: str | None = None,
384
+ config_path: str | None = None,
385
+ ) -> dict[str, Any]:
386
+ """Run combined commit-check validations in one call."""
387
+ normalized_message = message.strip() if isinstance(message, str) else None
388
+ normalized_branch = branch.strip() if isinstance(branch, str) else None
389
+ normalized_name = author_name.strip() if isinstance(author_name, str) else None
390
+ normalized_email = author_email.strip() if isinstance(author_email, str) else None
391
+
392
+ if isinstance(message, str) and not normalized_message:
393
+ raise ValueError("message cannot be empty when provided")
394
+ if isinstance(branch, str) and not normalized_branch:
395
+ raise ValueError("branch cannot be empty when provided")
396
+ if isinstance(author_name, str) and not normalized_name:
397
+ raise ValueError("author_name cannot be empty when provided")
398
+ if isinstance(author_email, str) and not normalized_email:
399
+ raise ValueError("author_email cannot be empty when provided")
400
+
401
+ if not any([normalized_message, normalized_branch, normalized_name, normalized_email]):
402
+ raise ValueError(
403
+ "At least one of message, branch, author_name, or author_email must be provided"
404
+ )
405
+ normalized_repo_path = _normalize_repo_path(repo_path)
406
+
407
+ return _validate_all(
408
+ message=normalized_message,
409
+ branch=normalized_branch,
410
+ author_name=normalized_name,
411
+ author_email=normalized_email,
412
+ config=_normalize_config(config),
413
+ repo_path=normalized_repo_path,
414
+ config_path=_normalize_config_path(config_path, normalized_repo_path),
415
+ )
416
+
417
+
418
+ @mcp.tool()
419
+ def validate_repository_state(
420
+ repo_path: str | None = None,
421
+ config: dict[str, Any] | None = None,
422
+ config_path: str | None = None,
423
+ include_message: bool = True,
424
+ include_branch: bool = True,
425
+ include_author: bool = True,
426
+ ) -> dict[str, Any]:
427
+ """Validate the latest commit, current branch, and git author state of a repository."""
428
+ if not any([include_message, include_branch, include_author]):
429
+ raise ValueError("At least one validation target must be enabled")
430
+
431
+ normalized_repo_path = _normalize_repo_path(repo_path)
432
+ normalized_config = _normalize_config(config)
433
+ normalized_config_path = _normalize_config_path(config_path, normalized_repo_path)
434
+
435
+ checks: list[dict[str, Any]] = []
436
+ if include_message:
437
+ checks.extend(
438
+ _validate_message(
439
+ "",
440
+ config=normalized_config,
441
+ repo_path=normalized_repo_path,
442
+ config_path=normalized_config_path,
443
+ )["checks"]
444
+ )
445
+ if include_branch:
446
+ checks.extend(
447
+ _validate_branch(
448
+ None,
449
+ config=normalized_config,
450
+ repo_path=normalized_repo_path,
451
+ config_path=normalized_config_path,
452
+ )["checks"]
453
+ )
454
+ if include_author:
455
+ checks.extend(
456
+ _validate_author(
457
+ None,
458
+ None,
459
+ config=normalized_config,
460
+ repo_path=normalized_repo_path,
461
+ config_path=normalized_config_path,
462
+ )["checks"]
463
+ )
464
+
465
+ return {
466
+ "status": "fail" if any(c["status"] == "fail" for c in checks) else "pass",
467
+ "checks": checks,
468
+ }
469
+
470
+
471
+ @mcp.tool()
472
+ def describe_validation_rules(
473
+ config: dict[str, Any] | None = None,
474
+ repo_path: str | None = None,
475
+ config_path: str | None = None,
476
+ ) -> dict[str, Any]:
477
+ """Return enabled commit-check rules after merging defaults, repo config, and overrides."""
478
+ normalized_repo_path = _normalize_repo_path(repo_path)
479
+ normalized_config = _normalize_config(config)
480
+ normalized_config_path = _normalize_config_path(config_path, normalized_repo_path)
481
+ merged_config = _merge_config(
482
+ normalized_config,
483
+ repo_path=normalized_repo_path,
484
+ config_path=normalized_config_path,
485
+ )
486
+ rules = [rule.to_dict() for rule in RuleBuilder(merged_config).build_all_rules()]
487
+
488
+ return {
489
+ "commit_check_version": commit_check_version,
490
+ "config": merged_config,
491
+ "supported_checks": list(
492
+ dict.fromkeys(entry.check for entry in COMMIT_RULES + BRANCH_RULES)
493
+ ),
494
+ "enabled_rules": rules,
495
+ }
496
+
497
+
498
+ def main() -> None:
499
+ """Run commit-check MCP server via stdio transport."""
500
+ mcp.run(transport="stdio")
501
+
502
+
503
+ if __name__ == "__main__": # pragma: no cover
504
+ main()
@@ -0,0 +1,86 @@
1
+ Metadata-Version: 2.4
2
+ Name: commit-check-mcp
3
+ Version: 0.1.1.post1.dev1
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
+ Dynamic: license-file
15
+
16
+ # commit-check-mcp
17
+
18
+ Model Context Protocol (MCP) server for [commit-check](https://github.com/commit-check/commit-check).
19
+
20
+ ## Features
21
+
22
+ This MCP server exposes commit-check validations as MCP tools:
23
+
24
+ - `server_health` — returns server/sdk versions
25
+ - `validate_commit_message` — validates a commit message
26
+ - `validate_branch_name` — validates a branch name or the current repo branch
27
+ - `validate_author_info` — validates author name/email or the repo's git author config
28
+ - `validate_commit_context` — runs combined checks in one call
29
+ - `validate_repository_state` — validates latest commit, current branch, and author state for a repo
30
+ - `describe_validation_rules` — returns the effective config and enabled rules after merging defaults and repo config
31
+
32
+ All validation tools return the same structured commit-check result shape:
33
+
34
+ ```json
35
+ {
36
+ "status": "pass|fail",
37
+ "checks": [
38
+ {
39
+ "check": "message",
40
+ "status": "pass|fail",
41
+ "value": "...",
42
+ "error": "...",
43
+ "suggest": "..."
44
+ }
45
+ ]
46
+ }
47
+ ```
48
+
49
+ ## Install
50
+
51
+ ```bash
52
+ pip install -e .
53
+ ```
54
+
55
+ ## Run
56
+
57
+ ```bash
58
+ commit-check-mcp
59
+ ```
60
+
61
+ The server runs over stdio transport (recommended MCP default for local tool integrations).
62
+
63
+ ## Repository-Aware Validation
64
+
65
+ `commit-check` is most useful when it runs against a real git repository and its `cchk.toml` or `commit-check.toml` file. This MCP server now supports that directly:
66
+
67
+ - `repo_path` — run git-based validations against a specific repository
68
+ - `config_path` — point to an explicit TOML config file; relative paths are resolved from `repo_path`
69
+ - `config` — apply ad-hoc overrides on top of defaults and repo config
70
+
71
+ Typical patterns:
72
+
73
+ - Validate an explicit message with a repository's rules
74
+ - Validate the current repository state without passing message/branch/author values manually
75
+ - Inspect which rules are actually enabled after config merging
76
+
77
+ Example payload for a repository-wide validation:
78
+
79
+ ```json
80
+ {
81
+ "repo_path": "/path/to/repo",
82
+ "include_message": true,
83
+ "include_branch": true,
84
+ "include_author": true
85
+ }
86
+ ```
@@ -0,0 +1,8 @@
1
+ commit_check_mcp/__init__.py,sha256=0qlKOLxQwzq4RmQlxbdAO2UT7y0zKqS2RQq-PQs7jkM,141
2
+ commit_check_mcp/server.py,sha256=aZfgzLQp_pWKYgMm49IZRBCOuQiMiscMU6ltfr5OJIo,17505
3
+ commit_check_mcp-0.1.1.post1.dev1.dist-info/licenses/LICENSE,sha256=XMRJzGhsjuBcVso4JnpcvzaDBl7N1TR4WU_Y6E8f6Wk,1069
4
+ commit_check_mcp-0.1.1.post1.dev1.dist-info/METADATA,sha256=W_qoI2-LwxjVUACHNOZTqOVaGjxD0mgzFiMQG_OvuaQ,2483
5
+ commit_check_mcp-0.1.1.post1.dev1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
6
+ commit_check_mcp-0.1.1.post1.dev1.dist-info/entry_points.txt,sha256=Aj84jmw43ZbHhkLA2W_tFQSMj0cn_xw8GAlL-44trH4,66
7
+ commit_check_mcp-0.1.1.post1.dev1.dist-info/top_level.txt,sha256=VPx0wL4_vLMrJSZou2krNUhaa8NAjlqbgJKjN2co4ic,17
8
+ commit_check_mcp-0.1.1.post1.dev1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ commit-check-mcp = commit_check_mcp.server:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Commit Check
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ commit_check_mcp