lunnyandsilverwind 0b855fa70f
release-nightly / release-image (push) Successful in 1m28s
test(label,milestone): cover every tool method (#258)
Adds request and result tests for every `label_read`, `label_write`, `milestone_read` and `milestone_write` method, failing when a new method has no test case. No tool schema or behavior changes.

Closes #39

Assisted by Codet (CommitGo coding agent) and Claude.

---------

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: silverwind <2021+silverwind@noreply.gitea.com>
Reviewed-on: #258
Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-09-23 23:54:51 +00:00
2025-04-08 14:01:14 +00:00
2026-09-21 14:50:37 +00:00
2026-09-21 14:50:37 +00:00
2025-03-19 02:59:18 +00:00

Gitea MCP Server

繁體中文 | 简体中文

Gitea MCP Server connects a Gitea instance to Model Context Protocol clients, so repositories, issues, pull requests and more can be browsed and managed from an MCP-compatible chat interface.

Install with Docker in VS Code Install with Docker in VS Code Insiders

Installation

Download a binary from the releases page and put it in your PATH, use the docker.gitea.com/gitea-mcp-server image, or build from source into $GOPATH/bin with make and Go 1.27 or later:

git clone https://gitea.com/gitea/gitea-mcp.git
cd gitea-mcp
make install

Configuration

Pass the Gitea host and access token as command-line flags or environment variables, flags take precedence. Run gitea-mcp --help for the full list of flags and environment variables. Logs are written to $HOME/.gitea-mcp/gitea-mcp.log, add -d for debug logging. To reach a Gitea listening on a Unix socket, pass -gitea-unix-socket <path>, the host then defaults to http://unix/.

MCP protocol and HTTP transport

The server supports MCP up to 2026-07-28 and negotiates down to the client's version, advertising only the tools capability. Tool and Gitea failures return a tools/call result with result.isError: true, while malformed requests and server faults stay JSON-RPC errors.

HTTP is always stateless: /mcp accepts POST only, without Mcp-Session-Id, standalone SSE or Last-Event-ID resumability. Origins are validated, and reverse proxies must forward Mcp-Protocol-Version, Mcp-Method and Mcp-Name unchanged. Authorization: Bearer <token> and Authorization: token <token> pass a Gitea credential per request, which is credential passthrough rather than MCP OAuth.

HTTP mode also serves /healthz, which returns 200 OK when the server is up. The Docker image's built-in HEALTHCHECK runs gitea-mcp -healthcheck, which dials http://127.0.0.1:<port>/healthz using the same -p/-port value (or 8080 by default) and exits 0 on success or 1 on failure. Stdio deployments do not serve /healthz, so override or disable the image's HEALTHCHECK when running in stdio mode.

OAuth for remote clients

Clients that cannot be given a token, such as Claude.ai on web and mobile, need the OAuth 2.1 flow from the MCP authorization spec, where -oauth-public-url is the public origin clients reach the server at:

gitea-mcp -t http -oauth -oauth-public-url https://mcp.example.com -H https://gitea.example.com

The server then serves /.well-known/oauth-protected-resource, naming the Gitea instance as the authorization server, and answers unauthenticated /mcp requests with a 401 challenge. Users act with their own Gitea account instead of a shared static token, and -r narrows the requested scopes to read-only.

Gitea has no dynamic client registration, so register the application once under Settings → Applications → Create OAuth2 Application, leaving Confidential Client unchecked so the flow uses PKCE. Set the redirect URI to https://claude.ai/api/mcp/auth_callback for Claude on web, desktop and mobile, adding http://127.0.0.1/callback for Claude Code, which Gitea matches on any port. Users enter the client ID under Advanced settings when adding the connector.

Both the server and Gitea have to be reachable over HTTPS from the client's network, for hosted Claude that is Anthropic's egress range. Behind a reverse proxy, /mcp only accepts the host from -oauth-public-url or a loopback host, so forward Host unchanged or leave it as the proxy default.

Claude Code

Runs the server through go run and requires Go:

claude mcp add --transport stdio --scope user gitea \
  --env GITEA_ACCESS_TOKEN=token \
  --env GITEA_HOST=https://gitea.com \
  -- go run gitea.com/gitea/gitea-mcp@latest -t stdio

VS Code

Use the install buttons at the top of this README, or add the block below to your User Settings (JSON), reachable via Ctrl + Shift + P and Preferences: Open User Settings (JSON). It also works in a workspace .vscode/mcp.json, where the mcp key is omitted.

{
  "mcp": {
    "inputs": [
      {
        "type": "promptString",
        "id": "gitea_token",
        "description": "Gitea Personal Access Token",
        "password": true
      }
    ],
    "servers": {
      "gitea-mcp": {
        "command": "docker",
        "args": ["run", "-i", "--rm", "-e", "GITEA_ACCESS_TOKEN", "docker.gitea.com/gitea-mcp-server"],
        "env": {
          "GITEA_ACCESS_TOKEN": "${input:gitea_token}"
        }
      }
    }
  }
}

OpenCode

Add the following to the top-level mcp object of your OpenCode config:

    "gitea-mcp": {
      "enabled": true,
      "type": "local",
      "command": [
        "gitea-mcp",
        "-t", "stdio",
        "-H", "https://gitea.com",
        "-T", "<your personal access token>"
      ]
    }

Mistral Vibe

Add the following to ~/.vibe/config.toml:

[[mcp_servers]]
name = "gitea"
transport = "stdio"
command = "docker"
args = ["run", "--rm", "-i", "-e", "GITEA_ACCESS_TOKEN", "-e", "GITEA_HOST", "docker.gitea.com/gitea-mcp-server"]

[mcp_servers.env]
GITEA_ACCESS_TOKEN = "TOKEN"
GITEA_HOST = "https://gitea.com"

Other clients

Clients such as Cursor take either a stdio command:

{
  "mcpServers": {
    "gitea": {
      "command": "gitea-mcp",
      "args": ["-t", "stdio", "--host", "https://gitea.com"],
      "env": {
        "GITEA_ACCESS_TOKEN": "<your personal access token>"
      }
    }
  }
}

or an http endpoint, for a server started with gitea-mcp -t http --port 8080:

{
  "mcpServers": {
    "gitea": {
      "url": "http://localhost:8080/mcp",
      "headers": {
        "Authorization": "Bearer <your personal access token>"
      }
    }
  }
}

Once configured, try list all my repositories in the chat box.

Available Tools

Tool Scope Access Description
get_gitea_mcp_server_version version Read Get the Gitea MCP server version
get_me user Read Get the current authenticated user
get_user_orgs user Read List the current user's organizations
search_users search Read Search for users
search_org_teams search Read Search teams within an organization
search_repos search Read Search for repositories
search_issues search Read Search issues and pull requests across repositories
notification_read notification Read Read notifications: list (optionally scoped to a repo) or get a thread by ID
notification_write notification Write Mark a notification or all notifications as read
label_read label Read Read repository or organization labels
label_write label Write Write labels (repo or org): create, edit, delete
milestone_read milestone Read Read milestones: get one or list
milestone_write milestone Write Write milestones: create, update, delete
wiki_read wiki Read Read wiki: list pages, get content, revision history
wiki_write wiki Write Write wiki pages: create, update, delete
timetracking_read timetracking Read Read time tracking: issue/repo times, active stopwatches, your tracked times
timetracking_write timetracking Write Write time tracking: stopwatches and entries
package_read packages Read Read package registry: list packages, list versions, or get a version
package_write packages Write Delete a package version (irreversible)
project_read project Read Read projects, columns and column issues
project_write project Write Write projects, columns and issue placement
list_issues issue Read List repository issues
attachment_read issue Read Read issue/comment attachments: list metadata, get metadata, or download content
issue_read issue Read Read issue: details, comments, or labels
issue_write issue Write Write issues: create, update, manage comments and labels
list_pull_requests pull_request Read List repository pull requests
pull_request_read pull_request Read Read pull request: details, diff, files, status, reviews, review comments
pull_request_write pull_request Write Write pull requests: create, update, close, reopen, merge, update branch, manage reviewers
pull_request_review_write pull_request Write Write PR reviews: create, submit, delete, dismiss, reply to and resolve review comments
actions_config_read actions Read Read Actions secrets and variables
actions_config_write actions Write Write Actions secrets and variables: upsert, create, update, delete
actions_run_read actions Read Read Actions workflows, runs, jobs, logs, and artifacts
actions_run_write actions Write Write Actions runs: dispatch, cancel, rerun
create_repo repository Write Create a new repository
fork_repo repository Write Fork a repository
list_my_repos repository Read List repositories owned by the current user
list_org_repos repository Read List repositories in an organization
get_repository_tree repository Read Get the repository file tree
get_file_contents file Read Get file content and metadata
get_dir_contents file Read Get the entries in a directory
create_or_update_file file Write Write files in one commit: create, update, rename, delete
delete_file file Write Delete a file
create_branch branch Write Create a new branch
delete_branch branch Write Delete a branch
list_branches branch Read List repository branches
rename_branch branch Write Rename a branch
create_tag tag Write Create a tag
delete_tag tag Write Delete a tag
get_tag tag Read Get tag details
list_tags tag Read List repository tags
list_commits commit Read List repository commits
get_commit commit Read Get commit details
create_release release Write Create a release
delete_release release Write Delete a release
get_release release Read Get a release by ID
get_latest_release release Read Get the latest release
list_releases release Read List repository releases

Note: Several tools are consolidated, action-based tools, a single tool exposes multiple operations through a method parameter. Tools with Write access are hidden when the server runs in read-only mode (-r / GITEA_READONLY), and the exposed tool set can be filtered by scope with -S / --scope (GITEA_SCOPES) and/or by individual tool name with -O / --tools (GITEA_TOOLS).

With neither flag set, every tool loads. --scope limits loading to tools whose Scope column value is in the given list; --tools limits loading to the named tools; setting both loads the union of the selected scopes and the individually named tools. Unknown scope names are ignored with a startup warning.

gitea-mcp -S issue,pull_request
gitea-mcp --scope repository,branch --tools get_me

Many tools accept page and per_page for pagination. The maximum effective page size is the Gitea server's [api].MAX_RESPONSE_ITEMS setting (default 50), larger values are silently capped.

S
Description
Interactive with Gitea instances with MCP
Readme MIT
19 MiB
96 Stars 63 Watchers 74 Forks
v1.7.0
Latest
2026-08-27 18:38:32 +00:00
Languages
Go 97.4%
PowerShell 1.2%
Makefile 0.6%
Shell 0.6%
Dockerfile 0.2%