issue-kit
Opinionated backlog-standards toolkit: a single spec file (issue-standard.yml)
declares your issue standard — label taxonomy with colors, the required
.github/ISSUE_TEMPLATE set, lint rules — and issue-kit checks any number of
repositories against it. MCP server and CLI over one engine.
Phase M0 is strictly read-only: it lints and reports, it never mutates a
repository. The only write is standard_init, which puts the default spec on
your local disk.
Design docs live in ARCHITECTURE.md, ROADMAP.md, and adr/.
Install
pip install issue-kit-mcp
# or from a checkout:
pip install -e '.[dev]'
Requires Python 3.10+.
CLI
# Write the default spec (standard 2026-07-14) to ./issue-standard.yml
issue-kit init [--path PATH] [--force]
# Lint one or more repos against the spec
issue-kit lint OWNER/REPO [OWNER/REPO ...] [--repo OWNER/REPO] [--repos-file FILE]
[--spec PATH] [--provider github|snapshot] [--snapshots DIR]
[--format json|text|markdown] [--ci]
# Aggregate conformance dashboard
issue-kit report OWNER/REPO ... [--repos-file FILE] [--spec PATH]
[--provider github|snapshot] [--snapshots DIR]
[--format json|text|markdown]
# Capture a repo's issues/labels/templates into a snapshot bundle (GET-only)
issue-kit snapshot OWNER/REPO --out DIR [--format json|text|markdown]
standard-init / standard-lint / standard-report / standard-snapshot
are accepted aliases — the same naming the MCP tools use (snapshot is
CLI-only in M0; it has no MCP double yet).
Exit codes
Shared CI contract (never masked):
| code | meaning |
|---|---|
| 0 | conformant, or advisory-only findings |
| 1 | error-severity findings present |
| 2 | config error: invalid spec, provider/auth failure, invalid arguments |
stdout carries the report in the chosen format (parseable even at exit 1);
stderr carries diagnostics. Default format is text on a TTY, json otherwise.
Spec resolution
--spec PATH > ISSUE_KIT_SPEC env > ./issue-standard.yml > built-in
default spec. An explicit path that does not exist is a config error (exit 2).
GitHub token
The GitHub provider is read-only (issues, labels, contents) and takes its
token from the same env chain MCP clients use:
GITHUB_PERSONAL_ACCESS_TOKEN > GITHUB_TOKEN > GH_TOKEN. A fine-grained
PAT with Issues:read, Contents:read, Metadata:read is enough. Without a token
the provider runs anonymously (60 req/h, public repos only); an auth failure
on a private repo is a config error, never a silent pass.
Snapshots (offline runs)
--provider snapshot --snapshots DIR reads repo state from bundle JSONs
instead of the network. Bundle format (fixed contract):
{
"repo": "owner/name",
"fetched_at": "2026-07-14T12:00:00Z",
"issues": [
{"number": 1, "title": "...", "state": "open",
"labels": [{"name": "bug", "color": "d73a4a", "description": ""}],
"body": "..."}
],
"labels": [{"name": "bug", "color": "d73a4a", "description": ""}],
"templates": {"bug.md": "---\nname: ...\n---\n..."}
}
labels may be null — the label inventory was unavailable at capture time;
label lint then covers only labels that appear on issues. templates may be
null, which is treated as "no templates". Keep local snapshot captures in
.snapshots/ (gitignored).
Produce a bundle with the toolkit itself instead of hand-assembling one:
issue-kit snapshot OWNER/REPO --out .snapshots
issue-kit lint OWNER/REPO --provider snapshot --snapshots .snapshots
snapshot is strictly read-only (GET issues, labels, contents), writes one
<owner>__<repo>.json under --out, and serializes deterministically (sorted
keys, ensure_ascii=False, indent 2) so re-captures diff cleanly. The label
inventory is captured in full (not null), so an offline --provider snapshot
run reproduces the live findings at capture time.
MCP server
{
"mcpServers": {
"issue-kit": {
"command": "python",
"args": ["-m", "issue_kit"]
}
}
}
Tools (names are a public contract): standard_init, standard_lint,
standard_report. Each returns the same JSON object the CLI prints with
--format json.
Lint rules (M0)
| rule | severity | meaning |
|---|---|---|
missing_type |
error | OPEN issue without a type label |
multiple_type |
error | more than one type label |
missing_priority |
error | no P1/P2/P3 label |
multiple_priority |
error | more than one priority label |
nonstandard_label |
advisory | repo label outside the spec (may be a legitimate domain label) |
missing_template |
error | no template whose labels contains the type — matched by content, not filename: .md front matter or a GitHub Issue Forms *.yml/*.yaml top-level labels (config.yml excluded) |
missing_template_config |
advisory | no config.yml in .github/ISSUE_TEMPLATE/ |
missing_body_section |
advisory | soft body-structure check (problem, todo) |
Title prefixes like [P1] are intentionally not mapped to priority
labels in M0 — recognizing them as relabel hints is M2 material
(issues_relabel). Issues by dependabot and pull requests are excluded
from checks and from the conformance denominator.
Reports contain issue numbers, titles, labels, and rule details — never issue bodies.
Development
pip install -e '.[dev]'
ruff check src tests
pytest -q
License
MIT — see LICENSE.
Metadata
Release files for issue-kit-mcp 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| issue_kit_mcp-0.1.0.tar.gz | 43.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| issue_kit_mcp-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 80.7 kB
Release files / issue_kit_mcp-0.1.0.tar.gz
| Download URL | issue_kit_mcp-0.1.0.tar.gz |
|---|---|
| Size | 43.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4d5c9b8d3ac241ddfe0006385b1882f9237332e5e4e500edef7e8852e26979f7
|
|
BLAKE2b-256 checksum How to use checksums |
9c5d75a2061885d94670a10735821f3a1beb337d099157d9373223334c4fd14c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.
Transparency logRelease files / issue_kit_mcp-0.1.0-py3-none-any.whl
| Download URL | issue_kit_mcp-0.1.0-py3-none-any.whl |
|---|---|
| Size | 37.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
db198c02bfbd7a3bbf453e72481cc7dbcf648fdb878cebf011bb576ee6c0501d
|
|
BLAKE2b-256 checksum How to use checksums |
aa032703af197639e542845c6483f47e70561841b82a34cd3679ae62c52a3300
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.
Transparency log