fix(gitea-issues): list_issues does have type and milestones on v1.7.0

SKILL.md's headline Gotcha said `list_issues` "has no `type` filter", and
references/issues.md stated in bold that neither `type` nor `milestones`
exists, "despite both appearing in api-reference.md". Both parameters are
present on the deployed gitea-mcp v1.7.0 and both work: `type: "issues"`
returns only issues, `type: "pulls"` only PRs, and `milestones` filters by
name. Unfiltered, the same window returns them interleaved, so the mixing
the Gotcha describes is real — only the stated remedy was wrong.

This mattered most in gitea-workflow's no-args check-in, which lists open
issues through this skill and so reported PRs under "Open Issues" while
the skill forbade the one-parameter fix. The list flow now passes
`type: "issues"`.

references/sources.md recorded the absence as a live-verification win over
stale research docs; it now records that the earlier check was superseded
by v1.7.0, since drift runs in both directions. gitea-prs cited the same
parameter as its canonical drift example and no longer does — no
replacement example was substituted, because the obvious candidate was not
verified in this pass.

Also defaults label writes to `add_labels`: `replace_labels` clears every
label not in the array, and per-label exclusivity makes blanket replacement
destructive for a non-exclusive scope.

Verified live against gitea-mcp v1.7.0, read-only calls.

Refs #99
This commit is contained in:
2026-08-30 20:51:02 +00:00
parent c5b207aee8
commit dd1981db80
10 changed files with 68 additions and 40 deletions

View File

@@ -7,11 +7,13 @@ source_keys:
# Issue operations
Call signatures below were verified live against the deployed `gitea-mcp` server via `ToolSearch`
at authoring time, not copied from `api-reference.md` — this is deliberate: research docs are
generated from source at a point in time and can drift from the server actually deployed (see the
`list_issues` gotcha below, which is the exact drift this policy exists to catch). Re-verify against
the live schema if these tools appear to behave differently than documented here.
Call signatures below were verified live against the deployed `gitea-mcp` server via `ToolSearch`,
not copied from `api-reference.md` — this is deliberate: research docs are generated from source at
a point in time and can drift from the server actually deployed. Last verified against gitea-mcp
**v1.7.0**, as reported by `get_gitea_mcp_server_version`. Drift runs in both directions: this file
previously recorded `list_issues` as having neither a `type` nor a `milestones` parameter, and
v1.7.0 has both. Re-verify against the live schema if these tools appear to behave differently than
documented here.
## `list_issues`
@@ -21,18 +23,22 @@ the live schema if these tools appear to behave differently than documented here
- `state` (string, optional, default `"all"`) — conventional values `"open"`/`"closed"`/`"all"`, not
schema-enforced as an enum
- `labels` (array of strings, optional) — filter by label *name* (not ID)
- `milestones` (array of strings, optional) — filter by milestone name or numeric ID, both passed as
strings
- `type` (string, enum `"issues"` | `"pulls"`, optional) — omit it and the response mixes both
- `since` (string, optional) — ISO 8601, issues updated after this time
- `before` (string, optional) — ISO 8601, issues updated before this time
- `page` (number, optional, default `1`)
- `per_page` (number, optional, default `30`)
**There is no `type` parameter and no `milestones` parameter**, despite both appearing in
`api-reference.md`. This tool cannot filter issues-vs-PRs or by milestone — see the Gotchas section
of SKILL.md for the consequence (PR entries can appear in results with no way to exclude them here).
**Pass `type: "issues"` on any listing meant to show issues.** Issues and PRs share one repo number
space and the unfiltered response interleaves them; the only thing distinguishing them on a list
item is the `html_url` path segment (`/issues/` vs `/pulls/`), since `is_pull` is not returned on
list items — see the Gotchas section of SKILL.md.
**Call:**
```
list_issues owner: <owner> repo: <repo> state: "open"
list_issues owner: <owner> repo: <repo> state: "open" type: "issues"
```
**Response (list item):** `number`, `title`, `state`, `html_url`, `user`, `comments`, `created_at`,
@@ -117,6 +123,13 @@ issue_write method: "add_labels" owner: <owner> repo: <repo> issue_number: <N> l
To replace all labels atomically instead of adding: `method: "replace_labels"`.
To remove one: `method: "remove_label" label_id: <single ID>`.
**Default to `add_labels`.** `replace_labels` clears every label not in the array, so it drops
labels the caller never mentioned. Reach for it only when the caller asked for the issue's label
set to become exactly what they listed. In particular, do not use it to enforce one-label-per-scope:
exclusivity is a per-label property — the server drops the sibling itself for a label whose
`exclusive` field is `true`, and a label whose `exclusive` is `false` (every `Kind/*` on this
instance) is legitimately stackable. See `gitea-labels-milestones` for how to read that field.
## Token scope
All of `list_issues`, `issue_read`, and `issue_write` are verified working under a token holding