-
Notifications
You must be signed in to change notification settings - Fork 838
feat: add DeleteFile tool to delete files from GitHub repositories #356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -528,6 +528,96 @@ func ForkRepository(getClient GetClientFn, t translations.TranslationHelperFunc) | |||
} | |||
} | |||
|
|||
// DeleteFile creates a tool to delete a file in a GitHub repository. | |||
func DeleteFile(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) { | |||
return mcp.NewTool("delete_file", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, can you look at adding annotations? You can see examples around the codebase?
For this particular one, as well as the tool title with translation I would add:
ReadOnlyHint: false
DestructiveHint: true
https://modelcontextprotocol.io/docs/concepts/tools#tool-definition-structure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SamMorrowDrums done! Thanks for the suggestion.
abe06cd
to
e6201f4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ashwin-ant thanks for this PR. I'm a bit confused about the implementation though. It seems like you:
- Get a github ref for the current branch
- Get the commit for that ref
- Create a new TreeEntry without the file
- Create a new commit
- Update the ref
Why not:
- Get a github ref for the current branch
- Get the commit for that ref
- Get the SHA of the filepath in that commit
- Call
client.Repositories.DeleteFile
which exactly calls the API endpoint you referenced.
Edit: Maybe the TreeEntry approach allows for deletion of a directory where the contents API doesn't?
e6201f4
to
be01e09
Compare
@ashwin-ant I just rebased this and added some e2e tests that we can consider refactoring behind (and perhaps, demonstrating that we can't do directory removal with the contents API). You can run them like:
Make sure your token has I'll probably collapse them to one test later, but for the moment while we figure this out it makes sense to keep them separate. |
be01e09
to
d22667f
Compare
@williammartin Thanks for reviewing! I actually was going with that approach in my first commit here, but ended up switching to this more complicated approach in 4d5f719. The reason for this is that I discovered the REST file deletion endpoint (and |
That's a great explanation and I'd love it if you put that as a comment in the code for all future reviewers! |
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
…tool 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
18b51d4
to
33d0402
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
➜ github-mcp-server git:(ashwin/deletefile) ✗ GOMAXPROCS=1 GITHUB_MCP_SERVER_E2E_TOKEN=$(gh auth token) go test -v -count=1 -run TestFileDeletion --tags e2e ./e2e
=== RUN TestFileDeletion
=== PAUSE TestFileDeletion
=== CONT TestFileDeletion
e2e_test.go:50: Building Docker image for e2e tests...
e2e_test.go:124: Starting Stdio MCP client...
e2e_test.go:385: Getting current user...
e2e_test.go:413: Creating repository williammartin/github-mcp-server-e2e-TestFileDeletion-1747137948412...
e2e_test.go:437: Creating branch in williammartin/github-mcp-server-e2e-TestFileDeletion-1747137948412...
e2e_test.go:454: Creating commit with new file in williammartin/github-mcp-server-e2e-TestFileDeletion-1747137948412...
e2e_test.go:478: Getting file contents in williammartin/github-mcp-server-e2e-TestFileDeletion-1747137948412...
e2e_test.go:506: Deleting file in williammartin/github-mcp-server-e2e-TestFileDeletion-1747137948412...
e2e_test.go:520: Listing commits in williammartin/github-mcp-server-e2e-TestFileDeletion-1747137948412...
e2e_test.go:554: Getting commit williammartin/github-mcp-server-e2e-TestFileDeletion-1747137948412:76f50ad460c472d7eb9df09bd1c94d5678a99b96...
e2e_test.go:422: Deleting repository williammartin/github-mcp-server-e2e-TestFileDeletion-1747137948412...
--- PASS: TestFileDeletion (6.65s)
PASS
ok github.com/github/github-mcp-server/e2e 6.894s


LGTM, thanks.
Bypassing the last pusher rule because I fixed minor breaking changes from mcp-go bump on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a new delete_file
tool that leverages the Git Data API to delete files with commit signing, and adds accompanying tests.
- Registers
DeleteFile
in the GitHub toolset initialization. - Implements
DeleteFile
inrepositories.go
, creating a deletion commit via trees and references. - Adds
Test_DeleteFile
inrepositories_test.go
for success and branch-not-found scenarios.
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
File | Description |
---|---|
pkg/github/tools.go | Register the new DeleteFile tool in server toolsets. |
pkg/github/repositories.go | Implement DeleteFile using Git Data API calls. |
pkg/github/repositories_test.go | Add unit tests for the DeleteFile tool. |
Comments suppressed due to low confidence (1)
pkg/github/repositories_test.go:1532
- The test covers success and branch-not-found paths; consider adding cases for failures in tree creation, commit creation, and reference updates to ensure robust error handling across all stages of the deletion flow.
func Test_DeleteFile(t *testing.T) {
This adds a tool that matches the behavior of this API endpoint. This is needed since the
create_or_update_file
tool doesn't allow deletion.