mitai-jinkendo/scripts/gitea/mcp_server_gitea.py
Lars 3d498d03c1
All checks were successful
Deploy Development / deploy (push) Successful in 48s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 16s
feat: Enhance dashboard widget configuration and introduce new widgets
- Updated the dashboard layout schema to include new widgets: DashboardGreeting, QuickWeightToday, BodyStatStrip, StatusPills, ProfileGoalsProgress, TrendKcalWeight, NutritionActivitySummary, RecoverySleepRest, and TrainingTypeDistribution.
- Improved widget configuration validation to support new features, including chart days for trend and distribution widgets.
- Refactored the default lab layout to align with the updated widget catalog and ensure proper default activation.
- Bumped app_dashboard version to 1.6.0 to reflect the addition of new widgets and configuration enhancements.
2026-04-07 14:19:45 +02:00

152 lines
4.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. "
"Kurze Titel-/Body-Änderungen: gitea_patch_issue. "
"Sehr lange Bodies oder Skripte: Terminal scripts/gitea/gitea_api.py issues edit … --body-file."
),
)
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_patch_issue(
issue_number: int,
title: str | None = None,
body: str | None = None,
) -> str:
"""Issue-Titel und/oder Beschreibung (PATCH). Mindestens eines von title/body setzen. Für sehr lange Markdown-Texte besser: CLI issues edit --body-file."""
fields: dict[str, str] = {}
if title is not None:
t = title.strip()
if not t:
return _json({"error": "title darf nicht leer sein"})
fields["title"] = t
if body is not None:
fields["body"] = body
if not fields:
return _json({"error": "Mindestens title oder body angeben"})
base, token, owner, repo = _cfg()
st, payload = issues_patch(base, token, owner, repo, issue_number, fields)
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()