chore: merge dev into main � MCP underscore convention + new features #1

Merged
jmiller merged 6 commits from dev into main 2026-05-19 19:59:35 +00:00
7 changed files with 219 additions and 1184 deletions
-857
View File
@@ -1,857 +0,0 @@
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
SPDX-License-Identifier: GPL-3.0-or-later
DEFGROUP: gitea-api-mcp.Documentation
REPO: https://git.mokoconsulting.tech/MokoConsulting/gitea-api-mcp
-->
# API Reference
Full parameter reference for all 61 tools in gitea-api-mcp.
All tools accept an optional `connection` parameter (string) to select a named connection from your config. If omitted, the default connection is used.
## Table of Contents
- [User / Auth](#user--auth)
- [Repositories](#repositories)
- [File Contents](#file-contents)
- [Branches](#branches)
- [Commits](#commits)
- [Issues](#issues)
- [Labels](#labels)
- [Milestones](#milestones)
- [Pull Requests](#pull-requests)
- [Releases](#releases)
- [Tags](#tags)
- [Actions](#actions)
- [Organizations](#organizations)
- [Users](#users)
- [Webhooks](#webhooks)
- [Wiki](#wiki)
- [Notifications](#notifications)
- [Generic](#generic)
---
## User / Auth
### gitea_me
Get the authenticated user info.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `connection` | string | No | Named connection from config |
### gitea_user_orgs
List organizations the authenticated user belongs to.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_user_repos
List repositories owned by the authenticated user.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
---
## Repositories
### gitea_repo_get
Get repository details.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `connection` | string | No | Named connection from config |
### gitea_repo_create
Create a new repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `name` | string | Yes | Repository name |
| `org` | string | No | Organization (omit for personal) |
| `description` | string | No | Description |
| `private` | boolean | No | Private repository |
| `auto_init` | boolean | No | Initialize with README |
| `default_branch` | string | No | Default branch (default "main") |
| `template` | boolean | No | Mark as template repository |
| `connection` | string | No | Named connection from config |
### gitea_repo_delete
Delete a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `connection` | string | No | Named connection from config |
### gitea_repo_edit
Edit repository settings.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `description` | string | No | New description |
| `private` | boolean | No | Set private/public |
| `has_issues` | boolean | No | Enable issues |
| `has_wiki` | boolean | No | Enable wiki |
| `has_pull_requests` | boolean | No | Enable PRs |
| `default_branch` | string | No | Default branch |
| `archived` | boolean | No | Archive/unarchive |
| `connection` | string | No | Named connection from config |
### gitea_repo_fork
Fork a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `organization` | string | No | Fork to this org (omit for personal) |
| `name` | string | No | Custom name for fork |
| `connection` | string | No | Named connection from config |
### gitea_repo_search
Search repositories.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `q` | string | Yes | Search query |
| `topic` | boolean | No | Search in topics |
| `sort` | string | No | Sort field: `alpha`, `created`, `updated`, `size`, `stars`, `forks` |
| `order` | string | No | Sort order: `asc`, `desc` |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_org_repos
List repositories in an organization.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `org` | string | Yes | Organization name |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_list_connections
List configured Gitea connections.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| *(none)* | | | |
---
## File Contents
### gitea_file_get
Get file contents from a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `filepath` | string | Yes | File path (e.g. "src/index.ts") |
| `ref` | string | No | Branch/tag/commit (default: default branch) |
| `connection` | string | No | Named connection from config |
### gitea_dir_get
Get directory contents (file listing) from a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `dirpath` | string | No | Directory path (default: root) |
| `ref` | string | No | Branch/tag/commit |
| `connection` | string | No | Named connection from config |
### gitea_file_create_or_update
Create or update a file in a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `filepath` | string | Yes | File path |
| `content` | string | Yes | File content (will be base64-encoded automatically) |
| `message` | string | Yes | Commit message |
| `branch` | string | No | Branch (default: default branch) |
| `sha` | string | No | SHA of existing file (required for updates) |
| `connection` | string | No | Named connection from config |
### gitea_file_delete
Delete a file from a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `filepath` | string | Yes | File path to delete |
| `sha` | string | Yes | SHA of file to delete |
| `message` | string | Yes | Commit message |
| `branch` | string | No | Branch |
| `connection` | string | No | Named connection from config |
### gitea_tree_get
Get the git tree for a repository (recursive file listing).
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `sha` | string | Yes | Tree SHA or branch name |
| `recursive` | boolean | No | Recursive listing (default true) |
| `connection` | string | No | Named connection from config |
---
## Branches
### gitea_branches_list
List branches in a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_branch_get
Get a specific branch.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `branch` | string | Yes | Branch name |
| `connection` | string | No | Named connection from config |
### gitea_branch_create
Create a new branch.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `new_branch_name` | string | Yes | Name for new branch |
| `old_branch_name` | string | No | Source branch (default: default branch) |
| `connection` | string | No | Named connection from config |
### gitea_branch_delete
Delete a branch.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `branch` | string | Yes | Branch name |
| `connection` | string | No | Named connection from config |
---
## Commits
### gitea_commits_list
List commits in a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `sha` | string | No | Branch or commit SHA |
| `path` | string | No | Filter by file path |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_commit_get
Get a specific commit.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `sha` | string | Yes | Commit SHA |
| `connection` | string | No | Named connection from config |
---
## Issues
### gitea_issues_list
List issues in a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `state` | string | No | Issue state filter: `open`, `closed`, `all` |
| `type` | string | No | Filter by type: `issues`, `pulls` |
| `labels` | string | No | Comma-separated label names |
| `milestones` | string | No | Comma-separated milestone names |
| `q` | string | No | Search query |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_issue_get
Get a single issue by number.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `number` | number | Yes | Issue number |
| `connection` | string | No | Named connection from config |
### gitea_issue_create
Create a new issue.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `title` | string | Yes | Issue title |
| `body` | string | No | Issue body (markdown) |
| `labels` | number[] | No | Label IDs |
| `milestone` | number | No | Milestone ID |
| `assignees` | string[] | No | Usernames to assign |
| `connection` | string | No | Named connection from config |
### gitea_issue_update
Update an issue.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `number` | number | Yes | Issue number |
| `title` | string | No | New title |
| `body` | string | No | New body |
| `state` | string | No | State: `open`, `closed` |
| `assignees` | string[] | No | Assignees |
| `milestone` | number | No | Milestone ID |
| `connection` | string | No | Named connection from config |
### gitea_issue_comments_list
List comments on an issue.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `number` | number | Yes | Issue number |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_issue_comment_create
Add a comment to an issue.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `number` | number | Yes | Issue number |
| `body` | string | Yes | Comment body (markdown) |
| `connection` | string | No | Named connection from config |
### gitea_issue_search
Search issues across all repositories.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `q` | string | Yes | Search query |
| `state` | string | No | State filter: `open`, `closed`, `all` |
| `labels` | string | No | Comma-separated label IDs |
| `type` | string | No | Filter type: `issues`, `pulls` |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
---
## Labels
### gitea_labels_list
List labels in a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_label_create
Create a label.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `name` | string | Yes | Label name |
| `color` | string | Yes | Color hex (e.g. "#d73a4a") |
| `description` | string | No | Label description |
| `connection` | string | No | Named connection from config |
---
## Milestones
### gitea_milestones_list
List milestones in a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `state` | string | No | State filter: `open`, `closed`, `all` |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_milestone_create
Create a milestone.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `title` | string | Yes | Milestone title |
| `description` | string | No | Description |
| `due_on` | string | No | Due date (ISO 8601) |
| `connection` | string | No | Named connection from config |
---
## Pull Requests
### gitea_pulls_list
List pull requests.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `state` | string | No | State filter: `open`, `closed`, `all` |
| `sort` | string | No | Sort: `oldest`, `recentupdate`, `leastupdate`, `mostcomment`, `leastcomment`, `priority` |
| `labels` | string | No | Comma-separated label IDs |
| `milestone` | number | No | Milestone ID |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_pull_get
Get a single pull request.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `number` | number | Yes | PR number |
| `connection` | string | No | Named connection from config |
### gitea_pull_create
Create a pull request.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `title` | string | Yes | PR title |
| `head` | string | Yes | Source branch |
| `base` | string | Yes | Target branch |
| `body` | string | No | PR description (markdown) |
| `labels` | number[] | No | Label IDs |
| `milestone` | number | No | Milestone ID |
| `assignees` | string[] | No | Assignees |
| `connection` | string | No | Named connection from config |
### gitea_pull_merge
Merge a pull request.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `number` | number | Yes | PR number |
| `merge_type` | string | No | Merge method: `merge`, `rebase`, `squash`, `rebase-merge` (default: merge) |
| `title` | string | No | Custom merge commit title |
| `message` | string | No | Custom merge commit message |
| `delete_branch_after_merge` | boolean | No | Delete head branch after merge |
| `connection` | string | No | Named connection from config |
### gitea_pull_files
List files changed in a pull request.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `number` | number | Yes | PR number |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_pull_review_create
Create a pull request review.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `number` | number | Yes | PR number |
| `event` | string | Yes | Review action: `APPROVED`, `REQUEST_CHANGES`, `COMMENT` |
| `body` | string | No | Review comment |
| `connection` | string | No | Named connection from config |
---
## Releases
### gitea_releases_list
List releases.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_release_get
Get a single release by ID.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `id` | number | Yes | Release ID |
| `connection` | string | No | Named connection from config |
### gitea_release_latest
Get the latest release.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `connection` | string | No | Named connection from config |
### gitea_release_create
Create a new release.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `tag_name` | string | Yes | Tag name (e.g. "v1.0.0") |
| `name` | string | No | Release title |
| `body` | string | No | Release notes (markdown) |
| `target_commitish` | string | No | Target branch/commit |
| `draft` | boolean | No | Create as draft |
| `prerelease` | boolean | No | Mark as prerelease |
| `connection` | string | No | Named connection from config |
### gitea_release_delete
Delete a release.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `id` | number | Yes | Release ID |
| `connection` | string | No | Named connection from config |
---
## Tags
### gitea_tags_list
List tags.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_tag_create
Create a tag.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `tag_name` | string | Yes | Tag name |
| `target` | string | No | Target branch/commit SHA |
| `message` | string | No | Tag message (annotated tag) |
| `connection` | string | No | Named connection from config |
### gitea_tag_delete
Delete a tag.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `tag` | string | Yes | Tag name |
| `connection` | string | No | Named connection from config |
---
## Actions
### gitea_actions_runs_list
List workflow runs for a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_actions_run_get
Get a specific workflow run.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `run_id` | number | Yes | Run ID |
| `connection` | string | No | Named connection from config |
---
## Organizations
### gitea_org_get
Get organization details.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `org` | string | Yes | Organization name |
| `connection` | string | No | Named connection from config |
### gitea_org_teams_list
List teams in an organization.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `org` | string | Yes | Organization name |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_org_members_list
List members of an organization.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `org` | string | Yes | Organization name |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
---
## Users
### gitea_user_get
Get a user profile.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `username` | string | Yes | Username |
| `connection` | string | No | Named connection from config |
### gitea_users_search
Search users.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `q` | string | Yes | Search query |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
---
## Webhooks
### gitea_webhooks_list
List webhooks for a repository.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_webhook_create
Create a webhook.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `type` | string | Yes | Hook type: `gitea`, `slack`, `discord`, `dingtalk`, `telegram`, `msteams`, `feishu`, `matrix`, `wechatwork`, `packagist` |
| `url` | string | Yes | Webhook URL |
| `events` | string[] | No | Events to listen for (e.g. `["push", "pull_request"]`) |
| `active` | boolean | No | Active status |
| `connection` | string | No | Named connection from config |
---
## Wiki
### gitea_wiki_pages_list
List wiki pages.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_wiki_page_get
Get a wiki page.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `owner` | string | Yes | Repository owner (user or org) |
| `repo` | string | Yes | Repository name |
| `page_name` | string | Yes | Page name/slug |
| `connection` | string | No | Named connection from config |
---
## Notifications
### gitea_notifications_list
List notifications for the authenticated user.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `status_types` | string | No | Comma-separated: `read`, `unread`, `pinned` |
| `page` | number | No | Page number (1-based) |
| `limit` | number | No | Items per page (max 50) |
| `connection` | string | No | Named connection from config |
### gitea_notifications_read
Mark all notifications as read.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `connection` | string | No | Named connection from config |
---
## Generic
### gitea_api_request
Make a raw API request to any Gitea v1 endpoint.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `method` | string | Yes | HTTP method: `GET`, `POST`, `PUT`, `PATCH`, `DELETE` |
| `endpoint` | string | Yes | API endpoint path (e.g. "/repos/owner/repo") |
| `body` | object | No | Request body |
| `params` | object | No | Query parameters |
| `connection` | string | No | Named connection from config |
### gitea_list_connections
List configured Gitea connections.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| *(none)* | | | |
-140
View File
@@ -1,140 +0,0 @@
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
SPDX-License-Identifier: GPL-3.0-or-later
DEFGROUP: gitea-api-mcp.Documentation
REPO: https://git.mokoconsulting.tech/MokoConsulting/gitea-api-mcp
-->
# Architecture
## Component Overview
```
src/
index.ts -- MCP server entry point, tool registrations (61 tools)
client.ts -- HTTP client for Gitea REST API v1
config.ts -- Configuration loader (multi-connection support)
types.ts -- TypeScript type definitions
```
### index.ts -- Server Entry Point
The main module that:
- Creates the `McpServer` instance with stdio transport
- Loads configuration on startup via `loadConfig()`
- Registers all 61 tools organized by category
- Provides shared parameter schemas (`OwnerRepo`, `PaginationParams`, `ConnectionParam`)
- Routes tool calls through `clientFor(connection)` to resolve the target Gitea instance
- Formats all API responses through `formatResponse()` for consistent MCP output
### client.ts -- HTTP Client
`GiteaClient` is a zero-dependency HTTP client built on `node:https` and `node:http`:
- Prepends `/api/v1` to all endpoint paths
- Sets `Authorization: token <token>` header on every request (Gitea's native auth format)
- Supports `GET`, `POST`, `PUT`, `PATCH`, `DELETE` methods
- Handles query parameter construction via `URL.searchParams`
- Parses JSON responses automatically
- 30-second request timeout
- Optional TLS certificate verification bypass (`insecure` flag)
### config.ts -- Configuration Loader
Loads the connection configuration from disk:
- Default path: `~/.gitea-api-mcp.json`
- Override via `GITEA_API_MCP_CONFIG` environment variable
- Validates that at least one connection exists
- Sets `defaultConnection` to the first connection if not explicitly specified
- `getConnection()` resolves a named connection or falls back to the default
### types.ts -- Type Definitions
Three core interfaces:
- `GiteaConnection` -- Single connection config (`baseUrl`, `token`, `insecure?`)
- `GiteaConfig` -- Full config with named connections map and default
- `ApiResponse` -- Standardized response wrapper (`status`, `data`)
## Design Decisions
### Token Authentication
Gitea uses `Authorization: token <access-token>` as its native authentication header format, unlike GitHub's `Bearer` token format. This server uses the native Gitea format directly, ensuring compatibility with all Gitea versions without requiring OAuth2 setup.
### Multi-Connection Architecture
Every tool accepts an optional `connection` parameter. This enables:
- Managing multiple Gitea instances from a single MCP server
- Switching between production, staging, and development instances
- Cross-instance operations within a single Claude Code session
The connection is resolved at call time, not at startup, so different tool calls can target different instances.
### node:https (Zero HTTP Dependencies)
The HTTP client uses Node.js built-in `node:https` and `node:http` modules instead of third-party libraries (e.g., axios, node-fetch). This decision:
- Eliminates supply-chain risk from HTTP client dependencies
- Reduces `node_modules` size
- Avoids compatibility issues across Node.js versions
- Provides full control over TLS configuration (needed for `insecure` flag)
### Stdio Transport
The MCP server uses stdio transport (stdin/stdout) rather than HTTP/SSE. This means:
- No network ports are opened by the server
- Tokens are never exposed through HTTP endpoints
- The server runs as a child process of the MCP client
- Communication is process-local, reducing attack surface
### Shared Parameter Objects
Common parameter patterns are defined as reusable objects:
- `OwnerRepo` -- `{ owner, repo }` for all repository-scoped operations
- `PaginationParams` -- `{ page, limit }` for all list endpoints
- `ConnectionParam` -- `{ connection }` for multi-connection routing
This ensures consistency across all 61 tools and simplifies adding new tools.
## Data Flow
```
+-----------------+
| Claude Code / |
| MCP Client |
+--------+--------+
|
stdio (JSON-RPC)
|
+--------v--------+
| index.ts |
| McpServer |
| (tool router) |
+--------+--------+
|
+-----------+-----------+
| |
+------v------+ +-------v-------+
| config.ts | | client.ts |
| loadConfig | | GiteaClient |
| getConn | | (HTTP calls) |
+------+------+ +-------+-------+
| |
+------v------+ HTTPS / HTTP
| ~/.gitea- | |
| api-mcp.json| +--------v--------+
+-------------+ | Gitea Instance |
| /api/v1/* |
+-----------------+
```
1. Claude Code sends a JSON-RPC tool call over stdio
2. `McpServer` routes the call to the registered tool handler
3. The handler calls `clientFor(connection)` which resolves the connection from config
4. `GiteaClient` constructs the HTTP request and sends it to the Gitea API
5. The JSON response is wrapped in `formatResponse()` and returned to the MCP client
-166
View File
@@ -1,166 +0,0 @@
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
SPDX-License-Identifier: GPL-3.0-or-later
DEFGROUP: gitea-api-mcp.Documentation
REPO: https://git.mokoconsulting.tech/MokoConsulting/gitea-api-mcp
-->
# Installation Guide
## Prerequisites
- **Node.js** >= 20.0.0 ([download](https://nodejs.org))
- **npm** (included with Node.js)
- A **Gitea instance** with API access enabled
- A **Gitea access token** with appropriate scopes
## Install
### Clone and Build
```bash
git clone https://git.mokoconsulting.tech/MokoConsulting/gitea-api-mcp.git
cd gitea-api-mcp
npm install
npm run build
```
The compiled output is placed in `dist/index.js`.
### Verify the Build
```bash
node dist/index.js --help
```
## Gitea Token Generation
1. Log in to your Gitea instance (e.g., `https://git.mokoconsulting.tech`)
2. Navigate to **Settings** (click your avatar, top-right corner)
3. Select **Applications** from the sidebar
4. Under **Manage Access Tokens**, enter a descriptive token name (e.g., `mcp-server`)
5. Select the required permission scopes:
- `repo` -- for repository operations
- `admin:org` -- for organization management
- `notification` -- for notification tools
- `user` -- for user profile operations
- `issue` -- for issue and pull request tools
- `package` -- if using package-related endpoints
6. Click **Generate Token**
7. **Copy the token immediately** -- it will not be displayed again
## Configuration
### Config File Format
Create `~/.gitea-api-mcp.json`:
```json
{
"defaultConnection": "moko",
"connections": {
"moko": {
"baseUrl": "https://git.mokoconsulting.tech",
"token": "your-gitea-access-token",
"insecure": false
}
}
}
```
### Config Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `defaultConnection` | string | No | Name of the default connection (defaults to the first one) |
| `connections` | object | Yes | Map of named connections |
| `connections.<name>.baseUrl` | string | Yes | Base URL of the Gitea instance (no trailing slash) |
| `connections.<name>.token` | string | Yes | Gitea API access token |
| `connections.<name>.insecure` | boolean | No | Skip TLS certificate verification (default: `false`) |
### Custom Config Path
Override the default config location with an environment variable:
```bash
export GITEA_API_MCP_CONFIG=/path/to/custom-config.json
```
### File Permissions
Secure your config file since it contains API tokens:
```bash
chmod 600 ~/.gitea-api-mcp.json
```
## Claude Code Registration
### Project-Level (`.mcp.json`)
Create or edit `.mcp.json` in your project root:
```json
{
"mcpServers": {
"gitea-moko": {
"command": "node",
"args": ["/absolute/path/to/gitea-api-mcp/dist/index.js"]
}
}
}
```
### Global-Level (`~/.claude/claude_desktop_config.json`)
```json
{
"mcpServers": {
"gitea-moko": {
"command": "node",
"args": ["/absolute/path/to/gitea-api-mcp/dist/index.js"]
}
}
}
```
After registering, restart Claude Code or run `/mcp` to verify the server is connected.
## Troubleshooting
### "Failed to load config" Error
- Verify `~/.gitea-api-mcp.json` exists and is valid JSON
- Check that at least one connection is defined in `connections`
- If using `GITEA_API_MCP_CONFIG`, verify the path is correct and the file is readable
### "Connection not found" Error
- The `connection` parameter you passed does not match any key in `connections`
- Run `gitea_list_connections` to see available connections
- Check for typos in the connection name
### Authentication Failures (HTTP 401)
- Verify your token is correct and has not expired
- Ensure the token has the required scopes for the operation
- Check that the `baseUrl` points to the correct Gitea instance
- Confirm the Gitea instance has API access enabled (admin setting)
### TLS / Certificate Errors
- For self-signed certificates, set `"insecure": true` in the connection config
- Ensure the Gitea instance URL uses the correct protocol (`https://` vs `http://`)
### Timeout Errors
- The default request timeout is 30 seconds
- Check network connectivity to the Gitea instance
- Verify the Gitea instance is running and responsive
- For large responses (e.g., recursive tree listings), consider pagination
### MCP Server Not Appearing in Claude Code
- Ensure the path in your MCP config is an absolute path to `dist/index.js`
- Verify the build completed successfully (`npm run build`)
- Check that Node.js >= 20.0.0 is in your PATH
- Restart Claude Code after modifying MCP configuration
-20
View File
@@ -1,20 +0,0 @@
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
SPDX-License-Identifier: GPL-3.0-or-later
DEFGROUP: gitea-api-mcp.Documentation
REPO: https://git.mokoconsulting.tech/MokoConsulting/gitea-api-mcp
-->
# gitea-api-mcp Documentation
## Contents
- [INSTALLATION.md](INSTALLATION.md) -- Prerequisites, installation, configuration, and troubleshooting
- [ARCHITECTURE.md](ARCHITECTURE.md) -- Component overview, design decisions, and data flow
- [API.md](API.md) -- Full parameter reference for all 61 tools
## Project-Level Documentation
- [README](../README.md) -- Project overview, quick start, and tool tables
- [CHANGELOG](../CHANGELOG.md) -- Version history and release notes
- [CONTRIBUTING](../CONTRIBUTING.md) -- Development guidelines and contribution process
- [SECURITY](../SECURITY.md) -- Security policy and token storage best practices
+1 -1
View File
@@ -18,7 +18,7 @@ import { resolve } from 'node:path';
import { homedir } from 'node:os';
import type { GiteaConfig, GiteaConnection } from './types.js';
const CONFIG_FILENAME = '.gitea-api-mcp.json';
const CONFIG_FILENAME = '.mcp_mokogitea.json';
export async function loadConfig(): Promise<GiteaConfig> {
const config_path = process.env.GITEA_API_MCP_CONFIG
+212
View File
@@ -1096,6 +1096,218 @@ server.tool(
async ({ owner, repo, connection }) => formatResponse(await clientFor(connection).get(`/repos/${owner}/${repo}/push_mirrors`)),
);
server.tool(
'gitea_repo_mirror_create',
'Create a push mirror to GitHub (backup). Sets up automatic push mirroring from Gitea to a GitHub repo.',
{
...OwnerRepo,
github_owner: z.string().optional().describe('GitHub org or user (defaults to config github.org)'),
github_repo: z.string().optional().describe('GitHub repo name (defaults to same as Gitea repo)'),
github_token: z.string().optional().describe('GitHub token (defaults to config github.token)'),
interval: z.string().optional().describe('Sync interval (e.g. "8h0m0s", default "8h0m0s")'),
...ConnectionParam,
},
async ({ owner, repo, github_owner, github_repo, github_token, interval, connection }) => {
const ghToken = github_token ?? config.github?.token;
const ghOwner = github_owner ?? config.github?.org;
if (!ghToken) return { content: [{ type: 'text' as const, text: 'Error: No GitHub token. Pass github_token or set github.token in config.' }] };
if (!ghOwner) return { content: [{ type: 'text' as const, text: 'Error: No GitHub owner. Pass github_owner or set github.org in config.' }] };
const ghRepo = github_repo ?? repo;
return formatResponse(await clientFor(connection).post(`/repos/${owner}/${repo}/push_mirrors`, {
remote_address: `https://github.com/${ghOwner}/${ghRepo}.git`,
remote_username: ghOwner,
remote_password: ghToken,
interval: interval ?? '8h0m0s',
sync_on_commit: true,
}));
},
);
server.tool(
'gitea_repo_mirror_delete',
'Delete a push mirror from a repository',
{
...OwnerRepo,
mirror_name: z.string().describe('Push mirror remote name (from mirrors_list)'),
...ConnectionParam,
},
async ({ owner, repo, mirror_name, connection }) => formatResponse(await clientFor(connection).delete(`/repos/${owner}/${repo}/push_mirrors/${mirror_name}`)),
);
server.tool(
'gitea_repo_mirror_setup_github_backup',
'One-step GitHub backup mirror setup: creates the GitHub repo (if needed) and configures push mirror. Requires a GitHub token with repo+org scope.',
{
...OwnerRepo,
github_org: z.string().optional().describe('GitHub org (defaults to config github.org)'),
github_token: z.string().optional().describe('GitHub token (defaults to config github.token)'),
private: z.boolean().optional().describe('Make GitHub repo private (default true)'),
description: z.string().optional().describe('GitHub repo description'),
interval: z.string().optional().describe('Mirror sync interval (default "8h0m0s")'),
...ConnectionParam,
},
async ({ owner, repo, github_org, github_token, private: isPrivate, description, interval, connection }) => {
const ghToken = github_token ?? config.github?.token;
const ghOrg = github_org ?? config.github?.org;
if (!ghToken) return { content: [{ type: 'text' as const, text: 'Error: No GitHub token. Pass github_token or set github.token in config.' }] };
if (!ghOrg) return { content: [{ type: 'text' as const, text: 'Error: No GitHub org. Pass github_org or set github.org in config.' }] };
const client = clientFor(connection);
const results: string[] = [];
// 1. Try to create the GitHub repo via GitHub API
const ghRes = await fetch(`https://api.github.com/orgs/${ghOrg}/repos`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${ghToken}`,
'Accept': 'application/vnd.github+json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: repo,
private: isPrivate ?? true,
description: description ?? `Backup mirror of ${owner}/${repo} from MokoGitea`,
auto_init: false,
has_issues: false,
has_wiki: false,
has_projects: false,
}),
});
const ghData = await ghRes.json();
if (ghRes.status === 201) {
results.push(`GitHub repo created: ${ghOrg}/${repo}`);
} else if (ghRes.status === 422) {
results.push(`GitHub repo already exists: ${ghOrg}/${repo}`);
} else {
return { content: [{ type: 'text' as const, text: `GitHub repo creation failed (${ghRes.status}): ${JSON.stringify(ghData)}` }] };
}
// 2. Create push mirror on Gitea
const mirrorRes = await client.post(`/repos/${owner}/${repo}/push_mirrors`, {
remote_address: `https://github.com/${ghOrg}/${repo}.git`,
remote_username: ghOrg,
remote_password: ghToken,
interval: interval ?? '8h0m0s',
sync_on_commit: true,
});
if (mirrorRes.status >= 400) {
const err = mirrorRes.data as { message?: string };
results.push(`Push mirror failed: ${err?.message ?? mirrorRes.status}`);
} else {
results.push(`Push mirror configured: sync every ${interval ?? '8h0m0s'}, sync on commit`);
}
// 3. Trigger initial sync
await client.post(`/repos/${owner}/${repo}/mirror-sync`, {});
results.push('Initial sync triggered');
return { content: [{ type: 'text' as const, text: results.join('\n') }] };
},
);
server.tool(
'gitea_repo_mirror_setup_github_backup_full',
'Full GitHub backup: mirrors code repo + wiki repo to GitHub. Creates GitHub repo, sets up push mirrors for both code and wiki, triggers initial sync.',
{
...OwnerRepo,
github_org: z.string().optional().describe('GitHub org (defaults to config github.org)'),
github_token: z.string().optional().describe('GitHub token (defaults to config github.token)'),
private: z.boolean().optional().describe('Make GitHub repo private (default true)'),
description: z.string().optional().describe('GitHub repo description'),
interval: z.string().optional().describe('Mirror sync interval (default "8h0m0s")'),
...ConnectionParam,
},
async ({ owner, repo, github_org, github_token, private: isPrivate, description, interval, connection }) => {
const ghToken = github_token ?? config.github?.token;
const ghOrg = github_org ?? config.github?.org;
if (!ghToken) return { content: [{ type: 'text' as const, text: 'Error: No GitHub token. Pass github_token or set github.token in config.' }] };
if (!ghOrg) return { content: [{ type: 'text' as const, text: 'Error: No GitHub org. Pass github_org or set github.org in config.' }] };
const client = clientFor(connection);
const syncInterval = interval ?? '8h0m0s';
const results: string[] = [];
// 1. Create GitHub repo (if needed)
const ghRes = await fetch(`https://api.github.com/orgs/${ghOrg}/repos`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${ghToken}`,
'Accept': 'application/vnd.github+json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: repo,
private: isPrivate ?? true,
description: description ?? `Backup mirror of ${owner}/${repo} from MokoGitea`,
auto_init: false,
has_issues: false,
has_wiki: true,
has_projects: false,
}),
});
const ghData = await ghRes.json();
if (ghRes.status === 201) {
results.push(`GitHub repo created: ${ghOrg}/${repo}`);
} else if (ghRes.status === 422) {
results.push(`GitHub repo already exists: ${ghOrg}/${repo}`);
} else {
return { content: [{ type: 'text' as const, text: `GitHub repo creation failed (${ghRes.status}): ${JSON.stringify(ghData)}` }] };
}
// 2. Enable wiki on GitHub repo (in case it was disabled)
await fetch(`https://api.github.com/repos/${ghOrg}/${repo}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${ghToken}`,
'Accept': 'application/vnd.github+json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ has_wiki: true }),
});
// 3. Code push mirror
const codeRes = await client.post(`/repos/${owner}/${repo}/push_mirrors`, {
remote_address: `https://github.com/${ghOrg}/${repo}.git`,
remote_username: ghOrg,
remote_password: ghToken,
interval: syncInterval,
sync_on_commit: true,
});
if (codeRes.status >= 400) {
const err = codeRes.data as { message?: string };
results.push(`Code mirror: ${err?.message ?? `failed (${codeRes.status})`}`);
} else {
results.push(`Code mirror configured: sync every ${syncInterval}, sync on commit`);
}
// 4. Wiki push mirror — Gitea wiki repos are at {repo}.wiki
// Check if wiki exists first
const wikiCheck = await client.get(`/repos/${owner}/${repo}/wiki/pages`);
if (wikiCheck.status < 400) {
const wikiRes = await client.post(`/repos/${owner}/${repo}/push_mirrors`, {
remote_address: `https://github.com/${ghOrg}/${repo}.wiki.git`,
remote_username: ghOrg,
remote_password: ghToken,
interval: syncInterval,
sync_on_commit: true,
});
if (wikiRes.status >= 400) {
const err = wikiRes.data as { message?: string };
results.push(`Wiki mirror: ${err?.message ?? `failed (${wikiRes.status})`}`);
} else {
results.push(`Wiki mirror configured: ${ghOrg}/${repo}.wiki.git`);
}
} else {
results.push('Wiki mirror skipped: no wiki pages found');
}
// 5. Trigger initial sync
await client.post(`/repos/${owner}/${repo}/mirror-sync`, {});
results.push('Initial sync triggered');
return { content: [{ type: 'text' as const, text: results.join('\n') }] };
},
);
// ── Repo Statistics ─────────────────────────────────────────────────────
server.tool(
+6
View File
@@ -20,9 +20,15 @@ export interface GiteaConnection {
insecure?: boolean;
}
export interface GitHubBackupConfig {
token: string;
org: string;
}
export interface GiteaConfig {
connections: Record<string, GiteaConnection>;
defaultConnection: string;
github?: GitHubBackupConfig;
}
export interface ApiResponse {