mitai-jinkendo/scripts/gitea/mcp_server_gitea.py
Lars dc87e7f3b8
All checks were successful
Deploy Development / deploy (push) Successful in 44s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
cursor_Setup
2026-04-04 14:05:50 +02:00

128 lines
3.7 KiB
Python

#!/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()