Skip to content

Commit 57b1956

Browse files
committed
get_file_contents accepts a ref instead of just branch
1 parent f51096d commit 57b1956

File tree

1 file changed

+50
-11
lines changed

1 file changed

+50
-11
lines changed

pkg/github/repositories.go

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"io"
99
"net/http"
1010
"net/url"
11+
"strconv"
1112
"strings"
1213

1314
"github.com/github/github-mcp-server/pkg/raw"
@@ -432,8 +433,11 @@ func GetFileContents(getClient GetClientFn, getRawClient raw.GetRawClientFn, t t
432433
mcp.Required(),
433434
mcp.Description("Path to file/directory (directories must end with a slash '/')"),
434435
),
435-
mcp.WithString("branch",
436-
mcp.Description("Branch to get contents from"),
436+
mcp.WithString("ref",
437+
mcp.Description("Accepts optional git refs such as `refs/tags/<tag>`, `refs/heads/<branch>` or `refs/pull/<pr_number>/head`"),
438+
),
439+
mcp.WithString("sha",
440+
mcp.Description("Accepts optional git sha, if sha is specified it will be used instead of ref"),
437441
),
438442
),
439443
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
@@ -449,17 +453,44 @@ func GetFileContents(getClient GetClientFn, getRawClient raw.GetRawClientFn, t t
449453
if err != nil {
450454
return mcp.NewToolResultError(err.Error()), nil
451455
}
452-
branch, err := OptionalParam[string](request, "branch")
456+
ref, err := OptionalParam[string](request, "ref")
457+
if err != nil {
458+
return mcp.NewToolResultError(err.Error()), nil
459+
}
460+
sha, err := OptionalParam[string](request, "sha")
453461
if err != nil {
454462
return mcp.NewToolResultError(err.Error()), nil
455463
}
456464

465+
rawOpts := &raw.RawContentOpts{}
466+
467+
if strings.HasPrefix(path, "refs/pull/") {
468+
prNumber, ok := strings.CutPrefix(path, "refs/pull/")
469+
if ok && len(prNumber) > 0 {
470+
// fetch the PR from the API to get the latest commit and use SHA
471+
githubClient, err := getClient(ctx)
472+
if err != nil {
473+
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
474+
}
475+
prNum, err := strconv.Atoi(prNumber)
476+
if err != nil {
477+
return nil, fmt.Errorf("invalid pull request number: %w", err)
478+
}
479+
pr, _, err := githubClient.PullRequests.Get(ctx, owner, repo, prNum)
480+
if err != nil {
481+
return nil, fmt.Errorf("failed to get pull request: %w", err)
482+
}
483+
sha = pr.GetHead().GetSHA()
484+
ref = ""
485+
}
486+
}
487+
488+
rawOpts.SHA = sha
489+
rawOpts.Ref = ref
490+
457491
// If the path is (most likely) not to be a directory, we will first try to get the raw content from the GitHub raw content API.
458492
if path != "" && !strings.HasSuffix(path, "/") {
459-
rawOpts := &raw.RawContentOpts{}
460-
if branch != "" {
461-
rawOpts.Ref = "refs/heads/" + branch
462-
}
493+
463494
rawClient, err := getRawClient(ctx)
464495
if err != nil {
465496
return mcp.NewToolResultError("failed to get GitHub raw content client"), nil
@@ -483,14 +514,19 @@ func GetFileContents(getClient GetClientFn, getRawClient raw.GetRawClientFn, t t
483514
contentType := resp.Header.Get("Content-Type")
484515

485516
var resourceURI string
486-
if branch == "" {
517+
if sha != "" {
487518
// do a safe url join
488-
resourceURI, err = url.JoinPath("repo://", owner, repo, "contents", path)
519+
resourceURI, err = url.JoinPath("repo://", owner, repo, "sha", sha, "contents", path)
520+
if err != nil {
521+
return nil, fmt.Errorf("failed to create resource URI: %w", err)
522+
}
523+
} else if ref != "" {
524+
resourceURI, err = url.JoinPath("repo://", owner, repo, ref, "contents", path)
489525
if err != nil {
490526
return nil, fmt.Errorf("failed to create resource URI: %w", err)
491527
}
492528
} else {
493-
resourceURI, err = url.JoinPath("repo://", owner, repo, "refs", "heads", branch, "contents", path)
529+
resourceURI, err = url.JoinPath("repo://", owner, repo, "contents", path)
494530
if err != nil {
495531
return nil, fmt.Errorf("failed to create resource URI: %w", err)
496532
}
@@ -517,8 +553,11 @@ func GetFileContents(getClient GetClientFn, getRawClient raw.GetRawClientFn, t t
517553
return mcp.NewToolResultError("failed to get GitHub client"), nil
518554
}
519555

556+
if sha != "" {
557+
ref = sha
558+
}
520559
if strings.HasSuffix(path, "/") {
521-
opts := &github.RepositoryContentGetOptions{Ref: branch}
560+
opts := &github.RepositoryContentGetOptions{Ref: ref}
522561
_, dirContent, resp, err := client.Repositories.GetContents(ctx, owner, repo, path, opts)
523562
if err != nil {
524563
return mcp.NewToolResultError("failed to get file contents"), nil

0 commit comments

Comments
 (0)