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
This commit is contained in:
@@ -23,19 +23,19 @@ allowed-tools: Bash mcp__gitea__list_branches mcp__gitea__create_branch mcp__git
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **404 often means 403.** Gitea masks permission errors as not-found; on an unexpected one, check token scope before reporting a branch or commit missing.
|
||||
- **Nothing auto-paginates.** `list_branches` and `list_commits` return one page; iterate `page` until the returned count is below `per_page`.
|
||||
- **404 can mean 403.** Gitea masks permission errors as not-found — check token scope before reporting a branch or commit missing.
|
||||
- **Nothing auto-paginates.** `list_branches`/`list_commits` return one page — iterate `page` until the count is below `per_page`.
|
||||
- **`delete_branch` has no force-push guard.** Treat deleting a protected branch as a hard refusal unless the user explicitly confirms it in the conversation. Check `protected` from `list_branches` first — a protected branch need not be named `main`.
|
||||
|
||||
## Step 1 — Resolve owner and repo
|
||||
|
||||
Before any tool call, extract `owner` and `repo` from the git remote:
|
||||
Extract `owner` and `repo` from the git remote before any tool call — `get_me` and `list_my_repos` are blocked under this skill's token scope, so the remote is the only source:
|
||||
|
||||
```bash
|
||||
rtk git remote get-url origin
|
||||
```
|
||||
|
||||
`get_me` and `list_my_repos` are blocked under the token scope this skill assumes, so the remote is the only source. If origin is not set or the URL is not a Gitea URL, stop and report: "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
No origin, or not a Gitea URL: stop and report "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
|
||||
## Step 2 — Dispatch
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@ list_branches owner: <owner> repo: <repo>
|
||||
**Response:** one object per branch: `name`, `protected` (bool), `commit_sha` (present when the
|
||||
underlying commit data is available).
|
||||
|
||||
Paginate if you need the full list (see Gotchas in SKILL.md) — iterate `page` until the returned
|
||||
count is less than `per_page`.
|
||||
Paginate for the full list (see Gotchas) — iterate `page` until the count is less than `per_page`.
|
||||
|
||||
## `create_branch`
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ compatibility: Requires the Gitea MCP server configured with a token scoped to a
|
||||
is not actually required for any of this domain's five tools.
|
||||
|
||||
metadata:
|
||||
version: "1.0.0"
|
||||
version: "1.0.1"
|
||||
category: gitea
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
@@ -23,7 +23,7 @@ allowed-tools: mcp__gitea__get_file_contents mcp__gitea__get_dir_contents mcp__g
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **A 404 may mean an under-scoped token, not a missing path.** Every tool here gates on `write:repository`, and Gitea masks insufficient scope as 404. Check scopes first.
|
||||
- **404 may mean an under-scoped token, not a missing path.** These tools gate on `write:repository`; check scope before concluding the path is missing.
|
||||
- **Reads take `ref` (`tree_sha` on `get_repository_tree`), writes take `branch_name`.** One concept, three names — carry the wrong key and the branch is dropped.
|
||||
- **`content` is base64 both ways — except under `withLines: true`.** Encode before a write, decode after a read; but with `withLines: true` `content` is already plain JSON text and the reported `"encoding": "base64"` is a lie. Decoding it yields garbage.
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ size. No recursion, no content, no `sha`.
|
||||
`get_repository_tree(owner, repo, tree_sha, recursive)`. Set `recursive: true` to walk
|
||||
subdirectories in one call.
|
||||
|
||||
The response sets `truncated: true` when one page does not hold every entry. Page through with
|
||||
`page`/`per_page` (defaults `1` and `30`) until a page returns fewer entries than `per_page`.
|
||||
The response sets `truncated: true` when one page doesn't hold every entry — page with
|
||||
`page`/`per_page` (defaults `1`/`30`) until a page returns fewer than `per_page`.
|
||||
|
||||
## Neither listing is a SHA source for a write
|
||||
|
||||
@@ -44,7 +44,6 @@ the canonical path for a write's SHA: one call returns the decoded content and t
|
||||
|
||||
## A 404 that is really a 403
|
||||
|
||||
These reads gate on `write:repository`, not on read access alone, and some Gitea endpoints answer
|
||||
an under-scoped token with 404 instead of 403 so they do not leak whether the resource exists. A
|
||||
404 on a path you are confident about is a scope problem until proven otherwise — check the token's
|
||||
configured scopes before concluding the file or directory does not exist.
|
||||
These reads gate on `write:repository`; an under-scoped token gets 404 instead of 403 so the
|
||||
endpoint doesn't leak whether the resource exists. On a path you're confident about, check token
|
||||
scope before concluding it doesn't exist.
|
||||
|
||||
@@ -14,7 +14,7 @@ compatibility: Requires Gitea MCP server configured with write:issue and write:r
|
||||
|
||||
metadata:
|
||||
category: integration
|
||||
version: "0.1.4"
|
||||
version: "0.1.5"
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
- gitea-mcp-slim-go
|
||||
@@ -29,17 +29,17 @@ allowed-tools: Bash mcp__gitea__list_issues mcp__gitea__issue_read mcp__gitea__i
|
||||
- **`list_issues` mixes in PRs unless you filter.** Issues and PRs share one number space; pass `type: "issues"` to exclude PRs (or `"pulls"`). `is_pull` is returned only by `issue_read method: "get"` — on a list item the only tell is `html_url`'s path segment (`/issues/` vs `/pulls/`).
|
||||
- **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 merge does not itself close the issue.** Gitea has no close-on-merge event, but a `Fixes #N` in the merged commits can, depending on merge style (`gitea-prs`). Re-read its 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.
|
||||
- **404 may mean 403.** Gitea hides permission errors as not-found — check `write:issue` scope before concluding the issue doesn't exist.
|
||||
|
||||
## Step 1 — Resolve owner and repo
|
||||
|
||||
An orchestrating caller may pass `owner` and `repo` in already, and the `search` row is cross-repository and needs only a query — both skip this step. Otherwise, before any tool call:
|
||||
Skip if an orchestrating caller already passed `owner`/`repo` in, or the action is `search` (cross-repository, needs only a query). Otherwise, before any tool call:
|
||||
|
||||
```bash
|
||||
rtk git remote get-url origin
|
||||
```
|
||||
|
||||
If origin is unset or the URL is not a Gitea URL, stop and report: "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
No origin, or not a Gitea URL: stop and report "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
|
||||
## Step 2 — Dispatch
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ list_issues owner: <owner> repo: <repo> state: "open" type: "issues"
|
||||
`updated_at`, and optionally `labels` (`[]string`), `milestone` (`{id, title}`), `ref`, `deadline`.
|
||||
Body and `closed_at` are omitted from list responses — call `issue_read method: "get"` for those.
|
||||
|
||||
Paginate with `page`/`per_page` until the returned count is less than `per_page`.
|
||||
Paginate: `page`/`per_page`, stop once the count is below `per_page`.
|
||||
|
||||
## `issue_read`
|
||||
|
||||
|
||||
@@ -16,30 +16,30 @@ metadata:
|
||||
- gitea-mcp-slim-go
|
||||
- context7-websites-gitea
|
||||
- context7-gitea-tea-cli
|
||||
version: "0.1.5"
|
||||
version: "0.1.6"
|
||||
|
||||
allowed-tools: Bash mcp__gitea__label_read mcp__gitea__label_write mcp__gitea__milestone_read mcp__gitea__milestone_write
|
||||
---
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Applying a label takes a numeric ID, but issue/PR responses slim labels down to name strings.** An issue's existing labels yield no IDs — resolve name → ID with `label_read`.
|
||||
- **`pull_request_read` returns `milestone` as a bare title string** where `issue_read` returns `{id, title}` — recover the milestone's ID by listing milestones and matching the title.
|
||||
- **Never assume a `Kind/*`/`Priority/*`/`Status/*` scope is exclusive — read each label's own `exclusive` field.** `list_repo_labels` returns it on every repo label, so it is always *readable* per label; `label_write` documents it as "(org only)" because it is only *settable* through the org create methods. Where it is `true` Gitea enforces one-per-scope itself, and replacing rather than stacking on a label whose `exclusive` is `false` destroys a valid label.
|
||||
- **Applying a label needs a numeric ID; issue/PR responses give only name strings.** Resolve name → ID with `label_read` first.
|
||||
- **`pull_request_read` returns `milestone` as a bare title string, `issue_read` as `{id, title}`.** Recover the ID by listing milestones and matching the title.
|
||||
- **Never assume a `Kind/*`/`Priority/*`/`Status/*` scope is exclusive — read each label's `exclusive` field.** `list_repo_labels` always returns it; `label_write` can only set it via org create methods ("org only"). `true` means Gitea enforces one-per-scope; replacing instead of stacking on a `false` label destroys a valid one.
|
||||
|
||||
## Step 1 — Resolve owner, repo and org
|
||||
|
||||
Before any tool call, extract `owner` and `repo` from the git remote (skip this if an orchestrating caller already passed them in):
|
||||
Extract `owner` and `repo` from the git remote before any tool call (skip if an orchestrating caller already passed them in):
|
||||
|
||||
```bash
|
||||
rtk git remote get-url origin
|
||||
```
|
||||
|
||||
If origin is not set or the URL is not a Gitea URL, stop and report: "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
No origin, or not a Gitea URL: stop and report "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
|
||||
The `*_org_label*` methods take `org`, not `owner`/`repo`. Pass that same `owner` as `org` — it is the org name whenever the owner is an organisation, and the remote URL does not say whether it is one.
|
||||
The `*_org_label*` methods take `org`, not `owner`/`repo`. Pass that same `owner` as `org` — it's the org name whenever the owner is an organisation, which the remote URL doesn't say.
|
||||
|
||||
Read the failure text before interpreting it. `list_org_labels` needs the `read:organization` token scope, which this skill's declared scopes (`write:issue`, `write:repository`) do not carry, so it fails with `token does not have at least one of required scope(s), required=[read:organization]` *before* it ever determines org-vs-user. Report that: the org pool went unchecked, not empty. Only a not-found response is evidence the owner is a user account with no org pool.
|
||||
Read the failure text before interpreting it: `list_org_labels` needs `read:organization`, which this skill's declared scopes don't carry, so it fails with a scope error *before* it ever checks org-vs-user. Report the unchecked scope, not an empty pool — only a genuine not-found means the owner is a user account with no org pool.
|
||||
|
||||
## Step 2 — Dispatch
|
||||
|
||||
@@ -58,6 +58,6 @@ Read the failure text before interpreting it. `list_org_labels` needs the `read:
|
||||
| Update / close a milestone | `milestone_write` | `"update"` |
|
||||
| Delete a milestone | `milestone_write` | `"delete"` |
|
||||
|
||||
Every list method paginates manually — `per_page` defaults to 30, so iterate `page: 1, 2, ...` until a page returns fewer results than `per_page`. A truncated list silently breaks name → ID resolution.
|
||||
Every list method paginates manually (`per_page` default 30) — iterate `page: 1, 2, ...` until a page returns fewer than `per_page`. A truncated list silently breaks name → ID resolution.
|
||||
|
||||
If the task is a label operation, read `references/labels.md`; if a milestone operation, read `references/milestones.md`. If the label to apply has to be derived from conversation context rather than named, read `references/label-inference.md`.
|
||||
|
||||
@@ -51,8 +51,8 @@ runtime error from Gitea rather than a client-side validation error.
|
||||
label_read method: "list_repo_labels" owner: <owner> repo: <repo> per_page: 50
|
||||
```
|
||||
|
||||
Paginate (`page: 1, 2, ...`) until the returned count is less than `per_page`. This is the only way
|
||||
to build a complete name → ID map — there is no lookup-by-name endpoint.
|
||||
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
|
||||
|
||||
@@ -19,7 +19,7 @@ metadata:
|
||||
- gitea-mcp-slim-go
|
||||
- context7-websites-gitea
|
||||
- context7-gitea-tea-cli
|
||||
version: "0.1.3"
|
||||
version: "0.1.4"
|
||||
|
||||
allowed-tools: Bash mcp__gitea__list_pull_requests mcp__gitea__pull_request_read mcp__gitea__pull_request_write mcp__gitea__pull_request_review_write
|
||||
---
|
||||
@@ -31,13 +31,13 @@ allowed-tools: Bash mcp__gitea__list_pull_requests mcp__gitea__pull_request_read
|
||||
|
||||
## Step 1 — Resolve owner and repo
|
||||
|
||||
Extract them from the git remote before any tool call, skipping this when an orchestrating caller already passed them in:
|
||||
Extract from the git remote before any tool call, skipping this when an orchestrating caller already passed them in:
|
||||
|
||||
```bash
|
||||
rtk git remote get-url origin
|
||||
```
|
||||
|
||||
If origin is not set or the URL is not a Gitea URL, stop and report: "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
No origin, or not a Gitea URL: stop and report "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
|
||||
## Step 2 — Dispatch
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ compatibility: Requires Gitea MCP server configured with a token with write:repo
|
||||
|
||||
metadata:
|
||||
category: integration
|
||||
version: "0.1.1"
|
||||
version: "0.1.2"
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
- gitea-mcp-slim-go
|
||||
@@ -33,13 +33,13 @@ allowed-tools: Bash mcp__gitea__list_releases mcp__gitea__get_release mcp__gitea
|
||||
|
||||
## Step 1 — Resolve owner and repo
|
||||
|
||||
`owner` and `repo` are required on every tool below. Extract them from the git remote, unless an orchestrating caller passed them in already:
|
||||
`owner` and `repo` are required on every tool below. Extract from the git remote, unless an orchestrating caller already passed them in:
|
||||
|
||||
```bash
|
||||
rtk git remote get-url origin
|
||||
```
|
||||
|
||||
If origin is not set or the URL is not a Gitea URL, stop and report: "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
No origin, or not a Gitea URL: stop and report "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
|
||||
## Step 2 — Dispatch
|
||||
|
||||
@@ -68,6 +68,6 @@ These four are mutually exclusive — pick the one row the request lands on.
|
||||
| Create a release | Call `create_release` with `tag_name`, `target`, `title`, and `is_draft`/`is_pre_release` set explicitly — never left to default. This surface carries no update or edit tool, so a wrong flag is repairable only by delete-and-recreate (`references/conventions.md`). A separate `create_tag` is only needed to tag a commit without wrapping it in a release — whether `create_release` creates a missing tag is unconfirmed, so verify with `get_tag`. |
|
||||
| Delete a release | Resolve the numeric `id` per the first Gotcha, confirm intent, then call `delete_release`. The tag survives. |
|
||||
| Delete a tag along with its release | Delete the release first, then call `delete_tag` — confirm both are intended before proceeding, since each is irreversible on its own. |
|
||||
| List every page | Loop `page: 1, 2, 3...` until a response returns fewer than `per_page` entries. Nothing here auto-paginates. |
|
||||
| List every page | Loop `page: 1, 2, 3...` until a response returns fewer than `per_page` entries — nothing auto-paginates. |
|
||||
|
||||
If exact input params or response field shapes are needed, read `references/call-signatures.md`. If the caller raises semver tag naming, draft/prerelease semantics, release-notes sourcing, or how a release relates to its tag, read `references/conventions.md`.
|
||||
|
||||
@@ -70,7 +70,6 @@ id, tag_name, target, title, body, draft, prerelease, html_url, author, created_
|
||||
|
||||
## Pagination
|
||||
|
||||
None of the list tools auto-paginate. To collect a full result set, call with `page: 1`, then
|
||||
`page: 2`, etc., stopping when a page returns fewer items than `per_page`. `list_releases` and
|
||||
`list_tags` default `per_page` to 20 — lower than the 30-default used by most other gitea-mcp list
|
||||
tools, so a caller assuming 30 will under-count pages needed for a fixed total.
|
||||
Nothing auto-paginates. Loop `page: 1, 2, ...` until a page returns fewer items than `per_page`.
|
||||
`list_releases`/`list_tags` default `per_page` to 20, not the usual 30 — assuming 30 under-counts
|
||||
pages needed.
|
||||
|
||||
@@ -13,7 +13,7 @@ compatibility: Requires Gitea MCP server configured with a token; delegates all
|
||||
|
||||
metadata:
|
||||
category: integration
|
||||
version: "0.1.3"
|
||||
version: "0.1.4"
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
- gitea-mcp-slim-go
|
||||
|
||||
@@ -14,7 +14,7 @@ The user has referenced a bare number without saying "issue" or "PR" (e.g. "what
|
||||
2. Check the response's `is_pull` field:
|
||||
- `true` → it's a PR. Invoke `gitea-prs` for full PR detail (status, diff, reviews as appropriate to the request) and present that instead.
|
||||
- `false` or absent → it's an issue. Present the issue detail already retrieved.
|
||||
3. If the resolution call 404s, don't conclude the number doesn't exist. Gitea hides permission errors as not-found (documented in `gitea-issues`' Gotchas), so report the 404 and suggest verifying the token carries `write:issue` rather than reporting "no such issue or PR."
|
||||
3. A 404 here isn't proof the number doesn't exist — Gitea hides permission errors as not-found (see `gitea-issues` Gotchas). Report the 404 and suggest checking the token's `write:issue` scope rather than reporting "no such issue or PR."
|
||||
|
||||
If the user stated an action on the number rather than asking about it, resolution is only step one: hand the action, with the resolved domain, to `gitea-issues` or `gitea-prs` to carry out. Presenting detail is not a substitute for performing the write.
|
||||
|
||||
|
||||
@@ -23,19 +23,19 @@ allowed-tools: Bash mcp__gitea__list_branches mcp__gitea__create_branch mcp__git
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **404 often means 403.** Gitea masks permission errors as not-found; on an unexpected one, check token scope before reporting a branch or commit missing.
|
||||
- **Nothing auto-paginates.** `list_branches` and `list_commits` return one page; iterate `page` until the returned count is below `per_page`.
|
||||
- **404 can mean 403.** Gitea masks permission errors as not-found — check token scope before reporting a branch or commit missing.
|
||||
- **Nothing auto-paginates.** `list_branches`/`list_commits` return one page — iterate `page` until the count is below `per_page`.
|
||||
- **`delete_branch` has no force-push guard.** Treat deleting a protected branch as a hard refusal unless the user explicitly confirms it in the conversation. Check `protected` from `list_branches` first — a protected branch need not be named `main`.
|
||||
|
||||
## Step 1 — Resolve owner and repo
|
||||
|
||||
Before any tool call, extract `owner` and `repo` from the git remote:
|
||||
Extract `owner` and `repo` from the git remote before any tool call — `get_me` and `list_my_repos` are blocked under this skill's token scope, so the remote is the only source:
|
||||
|
||||
```bash
|
||||
rtk git remote get-url origin
|
||||
```
|
||||
|
||||
`get_me` and `list_my_repos` are blocked under the token scope this skill assumes, so the remote is the only source. If origin is not set or the URL is not a Gitea URL, stop and report: "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
No origin, or not a Gitea URL: stop and report "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
|
||||
## Step 2 — Dispatch
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@ list_branches owner: <owner> repo: <repo>
|
||||
**Response:** one object per branch: `name`, `protected` (bool), `commit_sha` (present when the
|
||||
underlying commit data is available).
|
||||
|
||||
Paginate if you need the full list (see Gotchas in SKILL.md) — iterate `page` until the returned
|
||||
count is less than `per_page`.
|
||||
Paginate for the full list (see Gotchas) — iterate `page` until the count is less than `per_page`.
|
||||
|
||||
## `create_branch`
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ compatibility: Requires the Gitea MCP server configured with a token scoped to a
|
||||
is not actually required for any of this domain's five tools.
|
||||
|
||||
metadata:
|
||||
version: "1.0.0"
|
||||
version: "1.0.1"
|
||||
category: gitea
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
@@ -23,7 +23,7 @@ allowed-tools: mcp__gitea__get_file_contents mcp__gitea__get_dir_contents mcp__g
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **A 404 may mean an under-scoped token, not a missing path.** Every tool here gates on `write:repository`, and Gitea masks insufficient scope as 404. Check scopes first.
|
||||
- **404 may mean an under-scoped token, not a missing path.** These tools gate on `write:repository`; check scope before concluding the path is missing.
|
||||
- **Reads take `ref` (`tree_sha` on `get_repository_tree`), writes take `branch_name`.** One concept, three names — carry the wrong key and the branch is dropped.
|
||||
- **`content` is base64 both ways — except under `withLines: true`.** Encode before a write, decode after a read; but with `withLines: true` `content` is already plain JSON text and the reported `"encoding": "base64"` is a lie. Decoding it yields garbage.
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ size. No recursion, no content, no `sha`.
|
||||
`get_repository_tree(owner, repo, tree_sha, recursive)`. Set `recursive: true` to walk
|
||||
subdirectories in one call.
|
||||
|
||||
The response sets `truncated: true` when one page does not hold every entry. Page through with
|
||||
`page`/`per_page` (defaults `1` and `30`) until a page returns fewer entries than `per_page`.
|
||||
The response sets `truncated: true` when one page doesn't hold every entry — page with
|
||||
`page`/`per_page` (defaults `1`/`30`) until a page returns fewer than `per_page`.
|
||||
|
||||
## Neither listing is a SHA source for a write
|
||||
|
||||
@@ -44,7 +44,6 @@ the canonical path for a write's SHA: one call returns the decoded content and t
|
||||
|
||||
## A 404 that is really a 403
|
||||
|
||||
These reads gate on `write:repository`, not on read access alone, and some Gitea endpoints answer
|
||||
an under-scoped token with 404 instead of 403 so they do not leak whether the resource exists. A
|
||||
404 on a path you are confident about is a scope problem until proven otherwise — check the token's
|
||||
configured scopes before concluding the file or directory does not exist.
|
||||
These reads gate on `write:repository`; an under-scoped token gets 404 instead of 403 so the
|
||||
endpoint doesn't leak whether the resource exists. On a path you're confident about, check token
|
||||
scope before concluding it doesn't exist.
|
||||
|
||||
@@ -14,7 +14,7 @@ compatibility: Requires Gitea MCP server configured with write:issue and write:r
|
||||
|
||||
metadata:
|
||||
category: integration
|
||||
version: "0.1.4"
|
||||
version: "0.1.5"
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
- gitea-mcp-slim-go
|
||||
@@ -29,17 +29,17 @@ allowed-tools: Bash mcp__gitea__list_issues mcp__gitea__issue_read mcp__gitea__i
|
||||
- **`list_issues` mixes in PRs unless you filter.** Issues and PRs share one number space; pass `type: "issues"` to exclude PRs (or `"pulls"`). `is_pull` is returned only by `issue_read method: "get"` — on a list item the only tell is `html_url`'s path segment (`/issues/` vs `/pulls/`).
|
||||
- **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 merge does not itself close the issue.** Gitea has no close-on-merge event, but a `Fixes #N` in the merged commits can, depending on merge style (`gitea-prs`). Re-read its 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.
|
||||
- **404 may mean 403.** Gitea hides permission errors as not-found — check `write:issue` scope before concluding the issue doesn't exist.
|
||||
|
||||
## Step 1 — Resolve owner and repo
|
||||
|
||||
An orchestrating caller may pass `owner` and `repo` in already, and the `search` row is cross-repository and needs only a query — both skip this step. Otherwise, before any tool call:
|
||||
Skip if an orchestrating caller already passed `owner`/`repo` in, or the action is `search` (cross-repository, needs only a query). Otherwise, before any tool call:
|
||||
|
||||
```bash
|
||||
rtk git remote get-url origin
|
||||
```
|
||||
|
||||
If origin is unset or the URL is not a Gitea URL, stop and report: "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
No origin, or not a Gitea URL: stop and report "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
|
||||
## Step 2 — Dispatch
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ list_issues owner: <owner> repo: <repo> state: "open" type: "issues"
|
||||
`updated_at`, and optionally `labels` (`[]string`), `milestone` (`{id, title}`), `ref`, `deadline`.
|
||||
Body and `closed_at` are omitted from list responses — call `issue_read method: "get"` for those.
|
||||
|
||||
Paginate with `page`/`per_page` until the returned count is less than `per_page`.
|
||||
Paginate: `page`/`per_page`, stop once the count is below `per_page`.
|
||||
|
||||
## `issue_read`
|
||||
|
||||
|
||||
@@ -16,30 +16,30 @@ metadata:
|
||||
- gitea-mcp-slim-go
|
||||
- context7-websites-gitea
|
||||
- context7-gitea-tea-cli
|
||||
version: "0.1.5"
|
||||
version: "0.1.6"
|
||||
|
||||
allowed-tools: Bash mcp__gitea__label_read mcp__gitea__label_write mcp__gitea__milestone_read mcp__gitea__milestone_write
|
||||
---
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Applying a label takes a numeric ID, but issue/PR responses slim labels down to name strings.** An issue's existing labels yield no IDs — resolve name → ID with `label_read`.
|
||||
- **`pull_request_read` returns `milestone` as a bare title string** where `issue_read` returns `{id, title}` — recover the milestone's ID by listing milestones and matching the title.
|
||||
- **Never assume a `Kind/*`/`Priority/*`/`Status/*` scope is exclusive — read each label's own `exclusive` field.** `list_repo_labels` returns it on every repo label, so it is always *readable* per label; `label_write` documents it as "(org only)" because it is only *settable* through the org create methods. Where it is `true` Gitea enforces one-per-scope itself, and replacing rather than stacking on a label whose `exclusive` is `false` destroys a valid label.
|
||||
- **Applying a label needs a numeric ID; issue/PR responses give only name strings.** Resolve name → ID with `label_read` first.
|
||||
- **`pull_request_read` returns `milestone` as a bare title string, `issue_read` as `{id, title}`.** Recover the ID by listing milestones and matching the title.
|
||||
- **Never assume a `Kind/*`/`Priority/*`/`Status/*` scope is exclusive — read each label's `exclusive` field.** `list_repo_labels` always returns it; `label_write` can only set it via org create methods ("org only"). `true` means Gitea enforces one-per-scope; replacing instead of stacking on a `false` label destroys a valid one.
|
||||
|
||||
## Step 1 — Resolve owner, repo and org
|
||||
|
||||
Before any tool call, extract `owner` and `repo` from the git remote (skip this if an orchestrating caller already passed them in):
|
||||
Extract `owner` and `repo` from the git remote before any tool call (skip if an orchestrating caller already passed them in):
|
||||
|
||||
```bash
|
||||
rtk git remote get-url origin
|
||||
```
|
||||
|
||||
If origin is not set or the URL is not a Gitea URL, stop and report: "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
No origin, or not a Gitea URL: stop and report "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
|
||||
The `*_org_label*` methods take `org`, not `owner`/`repo`. Pass that same `owner` as `org` — it is the org name whenever the owner is an organisation, and the remote URL does not say whether it is one.
|
||||
The `*_org_label*` methods take `org`, not `owner`/`repo`. Pass that same `owner` as `org` — it's the org name whenever the owner is an organisation, which the remote URL doesn't say.
|
||||
|
||||
Read the failure text before interpreting it. `list_org_labels` needs the `read:organization` token scope, which this skill's declared scopes (`write:issue`, `write:repository`) do not carry, so it fails with `token does not have at least one of required scope(s), required=[read:organization]` *before* it ever determines org-vs-user. Report that: the org pool went unchecked, not empty. Only a not-found response is evidence the owner is a user account with no org pool.
|
||||
Read the failure text before interpreting it: `list_org_labels` needs `read:organization`, which this skill's declared scopes don't carry, so it fails with a scope error *before* it ever checks org-vs-user. Report the unchecked scope, not an empty pool — only a genuine not-found means the owner is a user account with no org pool.
|
||||
|
||||
## Step 2 — Dispatch
|
||||
|
||||
@@ -58,6 +58,6 @@ Read the failure text before interpreting it. `list_org_labels` needs the `read:
|
||||
| Update / close a milestone | `milestone_write` | `"update"` |
|
||||
| Delete a milestone | `milestone_write` | `"delete"` |
|
||||
|
||||
Every list method paginates manually — `per_page` defaults to 30, so iterate `page: 1, 2, ...` until a page returns fewer results than `per_page`. A truncated list silently breaks name → ID resolution.
|
||||
Every list method paginates manually (`per_page` default 30) — iterate `page: 1, 2, ...` until a page returns fewer than `per_page`. A truncated list silently breaks name → ID resolution.
|
||||
|
||||
If the task is a label operation, read `references/labels.md`; if a milestone operation, read `references/milestones.md`. If the label to apply has to be derived from conversation context rather than named, read `references/label-inference.md`.
|
||||
|
||||
@@ -51,8 +51,8 @@ runtime error from Gitea rather than a client-side validation error.
|
||||
label_read method: "list_repo_labels" owner: <owner> repo: <repo> per_page: 50
|
||||
```
|
||||
|
||||
Paginate (`page: 1, 2, ...`) until the returned count is less than `per_page`. This is the only way
|
||||
to build a complete name → ID map — there is no lookup-by-name endpoint.
|
||||
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
|
||||
|
||||
@@ -19,7 +19,7 @@ metadata:
|
||||
- gitea-mcp-slim-go
|
||||
- context7-websites-gitea
|
||||
- context7-gitea-tea-cli
|
||||
version: "0.1.3"
|
||||
version: "0.1.4"
|
||||
|
||||
allowed-tools: Bash mcp__gitea__list_pull_requests mcp__gitea__pull_request_read mcp__gitea__pull_request_write mcp__gitea__pull_request_review_write
|
||||
---
|
||||
@@ -31,13 +31,13 @@ allowed-tools: Bash mcp__gitea__list_pull_requests mcp__gitea__pull_request_read
|
||||
|
||||
## Step 1 — Resolve owner and repo
|
||||
|
||||
Extract them from the git remote before any tool call, skipping this when an orchestrating caller already passed them in:
|
||||
Extract from the git remote before any tool call, skipping this when an orchestrating caller already passed them in:
|
||||
|
||||
```bash
|
||||
rtk git remote get-url origin
|
||||
```
|
||||
|
||||
If origin is not set or the URL is not a Gitea URL, stop and report: "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
No origin, or not a Gitea URL: stop and report "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
|
||||
## Step 2 — Dispatch
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ compatibility: Requires Gitea MCP server configured with a token with write:repo
|
||||
|
||||
metadata:
|
||||
category: integration
|
||||
version: "0.1.1"
|
||||
version: "0.1.2"
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
- gitea-mcp-slim-go
|
||||
@@ -33,13 +33,13 @@ allowed-tools: Bash mcp__gitea__list_releases mcp__gitea__get_release mcp__gitea
|
||||
|
||||
## Step 1 — Resolve owner and repo
|
||||
|
||||
`owner` and `repo` are required on every tool below. Extract them from the git remote, unless an orchestrating caller passed them in already:
|
||||
`owner` and `repo` are required on every tool below. Extract from the git remote, unless an orchestrating caller already passed them in:
|
||||
|
||||
```bash
|
||||
rtk git remote get-url origin
|
||||
```
|
||||
|
||||
If origin is not set or the URL is not a Gitea URL, stop and report: "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
No origin, or not a Gitea URL: stop and report "No Gitea remote found — set origin to your Gitea instance URL."
|
||||
|
||||
## Step 2 — Dispatch
|
||||
|
||||
@@ -68,6 +68,6 @@ These four are mutually exclusive — pick the one row the request lands on.
|
||||
| Create a release | Call `create_release` with `tag_name`, `target`, `title`, and `is_draft`/`is_pre_release` set explicitly — never left to default. This surface carries no update or edit tool, so a wrong flag is repairable only by delete-and-recreate (`references/conventions.md`). A separate `create_tag` is only needed to tag a commit without wrapping it in a release — whether `create_release` creates a missing tag is unconfirmed, so verify with `get_tag`. |
|
||||
| Delete a release | Resolve the numeric `id` per the first Gotcha, confirm intent, then call `delete_release`. The tag survives. |
|
||||
| Delete a tag along with its release | Delete the release first, then call `delete_tag` — confirm both are intended before proceeding, since each is irreversible on its own. |
|
||||
| List every page | Loop `page: 1, 2, 3...` until a response returns fewer than `per_page` entries. Nothing here auto-paginates. |
|
||||
| List every page | Loop `page: 1, 2, 3...` until a response returns fewer than `per_page` entries — nothing auto-paginates. |
|
||||
|
||||
If exact input params or response field shapes are needed, read `references/call-signatures.md`. If the caller raises semver tag naming, draft/prerelease semantics, release-notes sourcing, or how a release relates to its tag, read `references/conventions.md`.
|
||||
|
||||
@@ -70,7 +70,6 @@ id, tag_name, target, title, body, draft, prerelease, html_url, author, created_
|
||||
|
||||
## Pagination
|
||||
|
||||
None of the list tools auto-paginate. To collect a full result set, call with `page: 1`, then
|
||||
`page: 2`, etc., stopping when a page returns fewer items than `per_page`. `list_releases` and
|
||||
`list_tags` default `per_page` to 20 — lower than the 30-default used by most other gitea-mcp list
|
||||
tools, so a caller assuming 30 will under-count pages needed for a fixed total.
|
||||
Nothing auto-paginates. Loop `page: 1, 2, ...` until a page returns fewer items than `per_page`.
|
||||
`list_releases`/`list_tags` default `per_page` to 20, not the usual 30 — assuming 30 under-counts
|
||||
pages needed.
|
||||
|
||||
@@ -13,7 +13,7 @@ compatibility: Requires Gitea MCP server configured with a token; delegates all
|
||||
|
||||
metadata:
|
||||
category: integration
|
||||
version: "0.1.3"
|
||||
version: "0.1.4"
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
- gitea-mcp-slim-go
|
||||
|
||||
@@ -14,7 +14,7 @@ The user has referenced a bare number without saying "issue" or "PR" (e.g. "what
|
||||
2. Check the response's `is_pull` field:
|
||||
- `true` → it's a PR. Invoke `gitea-prs` for full PR detail (status, diff, reviews as appropriate to the request) and present that instead.
|
||||
- `false` or absent → it's an issue. Present the issue detail already retrieved.
|
||||
3. If the resolution call 404s, don't conclude the number doesn't exist. Gitea hides permission errors as not-found (documented in `gitea-issues`' Gotchas), so report the 404 and suggest verifying the token carries `write:issue` rather than reporting "no such issue or PR."
|
||||
3. A 404 here isn't proof the number doesn't exist — Gitea hides permission errors as not-found (see `gitea-issues` Gotchas). Report the 404 and suggest checking the token's `write:issue` scope rather than reporting "no such issue or PR."
|
||||
|
||||
If the user stated an action on the number rather than asking about it, resolution is only step one: hand the action, with the resolved domain, to `gitea-issues` or `gitea-prs` to carry out. Presenting detail is not a substitute for performing the write.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user