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

@@ -25,7 +25,7 @@ allowed-tools: Bash mcp__gitea__list_issues mcp__gitea__issue_read mcp__gitea__i
## Gotchas ## Gotchas
- **`list_issues` returns PRs too.** It has no `type` filter and both share one repo number space. `is_pull` appears only on `issue_read method: "get"`, never on a list item — check it there before treating a number as an issue. - **`list_issues` mixes in PRs unless you filter.** Issues and PRs share one repo number space; pass `type: "issues"` to exclude PRs (or `"pulls"` for only PRs). Nothing on a list item flags which is which — `is_pull` appears only on `issue_read method: "get"`, never on a list item.
- **Label IDs and names are not interchangeable.** `issue_write` takes numeric IDs only; `list_issues` and `search_issues` filter by name; `issue_read "get"` returns names but `"get_labels"` returns full objects with IDs. Resolve via `gitea-labels-milestones` unless the caller named exact labels. - **Label IDs and names are not interchangeable.** `issue_write` takes numeric IDs only; `list_issues` and `search_issues` filter by name; `issue_read "get"` returns names but `"get_labels"` returns full objects with IDs. Resolve via `gitea-labels-milestones` unless the caller named exact labels.
- **A merged PR leaves its issue open.** Gitea does not auto-close on merge the way GitHub does. Re-read the issue's state after a merge before closing it manually. - **A merged PR leaves its issue open.** Gitea does not auto-close on merge the way GitHub does. Re-read the issue's state after a merge before closing it manually.
- **A 404 may really be a 403.** Gitea hides permission errors as not-found — check the token's `write:issue` scope before concluding the issue does not exist. - **A 404 may really be a 403.** Gitea hides permission errors as not-found — check the token's `write:issue` scope before concluding the issue does not exist.
@@ -46,7 +46,7 @@ One invocation takes one row. Read only the reference(s) that row names — the
| Invocation | Flow | Read | | Invocation | Flow | Read |
|---|---|---| |---|---|---|
| `/gitea-issues` or `/gitea-issues list` | List issues, optionally filtered by state | `references/issues.md` | | `/gitea-issues` or `/gitea-issues list` | List issues with `type: "issues"` so PRs are excluded, optionally filtered by state | `references/issues.md` |
| `/gitea-issues <N>` | Get one issue, routing to `gitea-prs` when the number turns out to be a PR | `references/issues.md` | | `/gitea-issues <N>` | Get one issue, routing to `gitea-prs` when the number turns out to be a PR | `references/issues.md` |
| `/gitea-issues <N> comments` | Get an issue's comments | `references/issues.md` | | `/gitea-issues <N> comments` | Get an issue's comments | `references/issues.md` |
| `/gitea-issues <N> labels` | Get an issue's labels as full objects, IDs included | `references/issues.md` | | `/gitea-issues <N> labels` | Get an issue's labels as full objects, IDs included | `references/issues.md` |

View File

@@ -7,11 +7,13 @@ source_keys:
# Issue operations # Issue operations
Call signatures below were verified live against the deployed `gitea-mcp` server via `ToolSearch` 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 not copied from `api-reference.md` — this is deliberate: research docs are generated from source at
generated from source at a point in time and can drift from the server actually deployed (see the a point in time and can drift from the server actually deployed. Last verified against gitea-mcp
`list_issues` gotcha below, which is the exact drift this policy exists to catch). Re-verify against **v1.7.0**, as reported by `get_gitea_mcp_server_version`. Drift runs in both directions: this file
the live schema if these tools appear to behave differently than documented here. 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` ## `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 - `state` (string, optional, default `"all"`) — conventional values `"open"`/`"closed"`/`"all"`, not
schema-enforced as an enum schema-enforced as an enum
- `labels` (array of strings, optional) — filter by label *name* (not ID) - `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 - `since` (string, optional) — ISO 8601, issues updated after this time
- `before` (string, optional) — ISO 8601, issues updated before this time - `before` (string, optional) — ISO 8601, issues updated before this time
- `page` (number, optional, default `1`) - `page` (number, optional, default `1`)
- `per_page` (number, optional, default `30`) - `per_page` (number, optional, default `30`)
**There is no `type` parameter and no `milestones` parameter**, despite both appearing in **Pass `type: "issues"` on any listing meant to show issues.** Issues and PRs share one repo number
`api-reference.md`. This tool cannot filter issues-vs-PRs or by milestone — see the Gotchas section space and the unfiltered response interleaves them; the only thing distinguishing them on a list
of SKILL.md for the consequence (PR entries can appear in results with no way to exclude them here). 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:** **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`, **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 replace all labels atomically instead of adding: `method: "replace_labels"`.
To remove one: `method: "remove_label" label_id: <single ID>`. 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 ## Token scope
All of `list_issues`, `issue_read`, and `issue_write` are verified working under a token holding All of `list_issues`, `issue_read`, and `issue_write` are verified working under a token holding

