Skip to content

Commit 309d811

Browse files
committed
1. Make sha optional (if not supplied - GetContents is used to retrieve original sha)
2. Instruct LLM to supply actual sha using git command and move instructions to tool description.
1 parent a0dbccd commit 309d811

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

pkg/github/instructions.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,6 @@ Tool usage guidance:
5050
// getToolsetInstructions returns specific instructions for individual toolsets
5151
func getToolsetInstructions(toolset string, enabledToolsets []string) string {
5252
switch toolset {
53-
case "repos":
54-
return `## Repositories
55-
56-
Before updating an existing file, always call 'get_file_contents' to retrieve the SHA of the file blob. Use this SHA as the "sha" parameter in create_or_update_file tool call to avoid conflicts.
57-
`
5853
case "pull_requests":
5954
pullRequestInstructions := `## Pull Requests
6055

pkg/github/repositories.go

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,15 @@ func ListBranches(getClient GetClientFn, t translations.TranslationHelperFunc) (
310310
// CreateOrUpdateFile creates a tool to create or update a file in a GitHub repository.
311311
func CreateOrUpdateFile(getClient GetClientFn, t translations.TranslationHelperFunc) (mcp.Tool, mcp.ToolHandlerFor[map[string]any, any]) {
312312
tool := mcp.Tool{
313-
Name: "create_or_update_file",
314-
Description: t("TOOL_CREATE_OR_UPDATE_FILE_DESCRIPTION", "Create or update a single file in a GitHub repository. If updating, you must provide the SHA of the file you want to update. Use this tool to create or update a file in a GitHub repository remotely; do not use it for local file operations."),
313+
Name: "create_or_update_file",
314+
Description: t("TOOL_CREATE_OR_UPDATE_FILE_DESCRIPTION", `Create or update a single file in a GitHub repository.
315+
If updating, you should provide the SHA of the file you want to update. Use this tool to create or update a file in a GitHub repository remotely; do not use it for local file operations.
316+
317+
In order to obtain the SHA of original file version before updating, use the following git command:
318+
git ls-tree HEAD <path to file>
319+
320+
If the SHA is not provided, the tool will attempt to acquire it by fetching the current file contents from the repository, which may lead to rewriting latest committed changes if the file has changed since last retrieval.
321+
`),
315322
Annotations: &mcp.ToolAnnotations{
316323
Title: t("TOOL_CREATE_OR_UPDATE_FILE_USER_TITLE", "Create or update file"),
317324
ReadOnlyHint: false,
@@ -345,7 +352,7 @@ func CreateOrUpdateFile(getClient GetClientFn, t translations.TranslationHelperF
345352
},
346353
"sha": {
347354
Type: "string",
348-
Description: "Required if updating an existing file. The blob SHA of the file being replaced.",
355+
Description: "The blob SHA of the file being replaced.",
349356
},
350357
},
351358
Required: []string{"owner", "repo", "path", "content", "message", "branch"},
@@ -406,11 +413,32 @@ func CreateOrUpdateFile(getClient GetClientFn, t translations.TranslationHelperF
406413
path = strings.TrimPrefix(path, "/")
407414
fileContent, resp, err := client.Repositories.CreateFile(ctx, owner, repo, path, opts)
408415
if err != nil {
409-
return ghErrors.NewGitHubAPIErrorResponse(ctx,
410-
"failed to create/update file",
411-
resp,
412-
err,
413-
), nil, nil
416+
if strings.Contains(err.Error(), `"sha" wasn't supplied`) && sha == "" {
417+
// attempt to get the current file SHA by fetching the file contents
418+
getOpts := &github.RepositoryContentGetOptions{
419+
Ref: branch,
420+
}
421+
currentFileContent, _, respContents, err := client.Repositories.GetContents(ctx, owner, repo, path, getOpts)
422+
defer func() { _ = respContents.Body.Close() }()
423+
424+
if err == nil && currentFileContent != nil {
425+
opts.SHA = currentFileContent.SHA
426+
fileContent, resp, err = client.Repositories.CreateFile(ctx, owner, repo, path, opts)
427+
if err != nil {
428+
return ghErrors.NewGitHubAPIErrorResponse(ctx,
429+
"failed to create/update file after retrieving current SHA",
430+
resp,
431+
err,
432+
), nil, nil
433+
}
434+
}
435+
} else {
436+
return ghErrors.NewGitHubAPIErrorResponse(ctx,
437+
"failed to create/update file",
438+
resp,
439+
err,
440+
), nil, nil
441+
}
414442
}
415443
defer func() { _ = resp.Body.Close() }()
416444

0 commit comments

Comments
 (0)