fix: map Gitea auth failures to structured MCP tool errors (Closes #699)

HTTP 401/scope-403/network failures become typed client errors with stable
reason codes. The FastMCP Tool.run boundary returns CallToolResult isError
payloads so stdio transport survives; daemon logs use sanitized reason codes
only. Regression tests cover author/reconciler profiles, transport survival,
and non-misclassification of unexpected exceptions.

Cross-links: #685, #695, #697, #698, PR #696 (scopes not absorbed).
This commit is contained in:
2026-07-13 13:10:00 -04:00
parent 237656702f
commit b4d0cb22e4
4 changed files with 782 additions and 19 deletions
+17 -3
View File
@@ -1084,7 +1084,9 @@ from gitea_auth import ( # noqa: E402
repo_api_url,
get_profile,
gitea_url,
GiteaConfigError,
)
import mcp_tool_error_boundary # noqa: E402
import gitea_audit # noqa: E402
import gitea_config # noqa: E402
import capability_stop_terminal # noqa: E402
@@ -1464,6 +1466,12 @@ def _with_optional_url(result: dict, url: str | None) -> dict:
result["url"] = url
return result
# #699: known auth/authz/network/config failures → structured CallToolResult
# isError; stdio transport must survive (no unhandled raise / process exit).
from mcp.server.fastmcp.tools.base import Tool as _FastMCPTool # noqa: E402
mcp_tool_error_boundary.install_tool_run_boundary(_FastMCPTool)
mcp = FastMCP("gitea-tools", instructions=(
"Gitea issue tracker and PR management for dadeschools and prgs instances. "
"Use the gitea_ prefixed tools to create issues, PRs, list issues, etc."
@@ -1801,12 +1809,18 @@ def _enforce_remote_repo_guard(
def _auth(host: str) -> str:
"""Get auth header, raise if unavailable."""
"""Get auth header, raise if unavailable.
Missing credentials are a configuration failure, not a silent internal
crash. Typed as :class:`gitea_auth.GiteaConfigError` so the tool-error
boundary (#699) maps them to a structured isError result without EOF.
"""
header = get_auth_header(host)
if header is None:
raise RuntimeError(
raise GiteaConfigError(
f"No credentials for {host}. "
"Ensure you've logged in via HTTPS at least once."
"Ensure you've logged in via HTTPS at least once.",
reason_code="config_error",
)
return header