Merge pull request 'fix: map Gitea auth failures to structured MCP tool errors (Closes #699)' (#701) from fix/issue-699-structured-auth-mcp-errors into master

This commit was merged in pull request #701.
This commit is contained in:
2026-07-15 23:48:06 -05:00
6 changed files with 1131 additions and 44 deletions
+16 -5
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
@@ -1466,6 +1468,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."
@@ -1803,13 +1811,16 @@ 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.
The exception message is a fixed constant (no host/token material).
"""
header = get_auth_header(host)
if header is None:
raise RuntimeError(
f"No credentials for {host}. "
"Ensure you've logged in via HTTPS at least once."
)
raise GiteaConfigError(reason_code="config_error")
return header