feat: add read-only gitea_whoami authenticated-user lookup (#11)
Add a read-only MCP tool that calls Gitea's authenticated-user endpoint (GET /api/v1/user) and returns safe identity metadata only: username, display name, user id, email, server, and remote. This lets future review/merge workflows prove which Gitea account the MCP server is authenticated as, so self-review/self-merge can be detected before acting — the blocker discovered during PR #8 dogfooding. - Never returns the token, Authorization header, password, or secrets. - Fails closed with a clear error if identity cannot be determined. - No mutation; no profile switching; no review/approve/merge behavior. Tests: identity mapping, secret-redaction, fail-closed, unknown-remote. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -595,6 +595,53 @@ def gitea_view_issue(
|
||||
}
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def gitea_whoami(
|
||||
remote: str = "dadeschools",
|
||||
host: str | None = None,
|
||||
) -> dict:
|
||||
"""Look up the Gitea account the MCP server is authenticated as.
|
||||
|
||||
Read-only. Calls Gitea's authenticated-user endpoint (GET /api/v1/user)
|
||||
with the configured token and returns safe identity metadata only. Use
|
||||
this to prove which account a mutating workflow (e.g. review/merge) would
|
||||
act as, so self-review/self-merge can be detected before acting.
|
||||
|
||||
Never returns the token, Authorization header, password, or any other
|
||||
secret material. Fails closed with a clear error if the identity cannot
|
||||
be determined.
|
||||
|
||||
Args:
|
||||
remote: Known instance — 'dadeschools' or 'prgs'.
|
||||
host: Override the Gitea host.
|
||||
|
||||
Returns:
|
||||
dict with 'authenticated', 'username', 'display_name', 'user_id',
|
||||
'email', 'server', and 'remote'.
|
||||
"""
|
||||
if remote not in REMOTES:
|
||||
raise ValueError(f"Unknown remote '{remote}'. Choose from: {list(REMOTES)}")
|
||||
h = host or REMOTES[remote]["host"]
|
||||
auth = _auth(h)
|
||||
url = f"https://{h}/api/v1/user"
|
||||
data = api_request("GET", url, auth)
|
||||
if not data or not data.get("login"):
|
||||
# Fail closed: never assume an identity we could not verify.
|
||||
raise RuntimeError(
|
||||
f"Could not determine the authenticated Gitea identity for {h}. "
|
||||
"Verify the configured token is valid for this instance."
|
||||
)
|
||||
return {
|
||||
"authenticated": True,
|
||||
"username": data.get("login"),
|
||||
"display_name": data.get("full_name") or None,
|
||||
"user_id": data.get("id"),
|
||||
"email": data.get("email") or None,
|
||||
"server": f"https://{h}",
|
||||
"remote": remote,
|
||||
}
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def gitea_mark_issue(
|
||||
issue_number: int,
|
||||
|
||||
Reference in New Issue
Block a user