View File

@@ -13,8 +13,8 @@ time (see `references/sources.md`) — confirmed to match `api-reference.md`.
**Parameters:** **Parameters:**
- `query` (string, required) — the only hard-required parameter - `query` (string, required) — the only hard-required parameter
- `state` (string, enum `"open"` | `"closed"` | `"all"`, optional) - `state` (string, enum `"open"` | `"closed"` | `"all"`, optional)
- `type` (string, enum `"issues"` | `"pulls"`, optional) — **this tool has a working type filter**, - `type` (string, enum `"issues"` | `"pulls"`, optional) — the same filter, with the same values,
unlike `list_issues` (see `references/issues.md`) that `list_issues` takes (see `references/issues.md`)
- `labels` (string, optional) — comma-separated label **names** — a plain string, not the array form - `labels` (string, optional) — comma-separated label **names** — a plain string, not the array form
`list_issues` uses `list_issues` uses
- `owner` (string, optional) — restrict results to one owner - `owner` (string, optional) — restrict results to one owner

View File

@@ -1,12 +1,13 @@
# Sources # Sources
**Note on call signatures:** per `docs/adr/0011-gitea-skill-deep-modules.md`, the tool parameter **Note on call signatures:** per `docs/adr/0011-gitea-skill-deep-modules.md`, the tool parameter
signatures in `references/issues.md` and `references/search.md` were re-verified live via signatures in `references/issues.md` and `references/search.md` are re-verified live via
`ToolSearch` against the deployed `gitea-mcp` server at authoring time — they are not copied `ToolSearch` against the deployed `gitea-mcp` server — they are not copied verbatim from
verbatim from `api-reference.md`. This resolves issue #6 comment #849's root-cause finding that a `api-reference.md`. This resolves issue #6 comment #849's root-cause finding that a prior skill was
prior skill was authored from API docs that had drifted from the actual MCP tool schema; the live authored from API docs that had drifted from the actual MCP tool schema. That re-verification is
check caught exactly this drift on `list_issues` (see `references/issues.md` — the research doc ongoing, not one-off: an earlier live check recorded `list_issues` as lacking the `type` and
documents a `type` and a `milestones` parameter that do not exist on the deployed server). `milestones` parameters `api-reference.md` documents, and both are present on the deployed
gitea-mcp **v1.7.0**, which is the version these signatures are current as of.
## gitea-mcp-repo ## gitea-mcp-repo

View File

@@ -7,7 +7,7 @@ source_keys:
# Pull request read/write execution detail # Pull request read/write execution detail
Parameter signatures below are cross-checked live against the deployed gitea-mcp server tool schemas at authoring time — not copied verbatim from the plugin's research doc for this domain, which has a known history of drifting from the deployed server (e.g. a prior `type` parameter that no longer exists on `list_issues`). These files were last verified against gitea-mcp **v1.7.0**, as reported by `get_gitea_mcp_server_version`. Re-verify via `ToolSearch` before trusting this file if the deployed version differs — drift has bitten this skill in both directions, adding methods it does not list and fixing quirks it still warns about. Parameter signatures below are cross-checked live against the deployed gitea-mcp server tool schemas at authoring time — not copied verbatim from the plugin's research doc for this domain, which has a known history of drifting from the deployed server. These files were last verified against gitea-mcp **v1.7.0**, as reported by `get_gitea_mcp_server_version`. Re-verify via `ToolSearch` before trusting this file if the deployed version differs — drift has bitten this skill in both directions, adding methods it does not list and fixing quirks it still warns about.
## `list_pull_requests` ## `list_pull_requests`

