Skip to main content
Glama

gitea-mcp

MCP server for Gitea, built for autonomous AI agents.

The supported Gitea baseline and integration harness are 28.3.0. The gate checks every endpoint in that release's Swagger against the hand-written operations.

Features

  • Repositories, issues, pull requests, releases, labels, milestones

  • File content management (create, read, update, delete)

  • Branches, tags, commits, and status checks

  • Actions / CI workflows and artifacts; job logs come back as text, one job or a whole run at a time

  • Projects (boards): columns and issue placement for repository, organization and user projects

  • Long-running waiters - workflow_runs_wait / workflow_jobs_wait block until a run or job finishes (streaming progress via MCP notifications); non-blocking *_wait_start / *_wait_poll(max_block=...) / *_wait_cancel + waits_list keep the agent responsive. Waits tolerate transient API errors (max_poll_failures, default 3 consecutive), background waits self-terminate after max_lifetime (default 2h), and all wait ops live in gitea_read - they only ever GET

  • Organizations, teams, and user management

  • Webhooks, deploy keys, notifications, wiki, packages

  • Admin endpoints for instance-level operations

  • Risk-graded meta-tools (gitea_read / gitea_write / gitea_execute / gitea_delete / gitea_admin_read / gitea_admin_write) — agents pick a tool surface by the kind of side effect, not the HTTP verb

  • Per-param help with operation='help' params={'search': 'foo'} for substring filtering and cross-group hints

  • Zero-config install via uvx

Related MCP server: gitea-mcp

Quick Start

Add the following to your MCP client configuration (Claude Desktop, Cursor, Claude Code, etc.). For Claude Code global config on macOS: ~/.claude.json → "mcpServers".

{
  "mcpServers": {
    "gitea": {
      "command": "uvx",
      "args": ["--refresh", "--extra-index-url", "https://nikitatsym.github.io/gitea-mcp/simple", "gitea-mcp"],
      "env": {
        "GITEA_URL": "https://gitea.example.com",
        "GITEA_TOKEN": "your-api-token"
      }
    }
  }
}

Or use the interactive Setup Page to generate the config.

HTTP

gitea-mcp --http serves streamable HTTP at http://127.0.0.1:8000/mcp (--host, --port) instead of stdio, same environment variables. No authentication: put a gateway in front.

The package can also be imported: mcp, Settings, the client class, and client_var (a ContextVar the host sets per request) let one process serve several instances.

Configuration

Variable

Required

Description

GITEA_URL

Yes

