Closes #7
Gitea Tools
A collection of Python scripts and an MCP server to automate interactions with Gitea instances.
Supported Instances
| Remote | Host | Org / Repo |
|---|---|---|
dadeschools |
gitea.dadeschools.net |
Contractor / Timesheet |
prgs |
gitea.prgs.cc |
Scaled-Tech-Consulting / Timesheet |
Authentication
Authentication is configured via environment variables or a local .env file in the repository root (uses python-dotenv).
Create a .env file in the project root:
# Option A: Gitea Personal Access Tokens (Recommended)
GITEA_TOKEN_DADESCHOOLS="your_token_here"
GITEA_TOKEN_PRGS="your_token_here"
# Option B: Gitea Username & Password (fallback)
GITEA_USER_DADESCHOOLS="username"
GITEA_PASS_DADESCHOOLS="password"
GITEA_USER_PRGS="username"
GITEA_PASS_PRGS="password"
# Optional: Fallback to macOS Keychain (via git credential fill)
# GITEA_USE_KEYCHAIN=1
MCP Server (Recommended)
The Gitea-Tools MCP server exposes all functionality as structured tool calls. Any MCP-compatible agent (Antigravity, Claude Code, etc.) can call these tools natively.
Available Tools
| Tool | Description |
|---|---|
gitea_create_issue |
Create an issue with title, body, remote |
gitea_create_pr |
Open a pull request with title, head, base |
gitea_close_issue |
Close an issue by number |
gitea_list_issues |
List issues with state/label filters |
gitea_view_issue |
Get full details of a single issue |
gitea_mark_issue |
Claim/release an issue (start/done) |
gitea_mirror_refs |
Mirror branches + tags between instances |
Setup
1. Install dependencies
cd /Users/jasonwalker/Development/Gitea-Tools
python3 -m venv venv # skip if venv already exists
source venv/bin/activate
pip install "mcp[cli]"
2. Configure your AI client
The MCP server uses stdio transport — each client starts it as a subprocess. Add the config below to your client, then restart it.
Antigravity (Google)
Add to ~/.gemini/antigravity-ide/mcp_config.json inside "mcpServers":
"gitea-tools": {
"command": "/Users/jasonwalker/Development/Gitea-Tools/venv/bin/python3",
"args": ["/Users/jasonwalker/Development/Gitea-Tools/mcp_server.py"],
"env": {}
}
Restart Antigravity to load the server. Tools appear as lazy-loaded MCP tools
(call via call_mcp_tool with ServerName: "gitea-tools").
Claude Code (Anthropic)
Add to ~/.claude.json (global) or .mcp.json in the project root:
{
"mcpServers": {
"gitea-tools": {
"command": "/Users/jasonwalker/Development/Gitea-Tools/venv/bin/python3",
"args": ["/Users/jasonwalker/Development/Gitea-Tools/mcp_server.py"]
}
}
}
Restart Claude Code. Tools appear as mcp__gitea-tools__gitea_create_issue, etc.
Any MCP-compatible client
The server is a standard MCP stdio server. Point your client at:
- Command:
/Users/jasonwalker/Development/Gitea-Tools/venv/bin/python3 - Args:
["/Users/jasonwalker/Development/Gitea-Tools/mcp_server.py"] - Transport:
stdio
No environment variables needed — auth is handled via macOS keychain.
Codex / non-MCP tools
OpenAI Codex and other tools that don't support MCP can use the CLI scripts directly. See the CLI Scripts section below.
# Example: Codex can shell out to the scripts
python3 /Users/jasonwalker/Development/Gitea-Tools/create_issue.py \
--remote prgs --title "Bug report" --body "Details here"
CLI Scripts
The MCP tools can also be used as standalone CLI scripts:
| Script | Description |
|---|---|
create_issue.py |
Create an issue (--remote, --title, --body, --body-file) |
create_pr.py |
Open a Pull Request (--remote, --title, --head, --base) |
close_issue.py |
Close a specific issue |
mark_issue.py |
Claim/release an issue via status:in-progress label |
manage_labels.py |
Create label set and apply label mappings (--dry to preview) |
mirror_refs.sh |
Mirror branches + tags between dadeschools ⇄ prgs |
Quick Examples
# Create an issue
./create_issue.py --title "Fix PDF output" --body "Blank on Safari"
# Create an issue on the prgs instance
./create_issue.py --remote prgs --title "Add tests" --body-file description.md
# Create a PR
./create_pr.py --title "feat: add validation" --head feat/validation --body "Closes #12"
# Close issue #5
./close_issue.py 5
# Claim an issue before working on it
./mark_issue.py 10 start
# Release when done
./mark_issue.py 10 done
# Mirror refs (dry-run by default)
./mirror_refs.sh
# Actually push the refs
./mirror_refs.sh --apply
Use --help on any Python script or shell script for full usage details.
Architecture
gitea_auth.py ← shared auth & API helpers (get_credentials, api_request)
mcp_server.py ← MCP server (FastMCP, stdio transport)
create_issue.py ← CLI: create issues
create_pr.py ← CLI: create PRs
manage_labels.py ← CLI: label management
close_issue.py ← CLI: close issues
mark_issue.py ← CLI: claim/release issues
mirror_refs.sh ← CLI: ref mirroring
Tests
# Run with the venv (includes MCP SDK)
source venv/bin/activate
python3 -m pytest tests/ -v
| Test file | Covers |
|---|---|
test_mcp_server.py |
All 7 MCP tools: create, list, view, close, mark, PR, mirror |
test_create_issue.py |
CLI arg parsing, remote resolution, payload, auth, errors |
test_create_pr.py |
CLI arg parsing, remote resolution, payload, auth, errors |
test_credentials.py |
get_credentials(), get_auth_header(), repo_api_url() |
test_manage_labels.py |
Label create/skip, dry run, mapping, constant validation |
test_python_cli.py |
close_issue.py + mark_issue.py CLI validation |
test_mirror_refs.py |
Flags, safety defaults, local integration tests |
All tests mock network and keychain access — no real API calls are made.