View File

@@ -25,7 +25,7 @@ allowed-tools: Bash mcp__gitea__list_issues mcp__gitea__issue_read mcp__gitea__i
## Gotchas ## Gotchas
- **`list_issues` returns PRs too.** It has no `type` filter and both share one repo number space. `is_pull` appears only on `issue_read method: "get"`, never on a list item — check it there before treating a number as an issue. - **`list_issues` mixes in PRs unless you filter.** Issues and PRs share one repo number space; pass `type: "issues"` to exclude PRs (or `"pulls"` for only PRs). Nothing on a list item flags which is which — `is_pull` appears only on `issue_read method: "get"`, never on a list item.
- **Label IDs and names are not interchangeable.** `issue_write` takes numeric IDs only; `list_issues` and `search_issues` filter by name; `issue_read "get"` returns names but `"get_labels"` returns full objects with IDs. Resolve via `gitea-labels-milestones` unless the caller named exact labels. - **Label IDs and names are not interchangeable.** `issue_write` takes numeric IDs only; `list_issues` and `search_issues` filter by name; `issue_read "get"` returns names but `"get_labels"` returns full objects with IDs. Resolve via `gitea-labels-milestones` unless the caller named exact labels.
- **A merged PR leaves its issue open.** Gitea does not auto-close on merge the way GitHub does. Re-read the issue's state after a merge before closing it manually. - **A merged PR leaves its issue open.** Gitea does not auto-close on merge the way GitHub does. Re-read the issue's state after a merge before closing it manually.
- **A 404 may really be a 403.** Gitea hides permission errors as not-found — check the token's `write:issue` scope before concluding the issue does not exist. - **A 404 may really be a 403.** Gitea hides permission errors as not-found — check the token's `write:issue` scope before concluding the issue does not exist.
@@ -46,7 +46,7 @@ One invocation takes one row. Read only the reference(s) that row names — the
| Invocation | Flow | Read | | Invocation | Flow | Read |
|---|---|---| |---|---|---|
| `/gitea-issues` or `/gitea-issues list` | List issues, optionally filtered by state | `references/issues.md` | | `/gitea-issues` or `/gitea-issues list` | List issues with `type: "issues"` so PRs are excluded, optionally filtered by state | `references/issues.md` |
| `/gitea-issues <N>` | Get one issue, routing to `gitea-prs` when the number turns out to be a PR | `references/issues.md` | | `/gitea-issues <N>` | Get one issue, routing to `gitea-prs` when the number turns out to be a PR | `references/issues.md` |
| `/gitea-issues <N> comments` | Get an issue's comments | `references/issues.md` | | `/gitea-issues <N> comments` | Get an issue's comments | `references/issues.md` |
| `/gitea-issues <N> labels` | Get an issue's labels as full objects, IDs included | `references/issues.md` | | `/gitea-issues <N> labels` | Get an issue's labels as full objects, IDs included | `references/issues.md` |

View File

@@ -7,11 +7,13 @@ source_keys:
# Issue operations # Issue operations
Call signatures below were verified live against the deployed `gitea-mcp` server via `ToolSearch` 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 not copied from `api-reference.md` — this is deliberate: research docs are generated from source at
generated from source at a point in time and can drift from the server actually deployed (see the a point in time and can drift from the server actually deployed. Last verified against gitea-mcp
`list_issues` gotcha below, which is the exact drift this policy exists to catch). Re-verify against **v1.7.0**, as reported by `get_gitea_mcp_server_version`. Drift runs in both directions: this file
the live schema if these tools appear to behave differently than documented here. 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` ## `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 - `state` (string, optional, default `"all"`) — conventional values `"open"`/`"closed"`/`"all"`, not
schema-enforced as an enum schema-enforced as an enum
- `labels` (array of strings, optional) — filter by label *name* (not ID) - `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 - `since` (string, optional) — ISO 8601, issues updated after this time
- `before` (string, optional) — ISO 8601, issues updated before this time - `before` (string, optional) — ISO 8601, issues updated before this time
- `page` (number, optional, default `1`) - `page` (number, optional, default `1`)
- `per_page` (number, optional, default `30`) - `per_page` (number, optional, default `30`)
**There is no `type` parameter and no `milestones` parameter**, despite both appearing in **Pass `type: "issues"` on any listing meant to show issues.** Issues and PRs share one repo number
`api-reference.md`. This tool cannot filter issues-vs-PRs or by milestone — see the Gotchas section space and the unfiltered response interleaves them; the only thing distinguishing them on a list
of SKILL.md for the consequence (PR entries can appear in results with no way to exclude them here). 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:** **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`, **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 replace all labels atomically instead of adding: `method: "replace_labels"`.
To remove one: `method: "remove_label" label_id: <single ID>`. 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 ## Token scope
All of `list_issues`, `issue_read`, and `issue_write` are verified working under a token holding All of `list_issues`, `issue_read`, and `issue_write` are verified working under a token holding

