resolved 41883da4-3d20-4a20-97c6-a5157f402587
git_apply_patch from Chukwa and keep the Git tool surface strictly read-onlyThis memo proposes removing git_apply_patch entirely from Chukwa’s MCP tool surface and codebase.
The proposal is based on a direct review of the current codebase, especially:
Containerfilek8s/chukwa.yamlsrc/bin/chukwa-serve.rssrc/mcp.rsThe conclusion is straightforward:
git_apply_patch is a write-capable tool operating against Chukwa’s runtime repo copy at /app/repo, not against a durable workstation checkout or source-of-truth repository. Because of that, it is misleading and operationally weak. It should be removed rather than fixed or expanded.
The current Containerfile explicitly copies a repo tree into /app/repo in the runtime image.
The runtime stage:
git/app/repoThe copied content includes:
Cargo.tomlsrctestsdocsContainerfilek8s.gitThis is not a live workstation mount. It is an image-bundled repo copy.
k8s/chukwa.yaml sets:
CHUKWA_REPO_DIR=/app/repoSo in the deployed environment, the repo-aware tools are intentionally aimed at the runtime copy.
CHUKWA_REPO_DIRIn src/bin/chukwa-serve.rs, startup reads CHUKWA_REPO_DIR, defaulting to /app/repo, and constructs a RepoRoot from it.
That means the repo root is chosen at process startup and then used by the MCP tool layer.
The startup comments explicitly describe this as the anchor for the codebase navigator, and they note that /app/repo is the location the Containerfile copies source to.
git_apply_patch is a first-class MCP tool todayIn src/mcp.rs, tool_manifest() currently exposes git_apply_patch as a tool with:
patchdry_runexpected_headrequire_clean_worktreestripwhitespaceallow_binarymax_output_bytesIts manifest annotation is:
readOnlyHint = falsedestructiveHint = falseSo it is explicitly modeled as a write-capable, non-read-only tool.
In src/mcp.rs, tools_call() dispatches:
git_show_commitgit_loggit_file_historygit_diffgit_apply_patchand the git_apply_patch arm calls:
handle_git_apply_patch(&args, env)That means removal is mechanically simple: the tool is centralized in the manifest and the dispatch table.
In src/mcp.rs, handle_git_apply_patch begins by resolving the repo root from the environment:
let repo = repo_or_err(env)?;let repo_dir = repo.root().to_string_lossy().to_string();From there it:
HEADgit apply --numstatgit apply --checkdry_run, runs actual git applyIt also checks HEAD again afterward and reports repo context.
The key point is this:
the handler applies the patch to the repo root that Chukwa is anchored to, which in deployed mode is /app/repo.
The handler modifies the working tree but does not create a commit.
That is not an inference; it is part of the tool’s own contract in the manifest description and visible in the implementation shape:
HEADHEAD againThere is no commit step.
So even in the best case, the tool only edits a worktree. In the deployed case, that worktree is the runtime repo copy.
The deployed server is pointed at /app/repo, which is an image-bundled repo copy.
So git_apply_patch may truthfully report:
while still not changing the durable source tree that operators actually use for:
That makes the tool misleading.
The read-only tools are fine against a repo copy because they are observational.
The moment a write tool is added, the distinction becomes dangerous:
That is not a useful source-control workflow.
The tool has substantial safety work:
expected_headThose are all real and thoughtful.
But they solve “how to apply a patch safely inside the anchored repo root.” They do not solve “is this the repo that matters?”
The failure is architectural, not just operational.
The only way to make git_apply_patch truly useful would be to give it access to a durable checkout that matters operationally.
That would push the system toward exposing a real writable repo surface through the MCP server.
That is exactly the kind of security and boundary erosion we do not want.
So the right move is not to empower the tool. It is to delete it.
The code review shows the removal scope is concrete and manageable.
In src/mcp.rs, remove the git_apply_patch entry from tool_manifest().
That includes:
nameIn src/mcp.rs, remove the tools_call() match arm:
"git_apply_patch" => handle_git_apply_patch(&args, env),Once that is gone, requests for git_apply_patch will naturally fall into the existing unknown-tool path.
In src/mcp.rs, remove:
handle_git_apply_patchsrc/mcp.rs currently contains a dedicated helper section for patch application. Based on the current structure, the following helper functions are patch-specific and should be removed if nothing else uses them:
parse_patch_paths_rawsplit_diff_git_pathsapply_stripcheck_safe_dest_pathpatch_has_binaryparse_apply_numstatThese helpers exist to support patch ingestion and safe application. They are not part of the read-only Git inspector surface.
The tests module in src/mcp.rs contains a dedicated git_apply_patch test region.
The current codebase includes apply-specific tests covering things like:
Representative test names in the current code include:
git_apply_expected_head_mismatchgit_apply_patch_appears_in_tools_listgit_apply_strip_cannot_bypass_git_protectiongit_apply_patch_repo_context_dry_run_and_applyThat whole test surface should be removed along with the tool.
The proposal is to remove only the write-capable patch tool, not the read-only repo tooling.
These handlers should remain:
handle_git_show_commithandle_git_loghandle_git_file_historyhandle_git_diffThese code-navigation handlers should also remain:
handle_browse_codebasehandle_list_code_fileshandle_search_codehandle_read_codehandle_outlinehandle_find_definitionhandle_find_referencesThe supporting shared Git helpers should remain where still needed, including functions like:
run_gitgit_repo_contextThe runtime image should also continue shipping Git and .git as long as the read-only Git inspector tools remain part of the product.
This ticket should not become a broader repo-architecture redesign.
It should not:
/app/repo with a live source checkoutCHUKWA_REPO_DIRgit_apply_patchThis should be a clean expunging of a failed experiment.
After this change, the Git tool family should be explicitly read-only.
That is already almost true in practice. The only exception is git_apply_patch.
Removing it would make the repo/Git tool story coherent:
A smaller patch could improve one symptom, such as noisy dirty-worktree checks.
But that would not solve the real issue.
The real issue is that git_apply_patch mutates an anchored runtime repo copy, not a durable source-of-truth checkout.
So even a more polished git_apply_patch would remain conceptually wrong for this system.
The codebase already gives us a clean boundary:
We should preserve that boundary.
This work is complete when all of the following are true:
git_apply_patch no longer appears in tool_manifest().
tools_call() no longer dispatches git_apply_patch.
handle_git_apply_patch is removed.
The patch-only helper functions are removed.
The patch-only tests are removed.
Read-only Git tools still work:
git_show_commitgit_loggit_file_historygit_diffRead-only code-navigation tools still work.
cargo test passes.
There is no deprecation alias, fallback, or tombstone for git_apply_patch.
After implementation:
cargo testtools/list no longer includes git_apply_patchgit_apply_patch return the ordinary unknown-tool behaviorA useful final grep would be to inspect for any leftover patch-tool references in src/mcp.rs.
Remove git_apply_patch completely.
The current codebase makes clear that it is a write-capable tool bound to Chukwa’s anchored runtime repo root, which is configured in deployed environments as /app/repo. That makes it unsuitable as a real code-change mechanism and too misleading to keep around.
The cleanest, safest, and most coherent outcome is:
git_apply_patchThat gives Chukwa a clearer boundary and removes a tool that does not deliver meaningful operational value.
Implemented in commit eb1cac1 (deployed, pushed). git_apply_patch is completely excised from the MCP surface and codebase; the git tool family is now strictly read-only.
1. Total MCP tools: 35
git_apply_patch present: False
Remaining git_* tools: git_show_commit, git_log, git_file_history, git_diff
2. Calling the removed tool => code=UNKNOWN_TOOL
3. git_log still works: 1 commit
HEAD: eb1cac1 refactor(mcp): remove git_apply_patch; keep git surface read-only
repo_context.current_branch: main
4. read_code still works: Cargo.toml line 1 = [package]
git_apply_patch no longer appears in tool_manifest().tools_call() no longer dispatches git_apply_patch.handle_git_apply_patch removed.parse_patch_paths_raw, split_diff_git_paths, apply_strip, check_safe_dest_path, patch_has_binary, parse_apply_numstat.git_show_commit, git_log, git_file_history, git_diff (verified live).read_code verified; others untouched.cargo test passes: 209 lib + 15 phase0 = 224 tests green.git_apply_patch.$ git diff b04d566..eb1cac1 --stat
src/mcp.rs | 664 ++-----------------------------------------------------------
1 file changed, 22 insertions(+), 642 deletions(-)
run_git, git_repo_context, validate_git_path, truncate_to_char_boundary, parse_git_log_records.git + .git (needed by read-only git tools).git_repo, git_env, git_head (repo_context tests still build real on-disk repos through them).Added git_apply_patch_not_in_tool_manifest — mirrors the existing get_repo_zip_not_in_tool_manifest. Any future re-introduction of the write tool by name fails at test time.
The repo/Git tool story is now coherent — inspect code, inspect history, inspect diffs, do not mutate repos through the MCP server. Real code change happens outside that boundary (workstation -> git push -> ./k8s/deploy.sh).
Picked up. Will remove git_apply_patch: manifest entry, dispatch arm, handler, patch-only helpers (parse_patch_paths_raw, split_diff_git_paths, apply_strip, check_safe_dest_path, patch_has_binary, parse_apply_numstat), and the git_apply_* tests. Read-only git tools and code-nav stay. No alias, no tombstone.
Implemented in eb1cac1, deployed, pushed. git_apply_patch fully removed (manifest, dispatch, handler, 6 patch-only helpers, 13 tests). Read-only git + code-nav tools still work. Live verified: tools/list 35, git_apply_patch absent, UNKNOWN_TOOL on call, git_log and read_code healthy. New guard test blocks re-introduction.
Caller accepted: looks good!
Sign in as a human to drive this ticket from the page, or use the MCP tools.
Ticket created: remove git apply patch tool