Base URL of your Gitea instance (e.g. https://gitea.example.com)

GITEA_TOKEN

Yes

Personal access token with appropriate permissions. For CreateUserAccessToken self-rotation, must include write:user (or all) scope.

MCP_GITEA_BRIEF_MAX

No

Max character length for the <brief>summary</brief> tag enforced on issue/PR bodies (default: 100; 0 disables the requirement)

By default, creating public repos and orgs is blocked — agents must pass private=true explicitly. To allow public repos, add --allow-public to the command args:

"args": ["--refresh", "--extra-index-url", "https://nikitatsym.github.io/gitea-mcp/simple", "gitea-mcp", "--allow-public"]

Tool Groups

Operations are exposed through risk-graded meta-tools — one tool surface per scope, dispatched via operation + params.

Meta-tool

Scope

Examples

gitea_read

GET, safe / read-only

ListRepos, GetIssue, ListPullRequests

gitea_write

Create + update (POST/PUT/PATCH)

CreateRepo, EditIssue, CreatePullRequest

gitea_execute

Action triggers with real-world side effects

MergePullRequest, DispatchWorkflow

gitea_delete

Destructive DELETE

DeleteRepo, DeleteBranch

gitea_admin_read

Admin-scope GET

AdminListUsers, AdminListRunners

gitea_admin_write

Admin-scope writes + admin actions

AdminCreateUser, AdminRunCronJob

Each meta-tool takes operation (PascalCase op name, or help / schema) plus params (dict):

gitea_read(operation="help")                                                # list every op in this group
gitea_read(operation="help", params={"search": "merge"})                    # filter by substring; surfaces cross-group hits
gitea_read(operation="schema", params={"op": "GetRepo"})                    # full JSON Schema for one op
gitea_read(operation="GetRepo", params={"owner": "alice", "repo": "x"})     # invoke

gitea_write(operation="CreateIssue", params={"owner": "alice", "repo": "x", "title": "Bug", "body": "<brief>repro</brief>"})
gitea_execute(operation="MergePullRequest", params={"owner": "alice", "repo": "x", "index": 7, "merge_type": "squash"})

Params are validated strictly via Pydantic: unknown keys, wrong types, and missing required fields return a contextual error result with field-level detail.

Creating a Gitea API Token

  1. Log in to your Gitea instance.

  2. Go to Settings > Applications.

  3. Under Manage Access Tokens, enter a token name (e.g. mcp-server).

  4. Select the permissions your agent needs (read/write on repos, issues, etc.).

  5. Click Generate Token and copy the value immediately -- it is shown only once.

Development

dev.py is the single gate entry point (dev-script contract): lint (ruff + mypy + tackbox), e2e (boots the dockerized Gitea, runs the integration suite), test (unit + e2e), check (lint + test). Pre-commit and CI both run ./dev.py check — install the hook once per clone with python dev.py hook, which points core.hooksPath at the tracked .githooks/.

npm scripts cover the docker lifecycle around it:

# unit tests (no docker, fast)
npm test

# bring up Gitea container + bootstrap admin user + write tests/.env
npm run gitea:up

# run integration tests against the live container
npm run test:integration

# tear down
npm run gitea:down

# one-shot: up + integration + down (exits with the pytest status code)
npm run test:integration:full

npm run gitea:bootstrap is idempotent — re-running against an already-bootstrapped instance no-ops if tests/.env carries a still-valid token, otherwise deletes the named token and creates a fresh one. The bootstrap script (scripts/bootstrap.py) is also runnable directly via uv run python scripts/bootstrap.py.

tests/.env schema:

GITEA_URL=http://localhost:3000
GITEA_TOKEN=<sha1>
GITEA_ADMIN_USER=testadmin
GITEA_ADMIN_PASSWORD=testadmin1234

Integration tests use @pytest.mark.integration and are deselected by npm test. Selecting them requires GITEA_URL + GITEA_TOKEN; missing configuration fails the run rather than silently skipping it.

License

MIT

Available Tools

7 tools
gitea_admin_readB

Gitea admin read operations (GET /admin/*).

operation='help' — list ops with parameter names + types. operation='help' params={'search':'X'} — same, filtered to ops whose name contains X (case-insensitive). operation='schema' — JSON Schema for one op. params={'op': 'OpName'} or params={} to list op names. operation='' params={...} — invoke. Params validated strictly: unknown keys, wrong types, missing required → ValueError with field-level detail.

Inputs: operation (required), params.

gitea_admin_writeA

Gitea admin write operations (POST/PUT/PATCH/DELETE /admin/*) and admin-scope actions like running cron jobs.

operation='help' — list ops with parameter names + types. operation='help' params={'search':'X'} — same, filtered to ops whose name contains X (case-insensitive). operation='schema' — JSON Schema for one op. params={'op': 'OpName'} or params={} to list op names. operation='' params={...} — invoke. Params validated strictly: unknown keys, wrong types, missing required → ValueError with field-level detail.

Inputs: operation (required), params.

gitea_deleteA

Gitea delete operations (DELETE) — destructive.

operation='help' — list ops with parameter names + types. operation='help' params={'search':'X'} — same, filtered to ops whose name contains X (case-insensitive). operation='schema' — JSON Schema for one op. params={'op': 'OpName'} or params={} to list op names. operation='' params={...} — invoke. Params validated strictly: unknown keys, wrong types, missing required → ValueError with field-level detail.

Inputs: operation (required), params.

gitea_executeA

Gitea action triggers — merge PRs, dispatch workflows, and other side-effecting actions beyond plain CRUD.

operation='help' — list ops with parameter names + types. operation='help' params={'search':'X'} — same, filtered to ops whose name contains X (case-insensitive). operation='schema' — JSON Schema for one op. params={'op': 'OpName'} or params={} to list op names. operation='' params={...} — invoke. Params validated strictly: unknown keys, wrong types, missing required → ValueError with field-level detail.

Inputs: operation (required), params.

gitea_readA

Gitea read operations — safe, GET-only.

operation='help' — list ops with parameter names + types. operation='help' params={'search':'X'} — same, filtered to ops whose name contains X (case-insensitive). operation='schema' — JSON Schema for one op. params={'op': 'OpName'} or params={} to list op names. operation='' params={...} — invoke. Params validated strictly: unknown keys, wrong types, missing required → ValueError with field-level detail.

Inputs: operation (required), params.

gitea_versionA

Get the Gitea MCP server version and service version.

Inputs: no named parameters.

gitea_writeA

Gitea write operations — create or update resources (POST/PUT/PATCH).

operation='help' — list ops with parameter names + types. operation='help' params={'search':'X'} — same, filtered to ops whose name contains X (case-insensitive). operation='schema' — JSON Schema for one op. params={'op': 'OpName'} or params={} to list op names. operation='' params={...} — invoke. Params validated strictly: unknown keys, wrong types, missing required → ValueError with field-level detail.

Inputs: operation (required), params.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 7 tools

    Disambiguation3/5

    The tools are divided by operation category (read, write, delete, etc.) with clear names, but there is overlap: gitea_delete and gitea_admin_write both handle DELETE operations, and gitea_execute may overlap with gitea_write for actions like merge PR. An agent may be uncertain which umbrella tool to use for a given operation.

    Naming Consistency4/5

    All tools share the gitea_ prefix and use snake_case, which is consistent. However, gitea_version is a noun while the others are verbs (read, write, delete, execute), a minor deviation from the otherwise verb-based pattern.

    Tool Count5/5

    With 7 tools, the count is well within the typical range for a server that wraps a full API. Each umbrella tool covers a broad category of operations, making the top-level count compact and manageable.

    Completeness4/5

    The set covers the core domains: version info, read/write/delete operations, admin read/write, and side-effecting actions. The split between gitea_write and gitea_execute is somewhat redundant for certain actions, and there is no dedicated search tool, but overall coverage is strong.

    Maintenance

    ActivityActive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      Not graded
      maintenance
      A comprehensive MCP server suite that enables AI interaction with Gitea for repository management, secure command execution, and Docker monitoring. It provides additional tools for long-term memory, filesystem access, and web searching to support full development cycles.
      -
    • A
      license
      A
      quality
      B
      maintenance
      MCP server for managing Gitea repositories via the Gitea API, enabling operations on issues, comments, labels, milestones, and repository info.
      72
      50 npm
      2
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      MCP server for OpenDev Gitea and Gerrit APIs, enabling repository browsing, code review, and change management for LLM agents.
      Apache 2.0