View File

@@ -13,8 +13,8 @@ time (see `references/sources.md`) — confirmed to match `api-reference.md`.
**Parameters:** **Parameters:**
- `query` (string, required) — the only hard-required parameter - `query` (string, required) — the only hard-required parameter
- `state` (string, enum `"open"` | `"closed"` | `"all"`, optional) - `state` (string, enum `"open"` | `"closed"` | `"all"`, optional)
- `type` (string, enum `"issues"` | `"pulls"`, optional) — **this tool has a working type filter**, - `type` (string, enum `"issues"` | `"pulls"`, optional) — the same filter, with the same values,
unlike `list_issues` (see `references/issues.md`) that `list_issues` takes (see `references/issues.md`)
- `labels` (string, optional) — comma-separated label **names** — a plain string, not the array form - `labels` (string, optional) — comma-separated label **names** — a plain string, not the array form
`list_issues` uses `list_issues` uses
- `owner` (string, optional) — restrict results to one owner - `owner` (string, optional) — restrict results to one owner

View File

@@ -1,12 +1,13 @@
# Sources # Sources
**Note on call signatures:** per `docs/adr/0011-gitea-skill-deep-modules.md`, the tool parameter **Note on call signatures:** per `docs/adr/0011-gitea-skill-deep-modules.md`, the tool parameter
signatures in `references/issues.md` and `references/search.md` were re-verified live via signatures in `references/issues.md` and `references/search.md` are re-verified live via
`ToolSearch` against the deployed `gitea-mcp` server at authoring time — they are not copied `ToolSearch` against the deployed `gitea-mcp` server — they are not copied verbatim from
verbatim from `api-reference.md`. This resolves issue #6 comment #849's root-cause finding that a `api-reference.md`. This resolves issue #6 comment #849's root-cause finding that a prior skill was
prior skill was authored from API docs that had drifted from the actual MCP tool schema; the live authored from API docs that had drifted from the actual MCP tool schema. That re-verification is
check caught exactly this drift on `list_issues` (see `references/issues.md` — the research doc ongoing, not one-off: an earlier live check recorded `list_issues` as lacking the `type` and
documents a `type` and a `milestones` parameter that do not exist on the deployed server). `milestones` parameters `api-reference.md` documents, and both are present on the deployed
gitea-mcp **v1.7.0**, which is the version these signatures are current as of.
## gitea-mcp-repo ## gitea-mcp-repo

View File

@@ -7,7 +7,7 @@ source_keys:
# Pull request read/write execution detail # Pull request read/write execution detail
Parameter signatures below are cross-checked live against the deployed gitea-mcp server tool schemas at authoring time — not copied verbatim from the plugin's research doc for this domain, which has a known history of drifting from the deployed server (e.g. a prior `type` parameter that no longer exists on `list_issues`). These files were last verified against gitea-mcp **v1.7.0**, as reported by `get_gitea_mcp_server_version`. Re-verify via `ToolSearch` before trusting this file if the deployed version differs — drift has bitten this skill in both directions, adding methods it does not list and fixing quirks it still warns about. Parameter signatures below are cross-checked live against the deployed gitea-mcp server tool schemas at authoring time — not copied verbatim from the plugin's research doc for this domain, which has a known history of drifting from the deployed server. These files were last verified against gitea-mcp **v1.7.0**, as reported by `get_gitea_mcp_server_version`. Re-verify via `ToolSearch` before trusting this file if the deployed version differs — drift has bitten this skill in both directions, adding methods it does not list and fixing quirks it still warns about.
## `list_pull_requests` ## `list_pull_requests`