Files
gitea_mcp/README.md
l3ocho c34e06aa2b feat: add merge tools, tests, and documentation
Added 3 new PR merge tools to complete v1.0.0:
- merge_pull_request: Merge PR with 5 strategies (merge, rebase, rebase-merge, squash, fast-forward-only)
- get_pr_merge_status: Check if PR is mergeable
- cancel_auto_merge: Cancel scheduled auto-merge

Changes:
- New merge methods in GiteaClient (gitea_client.py)
- New async wrappers in PullRequestTools with branch checks (tools/pull_requests.py)
- Tool definitions and dispatch routing in tool_registry.py
- Boolean type coercion for force_merge and delete_branch parameters
- Comprehensive test suite with 18 tests (test_pull_requests.py)
- Full documentation: README.md, CHANGELOG.md, CLAUDE.md

Features:
- 5 merge strategies with full Gitea API support
- Branch-aware security enforcement
- Type coercion handles MCP string serialization
- 100% test coverage for merge operations

Result:
- Total tools: 39 (7 PR operations + 3 merge = 10 PR tools)
- All tests passing (18 new merge tests + 60 existing tests)
- Ready for v1.0.0 release

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-08 16:38:35 -05:00

316 lines
8.6 KiB
Markdown

# gitea-mcp
![Version](https://img.shields.io/badge/version-1.0.0-blue) ![Python](https://img.shields.io/badge/python-3.10%2B-green)
MCP server providing 39 tools for Gitea repository operations, issue management, and pull request workflows.
## Overview
**gitea-mcp** is a Model Context Protocol (MCP) server that brings comprehensive Gitea integration to Claude Code and other MCP-compatible systems. It provides a unified interface for automating repository management, issue tracking, and PR workflows across multiple repositories.
### Dual-Mode Operation
- **Project Mode**: Works with a single configured repository (`GITEA_REPO`)
- **PMO/Company Mode**: Manages multiple repositories across your Gitea instance with org-level issue aggregation
### Tool Count: 39 MCP Tools
Across 7 functional categories:
- Issue Management (6 tools)
- Label Management (5 tools)
- Wiki & Lessons Learned (7 tools)
- Milestone Management (5 tools)
- Issue Dependencies (4 tools)
- Pull Requests (7 tools)
- PR Merge Operations (3 tools) — **NEW in v1.0.0**
## Installation
### From Gitea PyPI Registry
```bash
pip install gitea-mcp \
--extra-index-url https://gitea.hotserv.cloud/api/packages/personal-projects/pypi/simple
```
### From Source
```bash
git clone https://gitea.hotserv.cloud/personal-projects/gitea-mcp.git
cd gitea-mcp
pip install -e ".[dev]"
```
## Tools Reference
### Issue Management (6 tools)
| Tool | Description |
|------|-------------|
| `list_issues` | List issues with state/label/milestone filters |
| `get_issue` | Get specific issue details |
| `create_issue` | Create new issue with labels |
| `update_issue` | Update issue title, body, state, labels |
| `add_comment` | Add comment to issue |
| `aggregate_issues` | PMO mode: aggregate issues across multiple repos |
### Label Management (5 tools)
| Tool | Description |
|------|-------------|
| `list_labels` | Get all available labels |
| `get_labels` | Get labels with optional filtering |
| `suggest_labels` | AI-powered label suggestions for issues |
| `create_label` | Create repo-level label |
| `create_label_smart` | Create label at appropriate level (org or repo) |
### Wiki & Lessons Learned (7 tools)
| Tool | Description |
|------|-------------|
| `list_wiki_pages` | List all wiki pages |
| `get_wiki_page` | Get specific wiki page content |
| `create_wiki_page` | Create new wiki page |
| `update_wiki_page` | Update existing wiki page |
| `create_lesson` | Create structured lessons learned entry |
| `search_lessons` | Search lessons by tags or query |
| `allocate_rfc_number` | Auto-allocate next RFC number |
### Milestone Management (5 tools)
| Tool | Description |
|------|-------------|
| `list_milestones` | List milestones with state filter |
| `get_milestone` | Get specific milestone details |
| `create_milestone` | Create new milestone with due date |
| `update_milestone` | Update milestone properties |
| `delete_milestone` | Delete milestone |
### Issue Dependencies (4 tools)
| Tool | Description |
|------|-------------|
| `list_issue_dependencies` | List issues that block a given issue |
| `create_issue_dependency` | Create dependency between issues |
| `remove_issue_dependency` | Remove dependency link |
| `get_execution_order` | Get parallelizable execution order for issue set |
### Pull Requests (7 tools)
| Tool | Description |
|------|-------------|
| `list_pull_requests` | List PRs with state/label/sort filters |
| `get_pull_request` | Get specific PR details |
| `get_pr_diff` | Get PR diff as unified diff string |
| `get_pr_comments` | Get all comments on a PR |
| `create_pr_review` | Create review (approve/request-changes/comment) |
| `add_pr_comment` | Add comment to PR |
| `create_pull_request` | Create new PR with optional labels |
### PR Merge Operations (3 tools) — **NEW**
| Tool | Description |
|------|-------------|
| `merge_pull_request` | Merge PR with configurable strategy |
| `get_pr_merge_status` | Check if PR is mergeable |
| `cancel_auto_merge` | Cancel scheduled auto-merge |
## Merge Strategies
The `merge_pull_request` tool supports 5 merge strategies:
| Strategy | Description |
|----------|-------------|
| `merge` | Create a merge commit (default) |
| `rebase` | Rebase commits onto base branch, no merge commit |
| `rebase-merge` | Rebase commits then create merge commit |
| `squash` | Squash all commits into one |
| `fast-forward-only` | Only merge if fast-forward is possible |
### Example Usage
```python
# Merge with squash strategy
await merge_pull_request(
pr_number=42,
merge_style="squash",
delete_branch=True,
message="Merge feature branch into main"
)
# Check if mergeable before merging
status = await get_pr_merge_status(pr_number=42)
if status["mergeable"]:
await merge_pull_request(pr_number=42)
```
## Configuration
### Environment Variables
```bash
GITEA_API_URL # Gitea API URL (default: http://localhost:3000/api/v1)
GITEA_API_TOKEN # Gitea personal access token (required)
GITEA_MODE # 'project' or 'pmo' (default: auto-detect)
GITEA_REPO # 'owner/repo' for project mode (optional in PMO mode)
```
### Auto-Detection
- **Project Mode**: Activated when `GITEA_REPO` is set or detected from `.git/config`
- **PMO Mode**: Activated when GITEA_REPO is not set and user has org-level access
## Security Model
### Branch-Aware Access Control
Read operations (list, get, diff, comments) are allowed on all branches.
Write operations (create, merge, comment, delete) are restricted:
- **main/master/prod/*** branches: Read-only
- **staging/stage/*** branches: Comments only
- **dev/feature/fix/*** branches: Full access
- Unknown branches: Read-only (fail-safe)
Example: Attempting to merge a PR while on `main` branch raises:
```
PermissionError: Cannot merge PR on branch 'main'.
Switch to a development or feature branch to merge PRs.
```
## Usage
### Stdio Server Mode (Claude Code)
1. Add to `.mcp.json`:
```json
{
"mcpServers": {
"gitea": {
"command": "python",
"args": ["-m", "gitea_mcp.server"]
}
}
}
```
2. Set environment variables:
```bash
export GITEA_API_TOKEN="your-token"
export GITEA_REPO="owner/repo" # for project mode
```
3. Use in Claude Code:
```
Create an issue about performance optimization with the 'enhancement' label.
```
### Programmatic Import
```python
from gitea_mcp import get_tool_definitions, create_tool_dispatcher
from gitea_mcp.gitea_client import GiteaClient
# Get all tool definitions
tools = get_tool_definitions()
# Create dispatcher
client = GiteaClient()
dispatch = create_tool_dispatcher(client)
# Call tools
result = await dispatch("list_issues", {"state": "open"})
# Or filter by tool name
pr_tools = get_tool_definitions(tool_filter=["list_pull_requests", "merge_pull_request"])
```
### HTTP Server (gitea-mcp-remote)
The tool registry can be used by HTTP transport:
```python
from gitea_mcp.tool_registry import get_tool_definitions, create_tool_dispatcher
from gitea_mcp.gitea_client import GiteaClient
client = GiteaClient()
tools = get_tool_definitions()
dispatcher = create_tool_dispatcher(client)
```
## Development
### Setup
```bash
python -m venv .venv
source .venv/bin/activate # or: .venv\Scripts\activate (Windows)
pip install -e ".[dev]"
```
### Testing
```bash
# Run all tests
pytest tests/ -v
# Run specific test file
pytest tests/test_pull_requests.py -v
# Run with coverage
pytest tests/ --cov=gitea_mcp
```
### Building
```bash
pip install build
python -m build
```
### Publishing to Gitea PyPI
```bash
pip install twine
twine upload \
--repository-url https://gitea.hotserv.cloud/api/packages/personal-projects/pypi \
dist/*
```
## Architecture
### Core Components
| Module | Purpose |
|--------|---------|
| `gitea_client.py` | Synchronous Gitea REST API client |
| `config.py` | Configuration loader (env vars, auto-detection) |
| `tool_registry.py` | Tool definitions + dispatcher (transport-agnostic) |
| `server.py` | MCP stdio server entry point |
| `tools/*.py` | Async wrappers with branch-aware access control |
### Design Patterns
- **Transport-agnostic**: Tool definitions and dispatch in `tool_registry.py`, not `server.py`
- **Async-first**: All tools are async via `run_in_executor`
- **Type coercion**: Automatic string→int/bool conversion for MCP serialization
- **Branch security**: Checked in async wrappers, not in REST client
## Origin
Extracted from [leo-claude-mktplace](https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace) v9.1.0
Original location: `mcp-servers/gitea/` v1.3.0
Module renamed: `mcp_server``gitea_mcp`
## Contributing
1. Create a feature branch: `git checkout -b feat/your-feature`
2. Make your changes and test: `pytest tests/`
3. Create a pull request with a clear description
## License
MIT