feat(kyberforge): add gitea dispatch skill with research docs
Adds the gitea skill to kyberforge — a dispatch skill for managing Defame1297/holocron via Gitea MCP from within Claude Code. Covers issues, PRs, milestones, labels, branches, and status. Owner/repo derived from git remote at runtime; no config required. Also adds research docs (api-reference, data-model, examples, overview, troubleshooting) and token-access reference used during authoring and available for runtime scope lookups. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
693
plugins/kyberforge/docs/research/docs/gitea/api-reference.md
Normal file
693
plugins/kyberforge/docs/research/docs/gitea/api-reference.md
Normal file
@@ -0,0 +1,693 @@
|
||||
---
|
||||
topic: api-reference
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
- gitea-mcp-slim-go
|
||||
---
|
||||
|
||||
# Gitea MCP — Tool Reference
|
||||
|
||||
Full parameter schemas and response shapes for all MCP tools. Tools marked `[W]` are write operations suppressed in `--read-only` mode. Parameters listed as `required*` are conditionally required depending on the `method` value.
|
||||
|
||||
---
|
||||
|
||||
## Issues
|
||||
|
||||
### `list_issues` [R]
|
||||
|
||||
List repository issues or pull requests.
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `state` (string, optional, default: `"all"`) — `"open"`, `"closed"`, `"all"`
|
||||
- `type` (string, optional) — `"issues"` or `"pulls"` to filter; omit for both
|
||||
- `labels` (array of strings, optional) — filter by label names
|
||||
- `milestones` (array, optional) — filter by milestone name or ID
|
||||
- `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)
|
||||
|
||||
**Response shape (list item):**
|
||||
```
|
||||
number, title, state, html_url, user (login), comments, created_at, updated_at
|
||||
labels? ([]string), milestone? ({id, title}), ref?, deadline?
|
||||
```
|
||||
Body and `closed_at` are omitted from list responses.
|
||||
|
||||
---
|
||||
|
||||
### `issue_read` [R]
|
||||
|
||||
Read a single issue's details, comments, or label list.
|
||||
|
||||
**Parameters:**
|
||||
- `method` (string, required) — `"get"` | `"get_comments"` | `"get_labels"`
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `issue_number` (number, required)
|
||||
|
||||
**Response shapes:**
|
||||
|
||||
`get` — full issue:
|
||||
```
|
||||
number, title, body, state, html_url, user, labels ([]string),
|
||||
comments, created_at, updated_at, closed_at
|
||||
assignees? ([]string), milestone? ({id, title}), ref?, deadline?,
|
||||
is_pull? (true — present only when backed by a PR)
|
||||
```
|
||||
|
||||
`get_comments` — array of:
|
||||
```
|
||||
id (int64), body, user, html_url, created_at, updated_at
|
||||
```
|
||||
|
||||
`get_labels` — array of label objects from the Gitea API (not slimmed, full label objects including id, name, color).
|
||||
|
||||
---
|
||||
|
||||
### `issue_write` [W]
|
||||
|
||||
Create or mutate an issue, its comments, or its labels.
|
||||
|
||||
**Parameters:**
|
||||
- `method` (string, required) — one of:
|
||||
`"create"` | `"update"` | `"add_comment"` | `"edit_comment"` | `"add_labels"` | `"remove_label"` | `"replace_labels"` | `"clear_labels"`
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `issue_number` (number, required for all except `"create"`)
|
||||
- `title` (string, required for `"create"`)
|
||||
- `body` (string, required for `"create"`, `"add_comment"`, `"edit_comment"`)
|
||||
- `assignees` (array of strings, optional) — login names
|
||||
- `milestone` (number, optional) — milestone ID (not title, not number)
|
||||
- `state` (string, optional) — `"open"` | `"closed"` | `"all"` (for `"update"`)
|
||||
- `commentID` (number, optional, required for `"edit_comment"`)
|
||||
- `labels` (array of numbers, optional) — label IDs (not names) for add/replace ops
|
||||
- `label_id` (number, optional, required for `"remove_label"`)
|
||||
- `ref` (string, optional) — branch association
|
||||
- `deadline` (string, optional) — ISO 8601
|
||||
- `remove_deadline` (boolean, optional)
|
||||
|
||||
**Critical:** `labels` takes IDs (numbers), not names. Must resolve label names to IDs via `label_read` before labeling.
|
||||
|
||||
---
|
||||
|
||||
### `search_issues` [R]
|
||||
|
||||
Search issues and PRs across repositories.
|
||||
|
||||
**Parameters:**
|
||||
- `query` (string, required)
|
||||
- `state` (string, optional) — `"open"` | `"closed"` | `"all"`
|
||||
- `type` (string, optional) — `"issues"` | `"pulls"`
|
||||
- `labels` (string, optional) — comma-separated label names
|
||||
- `owner` (string, optional) — restrict to owner
|
||||
- `page` (number, optional, default: 1)
|
||||
- `per_page` (number, optional, default: 30)
|
||||
|
||||
---
|
||||
|
||||
## Pull Requests
|
||||
|
||||
### `list_pull_requests` [R]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `state` (string, optional, default: `"all"`) — `"open"` | `"closed"` | `"all"`
|
||||
- `sort` (string, optional, default: `"recentupdate"`) — `"oldest"` | `"recentupdate"` | `"leastupdate"` | `"mostcomment"` | `"leastcomment"` | `"priority"`
|
||||
- `milestone` (number, optional) — milestone ID filter
|
||||
- `page` (number, optional, default: 1)
|
||||
- `per_page` (number, optional, default: 30)
|
||||
|
||||
**Response shape (list item — heavily trimmed):**
|
||||
```
|
||||
number, title, state, draft, merged, html_url, user, created_at, updated_at
|
||||
head? (ref string only), base? (ref string only), labels? ([]string)
|
||||
```
|
||||
Body, mergeable, comments, closed_at, and diff stats are omitted from list responses. Head/base are bare ref strings in the list, not objects.
|
||||
|
||||
---
|
||||
|
||||
### `pull_request_read` [R]
|
||||
|
||||
**Parameters:**
|
||||
- `method` (string, required) — `"get"` | `"get_diff"` | `"get_files"` | `"get_status"` | `"get_reviews"` | `"get_review"` | `"get_review_comments"`
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `pull_number` (number, required)
|
||||
- `review_id` (number, optional, required for `"get_review"` and `"get_review_comments"`)
|
||||
- `binary` (boolean, optional) — include binary diff
|
||||
- `page` (number, optional, default: 1)
|
||||
- `per_page` (number, optional, default: 30)
|
||||
|
||||
**Response shapes:**
|
||||
|
||||
`get` — full PR:
|
||||
```
|
||||
number, title, body, state, draft, merged, mergeable, html_url, user,
|
||||
labels ([]string), comments, created_at, updated_at, closed_at
|
||||
head? ({ref, sha, repo?: {full_name, description}}),
|
||||
base? ({ref, sha, repo?: {full_name, description}}),
|
||||
additions?, deletions?, changed_files?,
|
||||
merged_at?, merge_commit_sha?, merged_by?,
|
||||
assignees? ([]string),
|
||||
milestone? (string — title only, NOT an object),
|
||||
review_scomments? (int — note: misspelled key in source, not review_comments)
|
||||
```
|
||||
|
||||
`get_diff` — raw diff text
|
||||
|
||||
`get_files` — list of changed file objects
|
||||
|
||||
`get_status` — combined commit status for the PR head commit
|
||||
|
||||
`get_reviews` — array of review objects:
|
||||
```
|
||||
id, state, body, user (login), comments_count, submitted_at, html_url,
|
||||
stale (bool), official (bool), dismissed (bool)
|
||||
```
|
||||
|
||||
`get_review_comments` — array of inline review comments:
|
||||
```
|
||||
id, body, path, position (new line), old_position, diff_hunk,
|
||||
user (login), html_url, created_at, updated_at
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `pull_request_write` [W]
|
||||
|
||||
**Parameters:**
|
||||
- `method` (string, required) — `"create"` | `"update"` | `"close"` | `"reopen"` | `"merge"` | `"update_branch"` | `"add_reviewers"` | `"remove_reviewers"`
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `pull_number` (number, required except for `"create"`)
|
||||
- `title` (string, required for `"create"`, optional for `"update"` and `"merge"`)
|
||||
- `body` (string, required for `"create"`, optional for `"update"`)
|
||||
- `head` (string, required for `"create"`) — source branch; use `owner:branch` for cross-repo
|
||||
- `base` (string, required for `"create"`) — target branch
|
||||
- `assignee` (string, optional)
|
||||
- `assignees` (array of strings, optional)
|
||||
- `milestone` (number, optional) — milestone ID
|
||||
- `state` (string, optional) — `"open"` | `"closed"`
|
||||
- `allow_maintainer_edit` (boolean, optional)
|
||||
- `labels` (array of numbers, optional) — label IDs
|
||||
- `deadline` (string, optional) — ISO 8601
|
||||
- `remove_deadline` (boolean, optional)
|
||||
- `merge_style` (string, optional, default: `"merge"`) — `"merge"` | `"rebase"` | `"rebase-merge"` | `"squash"` | `"fast-forward-only"`
|
||||
- `message` (string, optional) — merge commit message or review dismissal reason
|
||||
- `delete_branch` (boolean, optional) — delete head branch after merge
|
||||
- `force_merge` (boolean, optional) — merge even if checks fail
|
||||
- `merge_when_checks_succeed` (boolean, optional)
|
||||
- `head_commit_id` (string, optional) — expected head SHA for conflict detection
|
||||
- `reviewers` (array of strings, optional) — login names
|
||||
- `team_reviewers` (array of strings, optional)
|
||||
- `draft` (boolean, optional) — marks PR as draft by prefixing title with `"WIP:"`
|
||||
|
||||
---
|
||||
|
||||
### `pull_request_review_write` [W]
|
||||
|
||||
**Parameters:**
|
||||
- `method` (string, required) — `"create"` | `"submit"` | `"delete"` | `"dismiss"`
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `pull_number` (number, required)
|
||||
- `review_id` (number, optional, required except for `"create"`)
|
||||
- `state` (string, optional) — `"APPROVED"` | `"REQUEST_CHANGES"` | `"COMMENT"` | `"PENDING"`
|
||||
- `body` (string, optional)
|
||||
- `commit_id` (string, optional) — for `"create"`; anchors inline comments to a commit
|
||||
- `message` (string, optional) — dismissal reason for `"dismiss"`
|
||||
- `comments` (array, optional) — inline comments for `"create"`:
|
||||
each object: `{path, body, old_line_num, new_line_num}`
|
||||
|
||||
---
|
||||
|
||||
## Labels
|
||||
|
||||
### `label_read` [R]
|
||||
|
||||
**Parameters:**
|
||||
- `method` (string, required) — `"list_repo_labels"` | `"get_repo_label"` | `"list_org_labels"`
|
||||
- `owner` (string, optional, required for repo methods)
|
||||
- `repo` (string, optional, required for repo methods)
|
||||
- `org` (string, optional, required for org methods)
|
||||
- `id` (number, optional, required for `"get_repo_label"`)
|
||||
- `page` (number, optional, default: 1)
|
||||
- `per_page` (number, optional, default: 30)
|
||||
|
||||
**Response:** Full label objects including `id`, `name`, `color`, `description`, `exclusive`, `is_archived`. Use this to map label names to IDs before write operations.
|
||||
|
||||
---
|
||||
|
||||
### `label_write` [W]
|
||||
|
||||
**Parameters:**
|
||||
- `method` (string, required) — `"create_repo_label"` | `"edit_repo_label"` | `"delete_repo_label"` | `"create_org_label"` | `"edit_org_label"` | `"delete_org_label"`
|
||||
- `owner` (string, optional, required for repo methods)
|
||||
- `repo` (string, optional, required for repo methods)
|
||||
- `org` (string, optional, required for org methods)
|
||||
- `id` (number, optional, required for edit/delete)
|
||||
- `name` (string, optional, required for create)
|
||||
- `color` (string, optional, required for create) — hex format `#RRGGBB`
|
||||
- `description` (string, optional)
|
||||
- `exclusive` (boolean, optional) — org labels only; makes label mutually exclusive within a group
|
||||
- `is_archived` (boolean, optional) — repo labels only
|
||||
|
||||
---
|
||||
|
||||
## Milestones
|
||||
|
||||
### `milestone_read` [R]
|
||||
|
||||
**Parameters:**
|
||||
- `method` (string, required) — `"get"` | `"list"`
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `id` (number, optional, required for `"get"`) — milestone ID
|
||||
- `state` (string, optional, default: `"all"`) — `"open"` | `"closed"` | `"all"`
|
||||
- `name` (string, optional) — filter by title for `"list"`
|
||||
- `page` (number, optional, default: 1)
|
||||
- `per_page` (number, optional, default: 30)
|
||||
|
||||
**Response:** Full milestone objects including `id`, `title`, `description`, `state`, `due_on`, `closed_at`, `open_issues`, `closed_issues`.
|
||||
|
||||
---
|
||||
|
||||
### `milestone_write` [W]
|
||||
|
||||
**Parameters:**
|
||||
- `method` (string, required) — `"create"` | `"update"` | `"edit"` | `"delete"`
|
||||
(`"update"` and `"edit"` are aliases for the same operation)
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `id` (number, optional, required for update/delete)
|
||||
- `title` (string, optional, required for create)
|
||||
- `description` (string, optional)
|
||||
- `due_on` (string, optional) — ISO 8601 date
|
||||
- `state` (string, optional) — `"open"` | `"closed"`
|
||||
|
||||
---
|
||||
|
||||
## Branches
|
||||
|
||||
### `list_branches` [R]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `page` (number, optional, default: 1)
|
||||
- `per_page` (number, optional, default: 30)
|
||||
|
||||
**Response shape per branch:**
|
||||
```
|
||||
name (string), protected (bool), commit_sha? (string — present when Commit != nil)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `create_branch` [W]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `branch` (string, required) — new branch name
|
||||
- `old_branch` (string, optional) — source branch; defaults to repo default branch
|
||||
|
||||
---
|
||||
|
||||
### `delete_branch` [W]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `branch` (string, required)
|
||||
|
||||
---
|
||||
|
||||
## Commits
|
||||
|
||||
### `list_commits` [R]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `sha` (string, optional) — starting SHA or branch name
|
||||
- `path` (string, optional) — filter commits touching this path
|
||||
- `page` (number, optional, default: 1, min: 1)
|
||||
- `per_page` (number, optional, default: 30, min: 1)
|
||||
|
||||
**Response shape per commit:**
|
||||
```
|
||||
sha, html_url, created
|
||||
message? (string — present when RepoCommit != nil),
|
||||
author? ({name, email, date} — present when RepoCommit.Author != nil)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `get_commit` [R]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `sha` (string, required)
|
||||
|
||||
**Response:** Same shape as list commit but always includes full detail.
|
||||
|
||||
---
|
||||
|
||||
## Files
|
||||
|
||||
### `get_file_contents` [R]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `ref` (string, required) — branch name, tag, or commit SHA
|
||||
- `path` (string, required)
|
||||
- `withLines` (boolean, optional) — return content with line numbers
|
||||
|
||||
**Response:**
|
||||
```
|
||||
name, path, sha, type, size
|
||||
content? (string, base64-encoded), encoding?, html_url?, download_url?
|
||||
```
|
||||
The `sha` in the response is required when updating or deleting this file.
|
||||
|
||||
---
|
||||
|
||||
### `create_or_update_file` [W]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `path` (string, required)
|
||||
- `content` (string, required) — base64-encoded file content
|
||||
- `message` (string, required) — commit message
|
||||
- `branch_name` (string, required) — target branch
|
||||
- `sha` (string, optional, required when updating an existing file) — current file SHA
|
||||
- `new_branch_name` (string, optional) — create a new branch during the operation
|
||||
|
||||
To update an existing file: must provide the file's current `sha` (get it from `get_file_contents` first). Without `sha`, Gitea treats the operation as a create and returns 409 if the file already exists.
|
||||
|
||||
---
|
||||
|
||||
### `delete_file` [W]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `path` (string, required)
|
||||
- `message` (string, required) — commit message
|
||||
- `branch_name` (string, required)
|
||||
- `sha` (string, required) — current file SHA; must match the server's current SHA
|
||||
|
||||
---
|
||||
|
||||
### `get_dir_contents` [R]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `ref` (string, required)
|
||||
- `path` (string, required)
|
||||
|
||||
**Response:** Array of directory entry objects:
|
||||
```
|
||||
name, path, type, size
|
||||
```
|
||||
No sha, no content, no URLs in directory listings.
|
||||
|
||||
---
|
||||
|
||||
### `get_repository_tree` [R]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `tree_sha` (string, required) — SHA, branch, or tag
|
||||
- `recursive` (boolean, optional) — recurse into subdirectories
|
||||
- `page` (number, optional, default: 1)
|
||||
- `per_page` (number, optional, default: 30)
|
||||
|
||||
**Response:**
|
||||
```
|
||||
{sha, truncated (bool), total_count (int), tree: [{path, mode, type, size, sha}, ...]}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Releases and Tags
|
||||
|
||||
### `list_releases` [R]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `is_draft` (boolean, optional)
|
||||
- `is_pre_release` (boolean, optional)
|
||||
- `page` (number, optional, default: 1, min: 1)
|
||||
- `per_page` (number, optional, default: 20, min: 1)
|
||||
|
||||
**Response shape per release:**
|
||||
```
|
||||
id, tag_name, target (commitish), title, body (from Note field),
|
||||
draft, prerelease, html_url, author (login), created_at, published_at
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `create_release` [W]
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `tag_name` (string, required)
|
||||
- `target` (string, required) — branch, tag, or commit SHA
|
||||
- `title` (string, required)
|
||||
- `is_draft` (boolean, optional)
|
||||
- `is_pre_release` (boolean, optional)
|
||||
- `body` (string, optional) — release notes
|
||||
|
||||
---
|
||||
|
||||
### `get_release` / `get_latest_release` [R]
|
||||
|
||||
`get_release` requires `id` (number). `get_latest_release` takes only `owner` and `repo`.
|
||||
|
||||
---
|
||||
|
||||
### `delete_release` [W]
|
||||
|
||||
- `owner`, `repo`, `id` (number) — release numeric ID from list/get response.
|
||||
|
||||
---
|
||||
|
||||
### Tag tools
|
||||
|
||||
**`list_tags`** — `owner`, `repo`, `page`, `per_page` (default 20). Response per tag: `name`, `commit_sha?`. Message is dropped from list responses.
|
||||
|
||||
**`get_tag`** — `owner`, `repo`, `tag_name`. Full response: `name`, `message`, `commit_sha?`.
|
||||
|
||||
**`create_tag`** [W] — `owner`, `repo`, `tag_name` (required), `target` (commitish, optional), `message` (optional).
|
||||
|
||||
**`delete_tag`** [W] — `owner`, `repo`, `tag_name`.
|
||||
|
||||
---
|
||||
|
||||
## Search
|
||||
|
||||
### `search_repos` [R]
|
||||
|
||||
- `query` (string, required)
|
||||
- `keywordIsTopic` (boolean, optional)
|
||||
- `keywordInDescription` (boolean, optional)
|
||||
- `ownerID` (number, optional) — filter by numeric user/org ID
|
||||
- `isPrivate` (boolean, optional)
|
||||
- `isArchived` (boolean, optional)
|
||||
- `sort`, `order` (string, optional)
|
||||
- `page`, `per_page` (default 30)
|
||||
|
||||
`search_repos` is the workaround for listing a user's repos when `read:user` scope is unavailable. Requires knowing the numeric `ownerID`.
|
||||
|
||||
---
|
||||
|
||||
### `search_users` [R]
|
||||
|
||||
- `query` (string, required)
|
||||
- `page`, `per_page` (default 30)
|
||||
|
||||
---
|
||||
|
||||
### `search_org_teams` [R]
|
||||
|
||||
- `org` (string, required)
|
||||
- `query` (string, required)
|
||||
- `includeDescription` (boolean, optional)
|
||||
- `page`, `per_page` (default 30)
|
||||
|
||||
---
|
||||
|
||||
## Repository Management
|
||||
|
||||
### `create_repo` [W]
|
||||
|
||||
- `name` (string, required)
|
||||
- `description`, `private`, `issue_labels`, `auto_init`, `template`, `gitignores`, `license`, `readme`, `default_branch`, `trust_model`, `object_format_name` (all optional)
|
||||
- `organization` (string, optional) — creates under org; defaults to personal account
|
||||
- `trust_model` — `"default"` | `"collaborator"` | `"committer"` | `"collaboratorcommitter"`
|
||||
- `object_format_name` — `"sha1"` | `"sha256"`
|
||||
|
||||
### `fork_repo` [W]
|
||||
|
||||
- `user` (string, required) — source repo owner
|
||||
- `repo` (string, required) — source repo name
|
||||
- `organization` (string, optional) — target org
|
||||
- `name` (string, optional) — fork name
|
||||
|
||||
### `list_my_repos` [R]
|
||||
|
||||
Requires `read:user` scope. Without it, use `search_repos`.
|
||||
|
||||
- `page`, `per_page` (default 30, min 1)
|
||||
|
||||
### `list_org_repos` [R]
|
||||
|
||||
- `org` (string, required)
|
||||
- `page`, `per_page` (default 100, min 1)
|
||||
|
||||
---
|
||||
|
||||
## User
|
||||
|
||||
### `get_me` [R]
|
||||
|
||||
No parameters. Returns current authenticated user. Requires `read:user` scope.
|
||||
|
||||
### `get_user_orgs` [R]
|
||||
|
||||
- `page`, `per_page` (default 30)
|
||||
|
||||
Requires `read:user` scope.
|
||||
|
||||
---
|
||||
|
||||
## Actions (CI)
|
||||
|
||||
### `actions_config_read` [R]
|
||||
|
||||
- `method` — `"list_repo_secrets"` | `"list_org_secrets"` | `"list_repo_variables"` | `"get_repo_variable"` | `"list_org_variables"` | `"get_org_variable"`
|
||||
- `owner`, `repo` (for repo methods), `org` (for org methods)
|
||||
- `name` (for get methods)
|
||||
- `page`, `per_page` (default 30, min 1)
|
||||
|
||||
### `actions_config_write` [W]
|
||||
|
||||
- `method` — `"upsert_repo_secret"` | `"delete_repo_secret"` | `"upsert_org_secret"` | `"delete_org_secret"` | `"create_repo_variable"` | `"update_repo_variable"` | `"delete_repo_variable"` | `"create_org_variable"` | `"update_org_variable"` | `"delete_org_variable"`
|
||||
- `name` (secret/variable name), `data` (secret value), `value` (variable value), `description` (optional)
|
||||
|
||||
### `actions_run_read` [R]
|
||||
|
||||
- `method` — `"list_workflows"` | `"get_workflow"` | `"list_runs"` | `"get_run"` | `"list_jobs"` | `"list_run_jobs"` | `"get_job_log_preview"` | `"download_job_log"`
|
||||
- `owner`, `repo` (required)
|
||||
- `workflow_id` (string) — workflow ID or filename
|
||||
- `run_id`, `job_id` (numbers) — for run/job-specific methods
|
||||
- `status` — filter for list methods
|
||||
- `tail_lines` (default 200, min 1), `max_bytes` (default 65536, min 1024) — for log methods
|
||||
- `output_path` — for `"download_job_log"`
|
||||
- `page`, `per_page` (default 30, min 1)
|
||||
|
||||
### `actions_run_write` [W]
|
||||
|
||||
- `method` — `"dispatch_workflow"` | `"cancel_run"` | `"rerun_run"`
|
||||
- `owner`, `repo` (required)
|
||||
- `workflow_id` (for dispatch), `ref` (branch/tag for dispatch), `inputs` (object for dispatch)
|
||||
- `run_id` (for cancel/rerun)
|
||||
|
||||
---
|
||||
|
||||
## Notifications
|
||||
|
||||
### `notification_read` [R]
|
||||
|
||||
- `method` — `"list"` | `"get"`
|
||||
- `owner`, `repo` (optional, scopes to repo)
|
||||
- `id` (thread ID for `"get"`)
|
||||
- `status` — `"unread"` | `"read"` | `"pinned"`
|
||||
- `subject_type` — `"Issue"` | `"Pull"` | `"Commit"` | `"Repository"`
|
||||
- `since`, `before` (ISO 8601)
|
||||
- `page`, `per_page` (default 30)
|
||||
|
||||
### `notification_write` [W]
|
||||
|
||||
- `method` — `"mark_read"` | `"mark_all_read"`
|
||||
- `id` (thread ID for `"mark_read"`)
|
||||
- `owner`, `repo` (optional scope)
|
||||
- `last_read_at` (ISO 8601, defaults to now)
|
||||
|
||||
---
|
||||
|
||||
## Time Tracking
|
||||
|
||||
### `timetracking_read` [R]
|
||||
|
||||
- `method` — `"list_issue_times"` | `"list_repo_times"` | `"get_my_stopwatches"` | `"get_my_times"`
|
||||
- `owner`, `repo` (for list methods)
|
||||
- `issue_number` (for `"list_issue_times"`)
|
||||
- `page`, `per_page` (default 30)
|
||||
|
||||
### `timetracking_write` [W]
|
||||
|
||||
- `method` — `"start_stopwatch"` | `"stop_stopwatch"` | `"delete_stopwatch"` | `"add_time"` | `"delete_time"`
|
||||
- `owner`, `repo`, `issue_number` (optional depending on method)
|
||||
- `time` (seconds, for `"add_time"`)
|
||||
- `id` (entry ID, for `"delete_time"`)
|
||||
|
||||
---
|
||||
|
||||
## Packages
|
||||
|
||||
### `package_read` [R]
|
||||
|
||||
- `method` — `"list"` | `"list_versions"` | `"get"`
|
||||
- `owner` (user or org, required)
|
||||
- `type` (package type: `"container"` | `"npm"` | `"maven"` | `"pypi"` | `"cargo"` | `"generic"`) — required except for `"list"`
|
||||
- `name` (package name, slashes auto-encoded) — required except for `"list"`
|
||||
- `version` — for `"get"`
|
||||
- `q` (search query)
|
||||
- `page`, `per_page` (default 30, min 1)
|
||||
|
||||
### `package_write` [W]
|
||||
|
||||
- `method` — `"delete"` (only operation; irreversible)
|
||||
- `owner`, `type`, `name`, `version` (all required)
|
||||
|
||||
---
|
||||
|
||||
## Wiki
|
||||
|
||||
### `wiki_read` [R]
|
||||
|
||||
- `method` — `"list"` | `"get"` | `"get_revisions"`
|
||||
- `owner`, `repo` (required)
|
||||
- `pageName` (for `"get"` and `"get_revisions"`)
|
||||
|
||||
### `wiki_write` [W]
|
||||
|
||||
- `method` — `"create"` | `"update"` | `"delete"`
|
||||
- `owner`, `repo` (required)
|
||||
- `pageName` (required for update/delete)
|
||||
- `title` (required for create)
|
||||
- `content` (for create/update)
|
||||
- `message` (commit message)
|
||||
|
||||
---
|
||||
|
||||
## Version
|
||||
|
||||
### `get_gitea_mcp_server_version` [R]
|
||||
|
||||
No parameters. Returns the running server version string.
|
||||
87
plugins/kyberforge/docs/research/docs/gitea/data-model.md
Normal file
87
plugins/kyberforge/docs/research/docs/gitea/data-model.md
Normal file
@@ -0,0 +1,87 @@
|
||||
---
|
||||
topic: data-model
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
- gitea-mcp-slim-go
|
||||
---
|
||||
|
||||
# Gitea Data Model
|
||||
|
||||
How issues, PRs, labels, milestones, and branches relate to each other — and the representation quirks that affect how you call tools.
|
||||
|
||||
## Issues and PRs share a number space
|
||||
|
||||
Issues and pull requests are the same entity type in Gitea's data model. They share a single sequential counter per repository: if issue #3 exists, there cannot be a PR #3 in the same repo. The `list_issues` tool returns both unless you pass `type: "issues"` or `type: "pulls"` to filter. A single-item `issue_read` response includes `is_pull: true` when the issue is backed by a pull request.
|
||||
|
||||
This matters for cross-linking: when you refer to `#5`, it might be either an issue or a PR. Use `issue_read method: "get"` and check `is_pull` to determine the type before deciding how to handle it.
|
||||
|
||||
## Label identity: names vs IDs
|
||||
|
||||
Labels have two identifiers that appear in different contexts:
|
||||
|
||||
- **Name** (string) — what appears in `issue_read` and `list_issues` responses; `labels: ["bug", "wontfix"]`
|
||||
- **ID** (number) — what `issue_write` requires when applying labels; `labels: [3, 7]`
|
||||
|
||||
This mismatch is the single most common source of errors when managing labels. The MCP server slims label data in issue/PR responses to name-only strings. To apply labels to an issue or PR, you must first call `label_read method: "list_repo_labels"` to get the full label list (including IDs), then extract the IDs for the labels you want to apply.
|
||||
|
||||
The only tool that returns full label objects (including ID, color, description) is `label_read`.
|
||||
|
||||
## Milestone references
|
||||
|
||||
Milestones are repo-scoped and have both an **ID** and a sequential **number** within the repo. The tools use the numeric **ID** for all references:
|
||||
|
||||
- `issue_write` takes `milestone: <id>` (not a title, not a number)
|
||||
- `milestone_read method: "get"` takes `id: <id>`
|
||||
|
||||
Milestone representations differ between issue and PR responses:
|
||||
- In `issue_read` responses: `milestone: {id, title}` — an object with both fields
|
||||
- In `pull_request_read` responses: `milestone: "title string"` — the title only, no ID
|
||||
|
||||
This inconsistency means you cannot extract a milestone's ID from a PR response. To get the milestone ID from a PR, you must look up milestones via `milestone_read method: "list"` and match by title.
|
||||
|
||||
## Label scope: repo vs org
|
||||
|
||||
Labels exist at two scopes:
|
||||
- **Repo labels** — the default; scoped to a single repository; managed via `label_read/write` with `owner` + `repo`
|
||||
- **Org labels** — scoped to an organization; shared across repos in the org; managed via `label_read/write` with `org`
|
||||
|
||||
Org labels have an additional `exclusive` boolean. When `exclusive: true`, applying one label in an exclusive group removes all other exclusive labels from the same group on the issue. This is Gitea's equivalent of a single-select category field.
|
||||
|
||||
When listing labels for labeling purposes, repo labels and org labels are listed separately. Issues in a repo can carry both.
|
||||
|
||||
## PR branches and cross-repo forks
|
||||
|
||||
For a PR within the same repository, `head` is just a branch name. For cross-repo PRs (from a fork), `head` uses the format `owner:branch`.
|
||||
|
||||
In `pull_request_write method: "create"`:
|
||||
- `head` — the source (feature branch or fork branch)
|
||||
- `base` — the merge target (usually `main` or `master`)
|
||||
|
||||
In `pull_request_read method: "get"` responses, `head` and `base` are full objects: `{ref, sha, repo: {full_name, description}}`. In `list_pull_requests` responses, they are bare ref strings.
|
||||
|
||||
## File SHA requirement
|
||||
|
||||
File operations in Gitea use SHA-based optimistic concurrency. To update or delete an existing file, you must provide the file's current `sha` — a content-addressed identifier returned by `get_file_contents`. Without it:
|
||||
- `create_or_update_file` without `sha` is treated as a create; Gitea returns 409 if the file exists
|
||||
- `delete_file` without `sha` returns a validation error
|
||||
|
||||
The workflow is always: `get_file_contents` → extract `sha` → pass to `create_or_update_file` or `delete_file`.
|
||||
|
||||
## Commit association on issues
|
||||
|
||||
Issues optionally carry a `ref` field — a branch name that associates the issue with ongoing work. This is set via `issue_write method: "create"` or `"update"` with the `ref` parameter. It is informational only; it does not create a branch or affect PR linking.
|
||||
|
||||
## PR review states
|
||||
|
||||
PR reviews move through a state machine:
|
||||
1. Create a review in `"PENDING"` state (drafting inline comments)
|
||||
2. Submit the review with a state: `"APPROVED"`, `"REQUEST_CHANGES"`, or `"COMMENT"`
|
||||
3. A submitted review can be dismissed (not deleted)
|
||||
|
||||
The `stale` boolean on a review indicates the PR was pushed to after the review was submitted, making the review potentially outdated.
|
||||
|
||||
## Pagination and truncation
|
||||
|
||||
Repository tree (`get_repository_tree`) returns a `truncated: bool` field alongside `total_count`. When `truncated` is true, not all tree entries fit in one response — use `page` + `per_page` to paginate.
|
||||
|
||||
All list endpoints use cursor-less offset pagination (`page` integer). There is no `next_cursor` or `Link` header exposed through the MCP tools — iterate by incrementing `page` until you get fewer results than `per_page`.
|
||||
193
plugins/kyberforge/docs/research/docs/gitea/examples.md
Normal file
193
plugins/kyberforge/docs/research/docs/gitea/examples.md
Normal file
@@ -0,0 +1,193 @@
|
||||
---
|
||||
topic: examples
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
- gitea-mcp-slim-go
|
||||
---
|
||||
|
||||
# Gitea MCP — Common Workflow Patterns
|
||||
|
||||
Canonical call sequences for the operations most likely to appear in a Gitea-managing skill.
|
||||
|
||||
## Create an issue with labels and a milestone
|
||||
|
||||
Labels and milestones must be referenced by numeric ID in write operations. Resolve them first.
|
||||
|
||||
```
|
||||
1. label_read method: "list_repo_labels" owner: "Defame1297" repo: "holocron"
|
||||
→ returns [{id: 3, name: "bug"}, {id: 7, name: "enhancement"}, ...]
|
||||
|
||||
2. milestone_read method: "list" owner: "Defame1297" repo: "holocron"
|
||||
→ returns [{id: 1, title: "v1.0"}, ...]
|
||||
|
||||
3. issue_write method: "create"
|
||||
owner: "Defame1297" repo: "holocron"
|
||||
title: "Fix the widget"
|
||||
body: "Description of the problem"
|
||||
labels: [3] ← IDs, not names
|
||||
milestone: 1 ← milestone ID
|
||||
assignees: ["alice"]
|
||||
```
|
||||
|
||||
## Apply labels to an existing issue
|
||||
|
||||
```
|
||||
1. label_read method: "list_repo_labels" owner: ... repo: ...
|
||||
→ map name → id for the labels you want
|
||||
|
||||
2. issue_write method: "add_labels"
|
||||
owner: ... repo: ...
|
||||
issue_number: 42
|
||||
labels: [3, 7] ← IDs
|
||||
```
|
||||
|
||||
To replace all labels atomically (remove existing, set new):
|
||||
|
||||
```
|
||||
issue_write method: "replace_labels"
|
||||
issue_number: 42
|
||||
labels: [3, 7]
|
||||
```
|
||||
|
||||
To remove a single label:
|
||||
|
||||
```
|
||||
issue_write method: "remove_label"
|
||||
issue_number: 42
|
||||
label_id: 3 ← singular, not the array form
|
||||
```
|
||||
|
||||
## Create a feature branch, push a file, open a PR
|
||||
|
||||
```
|
||||
1. create_branch
|
||||
owner: "Defame1297" repo: "holocron"
|
||||
branch: "feat/my-feature"
|
||||
old_branch: "main" ← defaults to repo default if omitted
|
||||
|
||||
2. get_file_contents (only needed if updating an existing file)
|
||||
owner: ... repo: ... ref: "feat/my-feature" path: "README.md"
|
||||
→ note the sha field
|
||||
|
||||
3. create_or_update_file
|
||||
owner: ... repo: ...
|
||||
path: "README.md"
|
||||
content: "<base64-encoded content>"
|
||||
message: "feat: update README"
|
||||
branch_name: "feat/my-feature"
|
||||
sha: "<sha from step 2>" ← required when updating; omit only for new files
|
||||
|
||||
4. pull_request_write method: "create"
|
||||
owner: ... repo: ...
|
||||
title: "feat: my feature"
|
||||
body: "Description of changes"
|
||||
head: "feat/my-feature"
|
||||
base: "main"
|
||||
labels: [7] ← label IDs, if desired
|
||||
milestone: 1
|
||||
reviewers: ["alice"]
|
||||
```
|
||||
|
||||
## Merge a PR and clean up
|
||||
|
||||
```
|
||||
1. pull_request_read method: "get_status"
|
||||
owner: ... repo: ... pull_number: 12
|
||||
→ check that status is passing before merge
|
||||
|
||||
2. pull_request_write method: "merge"
|
||||
owner: ... repo: ... pull_number: 12
|
||||
merge_style: "squash" ← or "merge", "rebase", etc.
|
||||
message: "feat: my feature (#12)"
|
||||
delete_branch: true ← clean up the feature branch post-merge
|
||||
```
|
||||
|
||||
## Close an issue when a PR merges
|
||||
|
||||
Issues are not automatically closed when a PR merges in Gitea (unlike GitHub). Close them explicitly after merge:
|
||||
|
||||
```
|
||||
issue_write method: "update"
|
||||
owner: ... repo: ...
|
||||
issue_number: 5
|
||||
state: "closed"
|
||||
```
|
||||
|
||||
## Create and manage a milestone
|
||||
|
||||
```
|
||||
1. milestone_write method: "create"
|
||||
owner: ... repo: ...
|
||||
title: "v1.0"
|
||||
description: "First stable release"
|
||||
due_on: "2025-03-01T00:00:00Z"
|
||||
|
||||
2. Assign issues to it:
|
||||
issue_write method: "update"
|
||||
issue_number: 42
|
||||
milestone: <id from step 1>
|
||||
|
||||
3. Close it when done:
|
||||
milestone_write method: "update"
|
||||
id: <milestone id>
|
||||
state: "closed"
|
||||
```
|
||||
|
||||
## List open PRs linked to a milestone
|
||||
|
||||
```
|
||||
list_pull_requests
|
||||
owner: ... repo: ...
|
||||
state: "open"
|
||||
milestone: <milestone id>
|
||||
```
|
||||
|
||||
Note: `list_pull_requests` response items carry `milestone` as a bare title string, not an object. You cannot filter by milestone ID from the PR list response alone — pass the milestone ID as a query parameter instead.
|
||||
|
||||
## Resolve label name → ID without listing all labels
|
||||
|
||||
There is no direct lookup-by-name endpoint exposed through the MCP tools. The pattern is always:
|
||||
|
||||
```
|
||||
label_read method: "list_repo_labels" per_page: 50
|
||||
→ scan results for the target name → extract id
|
||||
```
|
||||
|
||||
If you have more than 50 labels, paginate until found.
|
||||
|
||||
## Submit a code review
|
||||
|
||||
```
|
||||
1. pull_request_review_write method: "create"
|
||||
pull_number: 12
|
||||
state: "PENDING"
|
||||
commit_id: "<head SHA from PR get response>"
|
||||
comments: [
|
||||
{path: "src/foo.go", body: "Consider extracting this", new_line_num: 42}
|
||||
]
|
||||
→ returns review_id
|
||||
|
||||
2. pull_request_review_write method: "submit"
|
||||
pull_number: 12
|
||||
review_id: <from step 1>
|
||||
state: "REQUEST_CHANGES"
|
||||
body: "A few nits, see inline comments"
|
||||
```
|
||||
|
||||
## Update a file when you don't know the current SHA
|
||||
|
||||
SHA is mandatory for file updates. If you skipped storing it:
|
||||
|
||||
```
|
||||
get_file_contents
|
||||
owner: ... repo: ...
|
||||
ref: "main"
|
||||
path: "the/file.md"
|
||||
→ extract sha from response
|
||||
|
||||
create_or_update_file
|
||||
...
|
||||
sha: <extracted sha>
|
||||
```
|
||||
|
||||
Do not guess or omit the SHA — the request will fail or create a duplicate.
|
||||
65
plugins/kyberforge/docs/research/docs/gitea/overview.md
Normal file
65
plugins/kyberforge/docs/research/docs/gitea/overview.md
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
topic: overview
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
---
|
||||
|
||||
# Gitea MCP Server — Overview
|
||||
|
||||
The Gitea MCP server (gitea-mcp v1.3.0) wraps the Gitea REST API and exposes it as 55 MCP tools. It runs as a stdio process and is launched with `go run gitea.com/gitea/gitea-mcp@latest -t stdio`. The skill author interacts with it entirely through MCP tool calls — no direct HTTP or shell access is required.
|
||||
|
||||
## Tool registry architecture
|
||||
|
||||
Tools are split into two registries at startup: 31 read-only tools and 24 write tools. The `--read-only` flag suppresses all write tools; the `--tools` flag accepts a comma-separated allowlist and filters out any tool not named. In normal use (no flags), all 55 tools are available.
|
||||
|
||||
Many tools use a **method dispatch** pattern: a single MCP tool exposes multiple operations through a required `method` enum parameter. For example, `issue_write` handles `create`, `update`, `add_comment`, `edit_comment`, `add_labels`, `remove_label`, `replace_labels`, and `clear_labels`. This keeps the tool surface smaller while multiplexing related mutations. The `method` parameter is always required for dispatch tools and must be one of the documented enum values.
|
||||
|
||||
## Naming and parameter conventions
|
||||
|
||||
All repo-scoped tools require `owner` (string, the Gitea username or org) and `repo` (string, the repository name). These are always required and positional — never omit them.
|
||||
|
||||
Pagination is consistent across list tools: `page` (default 1) and `per_page` (default 30 for most tools, 20 for releases, 100 for org repos). Results are not automatically paginated — the caller must iterate pages.
|
||||
|
||||
Timestamps use ISO 8601 format (`2024-01-15T10:00:00Z`) for both input parameters (`since`, `before`, `deadline`, `due_on`) and response fields.
|
||||
|
||||
## Token scopes and tool availability
|
||||
|
||||
Three token scopes gate different tool groups:
|
||||
|
||||
- `write:issue` — enables issue, comment, label, and milestone operations (read and write)
|
||||
- `write:repository` — enables PR, branch, file, release, and tag operations (read and write, because Gitea gates reads behind write scope for these)
|
||||
- `read:user` — required for `get_me`, `list_my_repos`, `get_user_orgs`; absent from the default token config
|
||||
|
||||
Tools that require `read:user` but are called without it return an error or empty result. The workaround for repo discovery without `read:user` is `search_repos` with an `ownerID` filter, though `ownerID` requires knowing the numeric user ID in advance.
|
||||
|
||||
## Response shape philosophy
|
||||
|
||||
The MCP server returns **slimmed** response objects, not the full Gitea API JSON. Key simplifications:
|
||||
|
||||
- User fields are always a bare login string, never a user object
|
||||
- Label fields are always a flat array of name strings (`["bug", "enhancement"]`), never label objects
|
||||
- List responses drop `body` (description text) and some metadata fields to reduce token payload
|
||||
- Single-item responses (get by ID or number) include full detail including body
|
||||
|
||||
This means you cannot get a user's display name or label colors from issue/PR responses — only the login or label name.
|
||||
|
||||
## Domain grouping
|
||||
|
||||
Tools are organized into these functional domains, each covered in detail in `api-reference.md`:
|
||||
|
||||
- **Issues** — `list_issues`, `search_issues`, `issue_read`, `issue_write`
|
||||
- **Pull Requests** — `list_pull_requests`, `pull_request_read`, `pull_request_write`, `pull_request_review_write`
|
||||
- **Labels** — `label_read`, `label_write`
|
||||
- **Milestones** — `milestone_read`, `milestone_write`
|
||||
- **Branches** — `list_branches`, `create_branch`, `delete_branch`
|
||||
- **Files** — `get_file_contents`, `get_dir_contents`, `create_or_update_file`, `delete_file`, `get_repository_tree`
|
||||
- **Commits** — `list_commits`, `get_commit`
|
||||
- **Releases / Tags** — `list_releases`, `get_release`, `get_latest_release`, `create_release`, `delete_release`, `list_tags`, `get_tag`, `create_tag`, `delete_tag`
|
||||
- **Search** — `search_repos`, `search_issues`, `search_users`, `search_org_teams`
|
||||
- **Repos** — `create_repo`, `fork_repo`, `list_my_repos`, `list_org_repos`
|
||||
- **User / Orgs** — `get_me`, `get_user_orgs`
|
||||
- **Actions (CI)** — `actions_config_read`, `actions_config_write`, `actions_run_read`, `actions_run_write`
|
||||
- **Notifications** — `notification_read`, `notification_write`
|
||||
- **Time Tracking** — `timetracking_read`, `timetracking_write`
|
||||
- **Packages** — `package_read`, `package_write`
|
||||
- **Wiki** — `wiki_read`, `wiki_write`
|
||||
22
plugins/kyberforge/docs/research/docs/gitea/sources.md
Normal file
22
plugins/kyberforge/docs/research/docs/gitea/sources.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Sources
|
||||
|
||||
## gitea-mcp-repo
|
||||
|
||||
- **URL:** https://gitea.com/gitea/gitea-mcp
|
||||
- **Description:** Official gitea-mcp repository (v1.3.0); operation/*.go source files documenting all 55 MCP tools, their parameters, and CLI flags
|
||||
- **Contributing files:** overview.md, api-reference.md, data-model.md, examples.md, troubleshooting.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## gitea-mcp-slim-go
|
||||
|
||||
- **URL:** https://gitea.com/gitea/gitea-mcp/raw/branch/main/operation/issue/slim.go, https://gitea.com/gitea/gitea-mcp/raw/branch/main/operation/pull/slim.go, https://gitea.com/gitea/gitea-mcp/raw/branch/main/operation/repo/slim.go
|
||||
- **Description:** Slim response shape structs from gitea-mcp source; defines exactly which fields the MCP server returns for issues, PRs, branches, commits, tags, releases, and files
|
||||
- **Contributing files:** api-reference.md, data-model.md, examples.md, troubleshooting.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## gitea-api-docs
|
||||
|
||||
- **URL:** https://docs.gitea.com/api/1.20/
|
||||
- **Description:** Gitea REST API swagger documentation covering underlying endpoints for issues, PRs, labels, milestones, and branches
|
||||
- **Contributing files:** (see notes below)
|
||||
- **Status:** `no content extracted` — source fetch timed out; all reference content derived from gitea-mcp source files which are authoritative for MCP tool usage
|
||||
@@ -0,0 +1,96 @@
|
||||
---
|
||||
topic: troubleshooting
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
- gitea-mcp-slim-go
|
||||
---
|
||||
|
||||
# Gitea MCP — Troubleshooting
|
||||
|
||||
Known gotchas, source-level bugs, and error patterns for skill authors.
|
||||
|
||||
## Source-level typo: `review_scomments`
|
||||
|
||||
The `pull_request_read method: "get"` response includes a field called `review_scomments` (not `review_comments`). This is a misspelling in the slim.go source code of gitea-mcp v1.3.0. Do not expect `review_comments` to be present — the field is `review_scomments`. This is the count of inline review comments.
|
||||
|
||||
## Label ID vs name confusion
|
||||
|
||||
`issue_write` (methods: `add_labels`, `replace_labels`) takes `labels` as an array of **numbers** (IDs). Issue and PR read responses return labels as an array of **name strings**. These are never interchangeable.
|
||||
|
||||
If you pass name strings to `labels`, the call will either fail validation or silently apply no labels. Always resolve names to IDs first via `label_read method: "list_repo_labels"`.
|
||||
|
||||
## Milestone representation inconsistency
|
||||
|
||||
The `milestone` field in responses differs by entity type:
|
||||
- `issue_read` response: `milestone: {id: 1, title: "v1.0"}` — object
|
||||
- `pull_request_read` response: `milestone: "v1.0"` — string (title only)
|
||||
|
||||
You cannot get a milestone's ID from a PR response. If you need the ID, call `milestone_read method: "list"` and match by title.
|
||||
|
||||
## File update requires current SHA
|
||||
|
||||
`create_or_update_file` and `delete_file` both require the file's current content SHA. Without it:
|
||||
- Updating: Gitea treats the call as a create. If the file exists, returns HTTP 409 (Conflict).
|
||||
- Deleting: returns HTTP 422 (Unprocessable entity) — the SHA is a required field.
|
||||
|
||||
Always call `get_file_contents` first to retrieve the SHA. The SHA is in the `sha` field of the response (not `content.sha` — it's top-level).
|
||||
|
||||
## `list_my_repos` requires `read:user` scope
|
||||
|
||||
With only `write:issue` and `write:repository` scopes, `list_my_repos` returns an error. Use `search_repos` with an `ownerID` filter instead. The `ownerID` is the numeric user ID — you cannot get it from `get_me` either (same `read:user` requirement). If ownerID is unknown, use `search_repos` with the username in the query.
|
||||
|
||||
## `get_me` requires `read:user` scope
|
||||
|
||||
There is no way to discover the current user's identity (login, ID) with `write:issue` + `write:repository` scopes only. Hardcode the owner/username in the skill or require it as an input parameter.
|
||||
|
||||
## Method dispatch: `"update"` vs `"edit"` on milestones
|
||||
|
||||
`milestone_write` accepts both `"update"` and `"edit"` as method values for updating a milestone — they map to the same operation. Use `"update"` for consistency with the issue and PR tools.
|
||||
|
||||
## Draft PR behavior
|
||||
|
||||
`pull_request_write method: "create"` with `draft: true` implements draft by prepending `"WIP:"` to the PR title (not via a dedicated Gitea API flag). This means:
|
||||
- The title returned by the API will have the `"WIP:"` prefix
|
||||
- To un-draft, use `"update"` and pass the title without the prefix
|
||||
|
||||
This differs from GitHub's draft PR mechanism; draft state is not a first-class boolean field.
|
||||
|
||||
## `delete_release` takes numeric ID, not tag name
|
||||
|
||||
`delete_release` requires the numeric `id` from the release object, not the `tag_name` string. Call `list_releases` or `get_release` first to get the numeric ID.
|
||||
|
||||
## Cross-repo PR `head` format
|
||||
|
||||
For PRs originating from a fork, `head` must be `"fork-owner:branch-name"`. Using just the branch name will result in Gitea looking for the branch in the base repo and failing with 422.
|
||||
|
||||
## Pagination is not automatic
|
||||
|
||||
List tools return one page at a time. There is no cursor, `Link` header, or auto-pagination in the MCP layer. When you need complete results (e.g., all labels to build a name→ID map), iterate `page: 1`, `page: 2`, etc. until the result count is less than `per_page`.
|
||||
|
||||
## HTTP error patterns
|
||||
|
||||
The MCP server surfaces HTTP error codes from the Gitea REST API:
|
||||
|
||||
| Code | Meaning in this context |
|
||||
|---|---|
|
||||
| 401 | Token is invalid, expired, or missing entirely |
|
||||
| 403 | Token lacks the required scope for this operation |
|
||||
| 404 | Resource not found — also returned by some endpoints when scope is insufficient |
|
||||
| 409 | Conflict — file already exists (create without SHA), branch already exists, duplicate PR |
|
||||
| 422 | Unprocessable entity — missing required field (e.g. SHA on file ops), invalid enum value |
|
||||
| 500 | Gitea server error — usually transient |
|
||||
|
||||
404 can mask a permissions error: some Gitea endpoints return 404 instead of 403 when the token has insufficient scope, to avoid leaking resource existence.
|
||||
|
||||
## `list_issues` with `milestones` filter
|
||||
|
||||
The `milestones` parameter on `list_issues` accepts milestone names or IDs as an array. Using IDs is more reliable — milestone names are mutable. Always prefer filtering by milestone ID when programmatically filtering.
|
||||
|
||||
## `per_page` defaults vary
|
||||
|
||||
Not all endpoints share the same default `per_page`:
|
||||
- Most tools: 30
|
||||
- `list_releases`, `list_tags`: 20
|
||||
- `list_org_repos`: 100
|
||||
|
||||
When building result-count-aware logic, do not assume 30 — check the tool's documented default.
|
||||
Reference in New Issue
Block a user