feat(git): add git_branch_delete tool + fix(lean): wire configured token limits into ResponseOffloader#182
Conversation
GitHub exposes commit-signature enforcement on a separate endpoint
(.../protection/required_signatures), so it could not be set through
github_update_branch_protection. Closes that gap by adding a dedicated
enable/disable/get trio, mirroring the existing
github_*_vulnerability_alerts pattern.
New tools:
- github_get_required_signatures(repo_owner, repo_name, branch)
- github_enable_required_signatures(repo_owner, repo_name, branch)
- github_disable_required_signatures(repo_owner, repo_name, branch)
Endpoint: PUT/DELETE/GET /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures
- security.py: three async functions using github_client_context().
PUT returns 200+JSON (not 204 like vulnerability_alerts PUT);
DELETE returns 204; GET returns 200 with {enabled, url} or 404
when branch protection is absent.
- models.py: three Pydantic models with (repo_owner, repo_name, branch).
- registry_github.py: ToolDefinition trio added after vulnerability_alerts.
- api.py untouched (wildcard re-export of security.py covers new funcs).
- README.md tool counts: 52 -> 55 and 51/22 -> 54/25.
- tests/unit/github/test_github_required_signatures.py: 7 tests via
AsyncMock+patch(github_client_context) covering get (enabled/disabled/
404), enable (200/404), disable (204/404).
Closes #178
Local branch deletion already worked via git_branch_update(delete=True), but it was undiscoverable by name. Add a thin git_branch_delete tool that delegates to git_branch_update's delete path (no command reimplementation), so callers scanning for branch-delete find it directly. - operations_extended.py: git_branch_delete(repo, branch_name, force=False) delegating to git_branch_update(..., delete=True, force=force). - models.py: GitBranchDelete (repo_path, branch_name, force). - registry_git.py: ToolDefinition registered after git_branch_update. - tests/unit/git/test_git_branch_delete.py: 11 tests mirroring test_git_branch_update delete cases. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ResponseOffloader's offload threshold was hard-wired to MCPTokenLimiter's 2000-token default; MCP_GIT_LLM_TOKEN_LIMIT/MCP_GIT_UNKNOWN_TOKEN_LIMIT were loaded but never consumed by the lean stack. GitLeanInterface now builds its default MCPTokenLimiter from TokenLimitSettings so the env-configured limits actually gate offloading. Adds a regression test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
|
Claude finished @MementoRC's task —— View job PR ReviewTasks:
SummaryThis PR is well-structured with two independent but related improvements. The code is clean, follows existing patterns, and includes good test coverage. A few observations below.
|
Summary
Two related improvements to the lean git MCP interface, branched off the #178 required-signatures work.
1.
git_branch_delete— discoverable local branch deletionLocal branch deletion already worked via
git_branch_update(delete=True), but it was undiscoverable by name (callers scanning for agit_branch_deletetool concluded it didn't exist). Adds a thingit_branch_delete(repo, branch_name, force=False)that delegates to the existinggit_branch_updatedelete path — no command reimplementation.operations_extended.py:git_branch_deletedelegating togit_branch_update(..., delete=True, force=force)models.py:GitBranchDelete(repo_path, branch_name, force)lean/registry_git.py:ToolDefinitionregistered aftergit_branch_updatetests/unit/git/test_git_branch_delete.py: 11 tests2. Fix: wire configured token limits into
ResponseOffloaderResponseOffloader's offload-to-/tmpthreshold was hard-wired toMCPTokenLimiter's 2000-token default (~7 KB). TheMCP_GIT_LLM_TOKEN_LIMIT(20000) /MCP_GIT_UNKNOWN_TOKEN_LIMIT(25000) env vars were loaded byTokenLimitConfigManagerbut never consumed by the lean stack — dead config. As a result the server offloaded ~10x more aggressively than configured.GitLeanInterface.__init__now builds its defaultMCPTokenLimiterfromconfig_manager.get_current_settings()(default_limit=settings.unknown_token_limit,operation_limits=settings.operation_limits) so the env-configured limits actually gate offloading.lean/interface.py: settings-driven defaultMCPTokenLimitertests/unit/lean/test_offloader_token_limit.py: regression test (3 cases)Test plan
pixi run -e quality test-unit— full unit suite passes (exit 0)pixi run -e quality lint(ruff F,E9) — clean🤖 Generated with Claude Code