Add pr_merge tool to allow merging pull requests from claude.ai sessions via gitea-mcp.
This is the critical missing piece for a complete code workflow from claude.ai without
needing GitHub or a local terminal.
Why this is now P0
With the ADR decision (infra #34) that Gitea is true master and GitHub is optional,
the tooling gap on the Gitea side must be closed. Today, claude.ai can:
✅ Read files, list repos, browse code ✅ Write files, create branches ✅ Create issues, comment on issues ✅ Create PRs (pr_create) ❌ Merge PRs — missing, blocks completing any code change from claude.ai
Without pr_merge, every code change started from claude.ai must be completed
in a terminal or web UI. That breaks the workflow.
Gitea API
POST /api/v1/repos/{owner}/{repo}/pulls/{index}/merge
tool: pr_merge
params:
owner: string
name: string // repo name
number: integer // PR number >= 1
style: string? // merge | squash | rebase | fast-forward-only (default: merge)
title: string? // merge commit title
message: string? // merge commit body
delete_branch: bool? // delete head branch after merge (default: true)
Required token permission
write:repository scope — same as existing write tools.
Risk classification
MEDIUM — merging is reversible via revert, but has real consequences.
No confirm param needed (unlike repo_delete) but tool description should be explicit.
Implementation notes
Follow pattern of existing tools in internal/tools/
Always check PR is open before attempting merge — return clear error if already merged/closed
delete_branch: true by default (consistent with TBD convention)
## Summary
Add `pr_merge` tool to allow merging pull requests from claude.ai sessions via gitea-mcp.
This is the critical missing piece for a complete code workflow from claude.ai without
needing GitHub or a local terminal.
## Why this is now P0
With the ADR decision (infra #34) that Gitea is true master and GitHub is optional,
the tooling gap on the Gitea side must be closed. Today, claude.ai can:
✅ Read files, list repos, browse code
✅ Write files, create branches
✅ Create issues, comment on issues
✅ Create PRs (pr_create)
❌ Merge PRs — missing, blocks completing any code change from claude.ai
Without pr_merge, every code change started from claude.ai must be completed
in a terminal or web UI. That breaks the workflow.
## Gitea API
`POST /api/v1/repos/{owner}/{repo}/pulls/{index}/merge`
Body:
```json
{
"Do": "merge",
"merge_message_title": "optional title",
"merge_message_field": "optional body",
"delete_branch_after_merge": true
}
```
Merge styles: `merge`, `rebase`, `rebase-merge`, `squash`, `fast-forward-only`
## Tool spec
```
tool: pr_merge
params:
owner: string
name: string // repo name
number: integer // PR number >= 1
style: string? // merge | squash | rebase | fast-forward-only (default: merge)
title: string? // merge commit title
message: string? // merge commit body
delete_branch: bool? // delete head branch after merge (default: true)
```
## Required token permission
`write:repository` scope — same as existing write tools.
## Risk classification
**MEDIUM** — merging is reversible via revert, but has real consequences.
No confirm param needed (unlike repo_delete) but tool description should be explicit.
## Implementation notes
- Follow pattern of existing tools in `internal/tools/`
- Always check PR is open before attempting merge — return clear error if already merged/closed
- `delete_branch: true` by default (consistent with TBD convention)
- Test cases:
- Happy path: open PR merged successfully
- Already merged: returns clear error
- PR not found (404)
- Allowlist rejection
- Merge conflict (Gitea returns 405) — return actionable error message
## Also fix: pr_files_diff loop bug already resolved
Note: pr_files_diff bug (#25) was already fixed in v0.2. pr_merge is the last
missing tool for a complete PR workflow from claude.ai.
## Acceptance criteria
- [ ] `task check` passes
- [ ] `pr_merge` registered in main
- [ ] Manual test: create test PR, merge via claude.ai, verify branch deleted
- [ ] Error case tested: attempt to merge already-merged PR returns clear error
- [ ] Committed directly to main (TBD)
## Part of
gitea-mcp v0.3 batch alongside:
- #30 issue_close / issue_reopen
- #11 repo_delete
- #17 release_create
Already shipped. pr_merge tool landed in commit 284d5e1 (feat(tools): pr_merge). I used it from this session — see the merges of e.g. infra commits earlier today, which all went through the corresponding workflow.
Verification:
$ grep -rn "NewPRMerge" --include="*.go"
cmd/gitea-mcp/main.go:53: reg.Register(tools.NewPRMerge(giteaClient, ownerAllow))
internal/tools/pr_merge.go:18:func NewPRMerge(c *gitea.Client, a *allowlist.Allowlist) *PRMerge {
$ go test ./internal/tools/ -run TestPRMerge -v
=== RUN TestPRMergeSuccess --- PASS
=== RUN TestPRMergeDefaultsToMergeStyle --- PASS
=== RUN TestPRMergeConflictReturnsError --- PASS
=== RUN TestPRMergeAllowlistRejects --- PASS
PASS
Closes.
Already shipped. `pr_merge` tool landed in commit `284d5e1` (`feat(tools): pr_merge`). I used it from this session — see the merges of e.g. infra commits earlier today, which all went through the corresponding workflow.
Verification:
```
$ grep -rn "NewPRMerge" --include="*.go"
cmd/gitea-mcp/main.go:53: reg.Register(tools.NewPRMerge(giteaClient, ownerAllow))
internal/tools/pr_merge.go:18:func NewPRMerge(c *gitea.Client, a *allowlist.Allowlist) *PRMerge {
$ go test ./internal/tools/ -run TestPRMerge -v
=== RUN TestPRMergeSuccess --- PASS
=== RUN TestPRMergeDefaultsToMergeStyle --- PASS
=== RUN TestPRMergeConflictReturnsError --- PASS
=== RUN TestPRMergeAllowlistRejects --- PASS
PASS
```
Closes.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Add
pr_mergetool to allow merging pull requests from claude.ai sessions via gitea-mcp.This is the critical missing piece for a complete code workflow from claude.ai without
needing GitHub or a local terminal.
Why this is now P0
With the ADR decision (infra #34) that Gitea is true master and GitHub is optional,
the tooling gap on the Gitea side must be closed. Today, claude.ai can:
✅ Read files, list repos, browse code
✅ Write files, create branches
✅ Create issues, comment on issues
✅ Create PRs (pr_create)
❌ Merge PRs — missing, blocks completing any code change from claude.ai
Without pr_merge, every code change started from claude.ai must be completed
in a terminal or web UI. That breaks the workflow.
Gitea API
POST /api/v1/repos/{owner}/{repo}/pulls/{index}/mergeBody:
Merge styles:
merge,rebase,rebase-merge,squash,fast-forward-onlyTool spec
Required token permission
write:repositoryscope — same as existing write tools.Risk classification
MEDIUM — merging is reversible via revert, but has real consequences.
No confirm param needed (unlike repo_delete) but tool description should be explicit.
Implementation notes
internal/tools/delete_branch: trueby default (consistent with TBD convention)Also fix: pr_files_diff loop bug already resolved
Note: pr_files_diff bug (#25) was already fixed in v0.2. pr_merge is the last
missing tool for a complete PR workflow from claude.ai.
Acceptance criteria
task checkpassespr_mergeregistered in mainPart of
gitea-mcp v0.3 batch alongside:
Already shipped.
pr_mergetool landed in commit284d5e1(feat(tools): pr_merge). I used it from this session — see the merges of e.g. infra commits earlier today, which all went through the corresponding workflow.Verification:
Closes.