Files
holocron/plugins/gitea/skills/gitea-labels-milestones/references/labels.md
Defame1297 6cfc3577e2 docs: trim repeated boilerplate in git, gitea, and bin skills
Finding 13: five blocks of near-identical wording were repeated across
skills within a plugin — the gitea "resolve owner and repo" step (5
skills), the 404-masks-403 note (6 files), the manual pagination
explanation (8 files), the git plugin's main/master force-push refusal
(7 files, some with multiple internal restatements), and the bin
skills' domain-glossary/ADR paragraph (5 skills). Tightened each
instance in place — same meaning, fewer words — rather than extracting
to a shared file, which ADR-0014's one-file-per-skill install
constraint rules out. Left the three git skills' structured-result
JSON shapes alone (coupled to the separate, out-of-scope git-orchestrate
merge candidate, finding 19).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD
2026-09-12 19:48:31 +00:00

5.3 KiB

topic, source_keys
topic source_keys
labels
gitea-mcp-repo
gitea-mcp-slim-go
context7-websites-gitea

Label operations

Execution detail for label_read and label_write. Both tools operate on either repo-scoped or org-scoped labels — never both in one call. Pick the method family (*_repo_label* vs. *_org_label*) that matches the target, and pass owner+repo or org accordingly.

Verified live schemas

label_read — required: method.

Param Type Notes
method string (enum) "list_repo_labels" | "get_repo_label" | "list_org_labels"
owner string for repo methods
repo string for repo methods
org string for org methods
id number label ID, required for "get_repo_label"
page number default 1
per_page number default 30

label_write — required: method.

Param Type Notes
method string (enum) "create_repo_label" | "edit_repo_label" | "delete_repo_label" | "create_org_label" | "edit_org_label" | "delete_org_label"
owner string for repo methods
repo string for repo methods
org string for org methods
id number for edit/delete
name string required for create
color string hex #RRGGBB, required for create
description string optional
exclusive boolean accepted as a write param on org creates only — repo labels still carry and enforce exclusive, set outside this tool surface
is_archived boolean repo labels only

Note: unlike milestone_read/milestone_write, owner/repo/org are not schema-required on either label tool — only method is. Passing none for a repo/org method still fails, just as a runtime error from Gitea rather than a client-side validation error.

List repo labels

label_read  method: "list_repo_labels"  owner: <owner>  repo: <repo>  per_page: 50

Paginate (page: 1, 2, ...) until the count is below per_page — the only way to build a complete name → ID map, since there's no lookup-by-name endpoint.

Every returned repo label carries its own exclusive boolean, so exclusivity is always readable per repo label. That does not contradict label_write's schema, which annotates exclusive as "(org only)": reading and setting are different questions, and only the setting half is org-scoped (see "Create a label" below). Where the field is true Gitea enforces one-label-per-scope server-side; where it is false labels in that scope stack legitimately. Read the field — never infer exclusivity from the / in a name, and never carry another repo's map over.

On the instance this skill was authored against (Defame1297/holocron) the split ran: every Priority/*, Reviewed/* and Status/* label exclusive: true, every Kind/* label and Compat/Breaking exclusive: false. That is one repo's configuration at one point in time, recorded as a worked example of what the field looks like in practice — it is not a property of the taxonomy and says nothing about the repo you are called against.

Get one label

label_read  method: "get_repo_label"  owner: <owner>  repo: <repo>  id: <id>

Resolve a name to an ID

The tool surface carries no lookup-by-name method. List all repo labels (paginating if needed), scan for a case-insensitive name match, and extract id. Both pools can apply to one issue: if the name is not in list_repo_labels, also check list_org_labels before reporting it unresolved. That method takes org, not owner/repo — pass the repo's owner as org, which is what it means when the owner is an organisation. Its failure modes are not interchangeable. token does not have at least one of required scope(s), required=[read:organization] means the org pool was never queried — report that missing scope rather than reporting the label unresolved. Only a not-found response means the owner is a user account with no org pool, making the miss a real miss.

Resolution is the required first step before any label application on an issue or PR — the actual add_labels/replace_labels/remove_label call lives in gitea-issues/gitea-prs via issue_write/pull_request_write, which take numeric IDs only.

Create a label

label_write  method: "create_repo_label"
  owner: <owner>  repo: <repo>
  name: "Kind/Bug"
  color: "#d73a4a"
  description: "Confirmed bug"

For an org label, use method: "create_org_label" with org: instead of owner/repo, and exclusive: true if the label belongs to a mutually-exclusive scope group. label_write accepts exclusive on org methods only, so a repo label's exclusivity cannot be set or cleared through this tool — it is set in the Gitea UI or against the REST API directly, and read back via list_repo_labels.

Edit a label

label_write  method: "edit_repo_label"  owner: <owner>  repo: <repo>  id: <id>  color: "#ff0000"

Only pass the fields being changed — id plus any of name/color/description/is_archived.

Delete a label

label_write  method: "delete_repo_label"  owner: <owner>  repo: <repo>  id: <id>

Deleting a label does not remove it from historical issue/PR timeline events — it disappears only from current label lists.