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:
+17
-3
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user