#!/usr/bin/env python3 """ MCP-Server für Gitea (Issues + Datei-Inhalt via API). Cursor: in den MCP-Einstellungen dieses Skript starten (siehe MCP_SETUP.md). Transport: stdio (Standard FastMCP). Abhängigkeit: pip install "mcp>=1.2.0" (siehe requirements-mcp.txt) """ from __future__ import annotations import json import sys from gitea_lib import ( issues_comment, issues_create, issues_get, issues_list_all, issues_list_page, issues_patch, load_dotenv, repo_file_content, repo_root, require_config, ) from mcp.server.fastmcp import FastMCP # noqa: E402 mcp = FastMCP( "mitai-gitea", instructions=( "Gitea-Tools für das Repo aus GITEA_OWNER/GITEA_REPO. " "Schließe Issues nur nach klarer Code-Verifikation; sonst Kommentar mit offenen Punkten." ), ) def _cfg(): load_dotenv(repo_root()) return require_config() def _json(obj) -> str: return json.dumps(obj, indent=2, ensure_ascii=False) @mcp.tool() def gitea_list_issues( state: str = "open", limit_per_page: int = 50, fetch_all_pages: bool = False, ) -> str: """Listet Issues. state: open | closed | all. fetch_all_pages=true holt alle Seiten (kann langsam sein).""" base, token, owner, repo = _cfg() if fetch_all_pages: items = issues_list_all( base, token, owner, repo, state=state, limit=limit_per_page ) return _json( [{"number": i.get("number"), "title": i.get("title"), "state": i.get("state")} for i in items] ) _, items = issues_list_page( base, token, owner, repo, state=state, page=1, limit=limit_per_page ) return _json( [{"number": i.get("number"), "title": i.get("title"), "state": i.get("state")} for i in items] ) @mcp.tool() def gitea_get_issue(issue_number: int) -> str: """Holt ein Issue inkl. Body, Labels, State (JSON).""" base, token, owner, repo = _cfg() st, payload = issues_get(base, token, owner, repo, issue_number) return _json({"http_status": st, "issue": payload}) @mcp.tool() def gitea_create_issue(title: str, body: str = "", labels: str = "") -> str: """Legt ein Issue an. labels: kommagetrennte Namen, z.B. \"bug,backend\".""" base, token, owner, repo = _cfg() lab = [x.strip() for x in labels.split(",") if x.strip()] st, payload = issues_create( base, token, owner, repo, title=title, body=body, labels=lab ) return _json({"http_status": st, "result": payload}) @mcp.tool() def gitea_comment_issue(issue_number: int, body: str) -> str: """Kommentar an ein Issue anhängen.""" base, token, owner, repo = _cfg() st, payload = issues_comment(base, token, owner, repo, issue_number, body) return _json({"http_status": st, "result": payload}) @mcp.tool() def gitea_close_issue(issue_number: int) -> str: """Issue schließen (state=closed).""" base, token, owner, repo = _cfg() st, payload = issues_patch( base, token, owner, repo, issue_number, {"state": "closed"} ) return _json({"http_status": st, "result": payload}) @mcp.tool() def gitea_reopen_issue(issue_number: int) -> str: """Geschlossenes Issue wieder öffnen.""" base, token, owner, repo = _cfg() st, payload = issues_patch( base, token, owner, repo, issue_number, {"state": "open"} ) return _json({"http_status": st, "result": payload}) @mcp.tool() def gitea_get_repo_file(path: str, git_ref: str = "") -> str: """Liest eine Datei aus dem Repo über die Gitea-API (Standard: Default-Branch).""" base, token, owner, repo = _cfg() st, payload = repo_file_content(base, token, owner, repo, path, ref=git_ref) return _json({"http_status": st, "payload": payload}) if __name__ == "__main__": mcp.run()