feat: add PR/release/branch/milestone/comment write tools
Adds six opt-in write tools (write-mode + policy + per-user permission still
enforced; no destructive or admin actions):
- create_pull_request (POST /pulls)
- create_release / edit_release (POST/PATCH /releases)
- create_branch (POST /branches; create only, no deletion)
- create_milestone (POST /milestones)
- edit_issue_comment (PATCH /issues/comments/{id})
Each: arg schema (extra=forbid, GitRef on branch/ref-like fields), Gitea client
method with url-encoded path segments, handler that surfaces auth errors, MCP
registration (write_operation=True), server wiring, docs, and success tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -253,6 +253,70 @@ class RemoveLabelsArgs(RepositoryArgs):
|
||||
labels: list[str] = Field(..., min_length=1, max_length=20)
|
||||
|
||||
|
||||
class CreatePullRequestArgs(RepositoryArgs):
|
||||
"""Arguments for create_pull_request."""
|
||||
|
||||
title: str = Field(..., min_length=1, max_length=256)
|
||||
head: GitRef = Field(..., min_length=1, max_length=200)
|
||||
base: GitRef = Field(..., min_length=1, max_length=200)
|
||||
body: str = Field(default="", max_length=20_000)
|
||||
|
||||
|
||||
class CreateReleaseArgs(RepositoryArgs):
|
||||
"""Arguments for create_release."""
|
||||
|
||||
tag_name: GitRef = Field(..., min_length=1, max_length=200)
|
||||
name: str = Field(default="", max_length=256)
|
||||
body: str = Field(default="", max_length=20_000)
|
||||
draft: bool = Field(default=False)
|
||||
prerelease: bool = Field(default=False)
|
||||
target: str | None = Field(default=None, min_length=1, max_length=200)
|
||||
|
||||
|
||||
class EditReleaseArgs(RepositoryArgs):
|
||||
"""Arguments for edit_release."""
|
||||
|
||||
release_id: int = Field(..., ge=1)
|
||||
name: str | None = Field(default=None, max_length=256)
|
||||
body: str | None = Field(default=None, max_length=20_000)
|
||||
draft: bool | None = Field(default=None)
|
||||
prerelease: bool | None = Field(default=None)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def require_change(self) -> EditReleaseArgs:
|
||||
"""Require at least one mutable field in the update payload."""
|
||||
if (
|
||||
self.name is None
|
||||
and self.body is None
|
||||
and self.draft is None
|
||||
and self.prerelease is None
|
||||
):
|
||||
raise ValueError("At least one of name, body, draft, or prerelease must be provided")
|
||||
return self
|
||||
|
||||
|
||||
class CreateBranchArgs(RepositoryArgs):
|
||||
"""Arguments for create_branch."""
|
||||
|
||||
new_branch_name: GitRef = Field(..., min_length=1, max_length=200)
|
||||
old_branch_name: str | None = Field(default=None, min_length=1, max_length=200)
|
||||
|
||||
|
||||
class CreateMilestoneArgs(RepositoryArgs):
|
||||
"""Arguments for create_milestone."""
|
||||
|
||||
title: str = Field(..., min_length=1, max_length=256)
|
||||
description: str = Field(default="", max_length=10_000)
|
||||
due_on: str | None = Field(default=None, max_length=64)
|
||||
|
||||
|
||||
class EditIssueCommentArgs(RepositoryArgs):
|
||||
"""Arguments for edit_issue_comment."""
|
||||
|
||||
comment_id: int = Field(..., ge=1)
|
||||
body: str = Field(..., min_length=1, max_length=10_000)
|
||||
|
||||
|
||||
def extract_repository(arguments: dict[str, object]) -> str | None:
|
||||
"""Extract `owner/repo` from raw argument mapping.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user