Add full read/write mode: give the AI complete access to the Gitea environment #21

Closed
opened 2026-06-19 20:38:32 +00:00 by Bartender · 1 comment
Owner

Goal

Today AegisGitea-MCP is read-only by design. This issue tracks adding write capability so the AI can not only inspect but also act on the Gitea environment — with the intent of giving it as complete access as possible through MCP tool calls.

Requested change

Expose write tools alongside the existing read-only ones, covering as much of the Gitea surface as practical:

  • Issues: create, comment, update (title/body/state), label, assign, close/reopen
  • Pull requests: create, comment, review, merge
  • Branches & tags: create branches, create releases/tags
  • Repository content: create/edit files, commits (where the API allows)
  • Labels & milestones: create/update
  • Anything else the Gitea API exposes that fits the "complete access" intent

The aim is that the AI can drive a full workflow end-to-end, not just read state.

Design notes / considerations

This deliberately reverses the original read-only posture, so it's worth being explicit about how to do it safely rather than just flipping a flag:

  • Keep it opt-in. A write mode toggle (env var / config) so read-only stays the default and full access is a conscious choice, not the baseline.
  • Bot user scoping. Access is already managed through a dedicated bot user inside Gitea — that user's permissions become the real ceiling on "complete access," so scope it intentionally.
  • Auditability. The project's value is that every action is an explicit, auditable MCP tool call. Write actions should log at least as clearly as reads.
  • Fix the known PAT bypass first. The earlier security audit flagged a PAT bypass and an open-redirect issue. Granting full write on top of an unpatched bypass is the risky combination — those should land before (or together with) write mode.

Acceptance

  • Write tools implemented and gated behind an explicit opt-in mode
  • Audit logging covers write actions
  • Known PAT bypass / open-redirect remediated
  • README documents the read-only vs full-access modes and the security trade-off
## Goal Today AegisGitea-MCP is read-only by design. This issue tracks adding **write capability** so the AI can not only inspect but also act on the Gitea environment — with the intent of giving it as complete access as possible through MCP tool calls. ## Requested change Expose write tools alongside the existing read-only ones, covering as much of the Gitea surface as practical: - **Issues**: create, comment, update (title/body/state), label, assign, close/reopen - **Pull requests**: create, comment, review, merge - **Branches & tags**: create branches, create releases/tags - **Repository content**: create/edit files, commits (where the API allows) - **Labels & milestones**: create/update - Anything else the Gitea API exposes that fits the "complete access" intent The aim is that the AI can drive a full workflow end-to-end, not just read state. ## Design notes / considerations This deliberately reverses the original read-only posture, so it's worth being explicit about how to do it safely rather than just flipping a flag: - **Keep it opt-in.** A `write` mode toggle (env var / config) so read-only stays the default and full access is a conscious choice, not the baseline. - **Bot user scoping.** Access is already managed through a dedicated bot user inside Gitea — that user's permissions become the real ceiling on "complete access," so scope it intentionally. - **Auditability.** The project's value is that every action is an explicit, auditable MCP tool call. Write actions should log at least as clearly as reads. - **Fix the known PAT bypass first.** The earlier security audit flagged a PAT bypass and an open-redirect issue. Granting full write on top of an unpatched bypass is the risky combination — those should land before (or together with) write mode. ## Acceptance - [ ] Write tools implemented and gated behind an explicit opt-in mode - [ ] Audit logging covers write actions - [ ] Known PAT bypass / open-redirect remediated - [ ] README documents the read-only vs full-access modes and the security trade-off
Latte closed this issue 2026-06-22 15:22:41 +00:00
Owner

Verified done — closing

Checked the current main against all four acceptance criteria. All met:

  • Write tools behind explicit opt-in mode — 16 write handlers in tools/write_tools.py; WRITE_MODE=false by default; scope write:repository; policy enforced via is_write=tool_def.write_operation.
  • Audit logging covers write actions — every dispatch goes through audit.log_tool_invocation / log_access_denied on the hash-chained audit log.
  • PAT bypass / open-redirect remediated_verify_user_repository_access runs before any service-PAT use plus the service_pat_requires_repository_target guard (server.py:1210-1237); is_redirect_uri_allowed allowlist enforced on the authorize proxy, callback and DCR registration (server.py:842/888/990). Path-traversal on ref/sha/base/head also fixed (#18).
  • README documents read-only vs full-access + trade-off — README WRITE_MODE/scopes section + docs/write-mode.md (Threat Model, Default Posture, Risk Tradeoffs).

Implemented write tools: create/update_issue (incl. state = close/reopen), issue/PR comments + edit, add/remove/create/update_label, assign_issue, create_pull_request, create/edit_release, create_branch, create_milestone.

Deliberately out of scope (not gaps)

The formal acceptance checklist is fully satisfied. Two items from the broader "complete access" wishlist were intentionally not implemented:

  • PR merge & reviewdocs/write-mode.md explicitly forbids merge / force-push / branch-deletion by design.
  • Repository content writes (create/edit files, commits) — not implemented; tools/repository.py is read-only.

If these are wanted later they belong in a dedicated follow-up issue. Minor doc lag: docs/write-mode.md "Supported Write Tools" lists 6 while 16 are implemented.

Closing as all acceptance criteria are met.

## Verified done — closing Checked the current `main` against all four acceptance criteria. All met: - [x] **Write tools behind explicit opt-in mode** — 16 write handlers in `tools/write_tools.py`; `WRITE_MODE=false` by default; scope `write:repository`; policy enforced via `is_write=tool_def.write_operation`. - [x] **Audit logging covers write actions** — every dispatch goes through `audit.log_tool_invocation` / `log_access_denied` on the hash-chained audit log. - [x] **PAT bypass / open-redirect remediated** — `_verify_user_repository_access` runs before any service-PAT use plus the `service_pat_requires_repository_target` guard (server.py:1210-1237); `is_redirect_uri_allowed` allowlist enforced on the authorize proxy, callback and DCR registration (server.py:842/888/990). Path-traversal on ref/sha/base/head also fixed (#18). - [x] **README documents read-only vs full-access + trade-off** — README WRITE_MODE/scopes section + `docs/write-mode.md` (Threat Model, Default Posture, Risk Tradeoffs). Implemented write tools: create/update_issue (incl. state = close/reopen), issue/PR comments + edit, add/remove/create/update_label, assign_issue, create_pull_request, create/edit_release, create_branch, create_milestone. ### Deliberately out of scope (not gaps) The formal acceptance checklist is fully satisfied. Two items from the broader "complete access" wishlist were intentionally not implemented: - **PR merge & review** — `docs/write-mode.md` explicitly forbids merge / force-push / branch-deletion by design. - **Repository content writes** (create/edit files, commits) — not implemented; `tools/repository.py` is read-only. If these are wanted later they belong in a dedicated follow-up issue. Minor doc lag: `docs/write-mode.md` "Supported Write Tools" lists 6 while 16 are implemented. Closing as all acceptance criteria are met.
Sign in to join this conversation.