diff --git a/plugins/gitea/skills/gitea-releases/README.md b/plugins/gitea/skills/gitea-releases/README.md index 83227d3..4a23a7d 100644 --- a/plugins/gitea/skills/gitea-releases/README.md +++ b/plugins/gitea/skills/gitea-releases/README.md @@ -19,6 +19,6 @@ Describe your release/tag task: list releases, get the latest release, create a | File | Purpose | |------|---------| | `SKILL.md` | Skill instructions for agents | -| `references/call-signatures.md` | Verified tool parameters and response shapes for all 9 release/tag tools | +| `references/call-signatures.md` | Tool parameters and response shapes derived from gitea-mcp source (see `references/sources.md`); input params for 3 of the 9 tools additionally live-cross-checked | | `references/conventions.md` | Semver/draft/prerelease practitioner conventions and pagination behavior | | `references/sources.md` | Research sources backing the call signatures and conventions | diff --git a/plugins/gitea/skills/gitea-releases/SKILL.md b/plugins/gitea/skills/gitea-releases/SKILL.md index 85f961a..cee7096 100644 --- a/plugins/gitea/skills/gitea-releases/SKILL.md +++ b/plugins/gitea/skills/gitea-releases/SKILL.md @@ -23,7 +23,7 @@ metadata: - **`delete_release` takes a numeric `id`, never a tag name.** `delete_tag` is the mirror opposite — it takes the `tag_name` string, never a numeric id. These two tools are asymmetric on purpose; passing a tag name to `delete_release` or a numeric id to `delete_tag` fails. Always resolve the numeric release id via `list_releases` or `get_release` first if you only have a tag name in hand. - **Deleting a release does not delete its tag.** They are separate destructive operations against separate resources — a release is a wrapper (title, notes, draft/prerelease flags, assets) around a tag, not the tag itself. If the intent is to remove both, call `delete_release` and `delete_tag` separately. - **`list_releases`/`list_tags` default to `per_page: 20`**, unlike most other gitea-mcp tools which default to 30. There is no auto-pagination in the MCP layer — to get a complete result set, loop `page` upward until a page returns fewer than `per_page` results. -- **`draft`/`is_pre_release` are explicit booleans the caller sets on `create_release` — never inferred from `tag_name`.** Practitioner convention (per the `tea` CLI) uses `-beta`/`-rc` suffixes for prereleases (e.g. `v2.0.0-beta.1`), but Gitea does not enforce or infer this from the tag string. If the user names a tag that looks like a prerelease, set `is_pre_release: true` explicitly rather than assuming the flag is redundant with the name. +- **`is_draft`/`is_pre_release` are explicit booleans the caller sets on `create_release` — never inferred from `tag_name`.** Note the input param is `is_draft`, which maps to the `draft` field on the *response* object (see Dispatch table below and `references/call-signatures.md`) — `draft` is never a valid input key. Practitioner convention (per the `tea` CLI) uses `-beta`/`-rc` suffixes for prereleases (e.g. `v2.0.0-beta.1`), but Gitea does not enforce or infer this from the tag string. If the user names a tag that looks like a prerelease, set `is_pre_release: true` explicitly rather than assuming the flag is redundant with the name. - **Tag names are conventionally semver, `v`-prefixed** (`v1.2.0`, `v2.0.0-beta.1`), but this is a practitioner convention, not a Gitea constraint — don't reject or rewrite a caller-supplied tag name that doesn't follow it. ## Dispatch table @@ -44,7 +44,7 @@ metadata: ## Workflow -- [ ] **Creating a release:** Call `create_release` directly with `tag_name` + `target` + `title` — it creates the underlying tag automatically if `tag_name` doesn't already exist, so a separate `create_tag` call is only needed when you want to tag a commit without wrapping it in a release yet. Set `is_pre_release`/`is_draft` explicitly per the Gotchas above; don't leave them to default inference. +- [ ] **Creating a release:** Call `create_release` directly with `tag_name` + `target` + `title` — Gitea is assumed to create the underlying tag automatically if `tag_name` doesn't already exist (this is plausible behavior inferred from the API shape, not directly confirmed in the research docs), so a separate `create_tag` call is only needed when you want to tag a commit without wrapping it in a release yet. Verify the tag exists afterward if this matters to the caller. Set `is_pre_release`/`is_draft` explicitly per the Gotchas above; don't leave them to default inference. - [ ] **Deleting a release safely:** Resolve the numeric id first — call `list_releases` (paginate if needed, see Gotchas) or `get_release` if the id is already known, find the entry matching the target `tag_name`, then call `delete_release` with that `id`. Never pass `tag_name` to `delete_release`. - [ ] **Deleting a tag along with its release:** Delete the release first (frees the id lookup), then call `delete_tag` with the `tag_name` separately — confirm both are intended before proceeding, since each is an independent irreversible operation. - [ ] **Listing completely:** If the caller needs all releases or tags (not just the first page), loop `page: 1, 2, 3...` until a response has fewer than `per_page` entries. diff --git a/plugins/gitea/skills/gitea-releases/references/call-signatures.md b/plugins/gitea/skills/gitea-releases/references/call-signatures.md index c84ee3b..62667db 100644 --- a/plugins/gitea/skills/gitea-releases/references/call-signatures.md +++ b/plugins/gitea/skills/gitea-releases/references/call-signatures.md @@ -7,9 +7,18 @@ source_keys: # Release and tag call signatures -Verified against the live MCP tool schemas at authoring time (not copied from upstream API docs, -which can drift from the deployed gitea-mcp version). `owner` and `repo` are required strings on -every tool below and are omitted from the per-tool lists for brevity. +Signatures and response shapes are derived from gitea-mcp source (`operation/*.go` and `slim.go`, +see `references/sources.md`) rather than copied from upstream API docs, which can drift from the +deployed gitea-mcp version — but this is a source-code extraction, not a live MCP tool call. + +Input parameter schemas for 3 of the 9 tools here — `create_release`, `delete_tag`, and +`get_latest_release` — were additionally cross-checked live via `ToolSearch` against the deployed +`mcp__gitea__*` tools in session 2026-07-05, and confirmed to match exactly (required/optional +params and names). That check covered only input params for those 3 tools, not response shapes, +and not the other 6 tools — treat the rest of this document as source-derived, not live-verified. + +`owner` and `repo` are required strings on every tool below and are omitted from the per-tool lists +for brevity. ## Releases @@ -23,12 +32,12 @@ every tool below and are omitted from the per-tool lists for brevity. **`get_latest_release`** - No parameters beyond `owner`/`repo`. -- Returns a single release object for the most recently published (non-draft, non-prerelease by Gitea's own "latest" definition) release. +- Returns a single release object for the most recently published release. It is assumed (by analogy with typical "latest release" semantics) that this excludes drafts and prereleases, but that exclusion is not directly confirmed by any of the research docs — verify with `list_releases` if the caller depends on this. **`create_release`** - Required: `tag_name` (string), `target` (string — branch, tag, or commit SHA to cut the tag from), `title` (string) - Optional: `body` (string — release notes), `is_draft` (boolean), `is_pre_release` (boolean) -- If `tag_name` doesn't already exist as a tag, Gitea creates it against `target` as part of this call. +- Assumed (not confirmed by the research docs) that if `tag_name` doesn't already exist as a tag, Gitea creates it against `target` as part of this call. Verify with `get_tag`/`list_tags` afterward if the caller needs certainty. **`delete_release`** - Required: `id` (number) — same numeric id as `get_release`. Does not accept `tag_name`. @@ -56,7 +65,7 @@ id, tag_name, target, title, body, draft, prerelease, html_url, author, created_ **`delete_tag`** - Required: `tag_name` (string). Does not accept a numeric id. -- Does not delete any release wrapping the tag. +- Assumed by symmetry with `delete_release` (documented above as not deleting the underlying tag) to also not delete any release wrapping the tag — but this reverse direction is not independently confirmed by the research docs, and is the more dangerous direction to get wrong: an agent might skip an explicit `delete_release` call assuming the release survives. Verify with `list_releases`/`get_release` after calling `delete_tag` rather than assume. ## Pagination diff --git a/plugins/gitea/skills/gitea-releases/references/conventions.md b/plugins/gitea/skills/gitea-releases/references/conventions.md index eb5690c..b8cf75f 100644 --- a/plugins/gitea/skills/gitea-releases/references/conventions.md +++ b/plugins/gitea/skills/gitea-releases/references/conventions.md @@ -27,11 +27,15 @@ caller-supplied tag name against semver; just pass it through. ## Draft and prerelease are explicit flags -`draft` and `is_pre_release`/`prerelease` are booleans the caller sets directly on `create_release` -— Gitea does not infer either from the tag name, even though the `-beta`/`-rc` suffix convention -above is commonly used to signal a prerelease to humans. When a user asks to "cut a beta" or -"publish a release candidate," set `is_pre_release: true` explicitly in the same call rather than -relying on the tag string to carry that meaning. +`is_draft` and `is_pre_release` are booleans the caller sets directly on `create_release` — Gitea +does not infer either from the tag name, even though the `-beta`/`-rc` suffix convention above is +commonly used to signal a prerelease to humans. When a user asks to "cut a beta" or "publish a +release candidate," set `is_pre_release: true` explicitly in the same call rather than relying on +the tag string to carry that meaning. + +Note the input/output naming mismatch: the input param is `is_draft`, but the release object +returned by the API uses `draft` (and `prerelease`) as the field names. `draft` is never a valid +input key — passing `draft: true` to `create_release` is silently ignored rather than erroring. ## Release notes sourcing