@@ -560,7 +560,7 @@ func GetFileContents(getClient GetClientFn, getRawClient raw.GetRawClientFn, t t
560560 },
561561 "path" : {
562562 Type : "string" ,
563- Description : "Path to file/directory (directories must end with a slash '/') " ,
563+ Description : "Path to file/directory" ,
564564 Default : json .RawMessage (`"/"` ),
565565 },
566566 "ref" : {
@@ -608,132 +608,126 @@ func GetFileContents(getClient GetClientFn, getRawClient raw.GetRawClientFn, t t
608608 return utils .NewToolResultError (fmt .Sprintf ("failed to resolve git reference: %s" , err )), nil , nil
609609 }
610610
611+ if rawOpts .SHA != "" {
612+ ref = rawOpts .SHA
613+ }
614+
611615 // If the path is (most likely) not to be a directory, we will
612616 // first try to get the raw content from the GitHub raw content API.
613617
614618 var rawAPIResponseCode int
615- if path != "" && ! strings .HasSuffix (path , "/" ) {
616- // First, get file info from Contents API to retrieve SHA
617- var fileSHA string
618- opts := & github.RepositoryContentGetOptions {Ref : ref }
619- fileContent , _ , respContents , err := client .Repositories .GetContents (ctx , owner , repo , path , opts )
620- if respContents != nil {
621- defer func () { _ = respContents .Body .Close () }()
622- }
623- if err != nil {
624- return ghErrors .NewGitHubAPIErrorResponse (ctx ,
625- "failed to get file SHA" ,
626- respContents ,
627- err ,
628- ), nil , nil
629- }
630- if fileContent == nil || fileContent .SHA == nil {
631- return utils .NewToolResultError ("file content SHA is nil, if a directory was requested, path parameters should end with a trailing slash '/'" ), nil , nil
632- }
633- fileSHA = * fileContent .SHA
619+ // First, get file info from Contents API to retrieve SHA
620+ var fileSHA string
621+ opts := & github.RepositoryContentGetOptions {Ref : ref }
622+ fileContent , dirContent , respContents , err := client .Repositories .GetContents (ctx , owner , repo , path , opts )
623+ if respContents != nil {
624+ defer func () { _ = respContents .Body .Close () }()
625+ }
626+ if err != nil {
627+ return ghErrors .NewGitHubAPIErrorResponse (ctx ,
628+ "failed to get file SHA" ,
629+ respContents ,
630+ err ,
631+ ), nil , nil
632+ }
634633
635- rawClient , err := getRawClient (ctx )
634+ // file content or file SHA is nil which means it's a directory
635+ if fileContent == nil || fileContent .SHA == nil {
636+ defer func () { _ = respContents .Body .Close () }()
637+ r , err := json .Marshal (dirContent )
636638 if err != nil {
637- return utils .NewToolResultError ("failed to get GitHub raw content client " ), nil , nil
639+ return utils .NewToolResultError ("failed to marshal response " ), nil , nil
638640 }
639- resp , err := rawClient .GetRawContent (ctx , owner , repo , path , rawOpts )
641+ return utils .NewToolResultText (string (r )), nil , nil
642+ }
643+
644+ fileSHA = * fileContent .SHA
645+
646+ rawClient , err := getRawClient (ctx )
647+ if err != nil {
648+ return utils .NewToolResultError ("failed to get GitHub raw content client" ), nil , nil
649+ }
650+ resp , err := rawClient .GetRawContent (ctx , owner , repo , path , rawOpts )
651+ if err != nil {
652+ return utils .NewToolResultError ("failed to get raw repository content" ), nil , nil
653+ }
654+ defer func () {
655+ _ = resp .Body .Close ()
656+ }()
657+
658+ if resp .StatusCode == http .StatusOK {
659+ // If the raw content is found, return it directly
660+ body , err := io .ReadAll (resp .Body )
640661 if err != nil {
641- return utils .NewToolResultError ("failed to get raw repository content " ), nil , nil
662+ return utils .NewToolResultError ("failed to read response body " ), nil , nil
642663 }
643- defer func () {
644- _ = resp .Body .Close ()
645- }()
664+ contentType := resp .Header .Get ("Content-Type" )
646665
647- if resp .StatusCode == http .StatusOK {
648- // If the raw content is found, return it directly
649- body , err := io .ReadAll (resp .Body )
666+ var resourceURI string
667+ switch {
668+ case sha != "" :
669+ resourceURI , err = url .JoinPath ("repo://" , owner , repo , "sha" , sha , "contents" , path )
650670 if err != nil {
651- return utils . NewToolResultError ("failed to read response body" ), nil , nil
671+ return nil , nil , fmt . Errorf ("failed to create resource URI: %w" , err )
652672 }
653- contentType := resp .Header .Get ("Content-Type" )
654-
655- var resourceURI string
656- switch {
657- case sha != "" :
658- resourceURI , err = url .JoinPath ("repo://" , owner , repo , "sha" , sha , "contents" , path )
659- if err != nil {
660- return nil , nil , fmt .Errorf ("failed to create resource URI: %w" , err )
661- }
662- case ref != "" :
663- resourceURI , err = url .JoinPath ("repo://" , owner , repo , ref , "contents" , path )
664- if err != nil {
665- return nil , nil , fmt .Errorf ("failed to create resource URI: %w" , err )
666- }
667- default :
668- resourceURI , err = url .JoinPath ("repo://" , owner , repo , "contents" , path )
669- if err != nil {
670- return nil , nil , fmt .Errorf ("failed to create resource URI: %w" , err )
671- }
673+ case ref != "" :
674+ resourceURI , err = url .JoinPath ("repo://" , owner , repo , ref , "contents" , path )
675+ if err != nil {
676+ return nil , nil , fmt .Errorf ("failed to create resource URI: %w" , err )
672677 }
673-
674- // Determine if content is text or binary
675- isTextContent := strings .HasPrefix (contentType , "text/" ) ||
676- contentType == "application/json" ||
677- contentType == "application/xml" ||
678- strings .HasSuffix (contentType , "+json" ) ||
679- strings .HasSuffix (contentType , "+xml" )
680-
681- if isTextContent {
682- result := & mcp.ResourceContents {
683- URI : resourceURI ,
684- Text : string (body ),
685- MIMEType : contentType ,
686- }
687- // Include SHA in the result metadata
688- if fileSHA != "" {
689- return utils .NewToolResultResource (fmt .Sprintf ("successfully downloaded text file (SHA: %s)" , fileSHA ), result ), nil , nil
690- }
691- return utils .NewToolResultResource ("successfully downloaded text file" , result ), nil , nil
678+ default :
679+ resourceURI , err = url .JoinPath ("repo://" , owner , repo , "contents" , path )
680+ if err != nil {
681+ return nil , nil , fmt .Errorf ("failed to create resource URI: %w" , err )
692682 }
683+ }
684+
685+ // Determine if content is text or binary
686+ isTextContent := strings .HasPrefix (contentType , "text/" ) ||
687+ contentType == "application/json" ||
688+ contentType == "application/xml" ||
689+ strings .HasSuffix (contentType , "+json" ) ||
690+ strings .HasSuffix (contentType , "+xml" )
693691
692+ if isTextContent {
694693 result := & mcp.ResourceContents {
695694 URI : resourceURI ,
696- Blob : body ,
695+ Text : string ( body ) ,
697696 MIMEType : contentType ,
698697 }
699698 // Include SHA in the result metadata
700699 if fileSHA != "" {
701- return utils .NewToolResultResource (fmt .Sprintf ("successfully downloaded binary file (SHA: %s)" , fileSHA ), result ), nil , nil
700+ return utils .NewToolResultResource (fmt .Sprintf ("successfully downloaded text file (SHA: %s)" , fileSHA ), result ), nil , nil
702701 }
703- return utils .NewToolResultResource ("successfully downloaded binary file" , result ), nil , nil
702+ return utils .NewToolResultResource ("successfully downloaded text file" , result ), nil , nil
704703 }
705- rawAPIResponseCode = resp .StatusCode
706- }
707704
708- if rawOpts .SHA != "" {
709- ref = rawOpts .SHA
710- }
711- if strings .HasSuffix (path , "/" ) {
712- opts := & github.RepositoryContentGetOptions {Ref : ref }
713- _ , dirContent , resp , err := client .Repositories .GetContents (ctx , owner , repo , path , opts )
714- if err == nil && resp .StatusCode == http .StatusOK {
715- defer func () { _ = resp .Body .Close () }()
716- r , err := json .Marshal (dirContent )
717- if err != nil {
718- return utils .NewToolResultError ("failed to marshal response" ), nil , nil
719- }
720- return utils .NewToolResultText (string (r )), nil , nil
705+ result := & mcp.ResourceContents {
706+ URI : resourceURI ,
707+ Blob : body ,
708+ MIMEType : contentType ,
709+ }
710+ // Include SHA in the result metadata
711+ if fileSHA != "" {
712+ return utils .NewToolResultResource (fmt .Sprintf ("successfully downloaded binary file (SHA: %s)" , fileSHA ), result ), nil , nil
721713 }
714+ return utils .NewToolResultResource ("successfully downloaded binary file" , result ), nil , nil
722715 }
716+ rawAPIResponseCode = resp .StatusCode
723717
724718 // The path does not point to a file or directory.
725719 // Instead let's try to find it in the Git Tree by matching the end of the path.
726720
727721 // Step 1: Get Git Tree recursively
728- tree , resp , err := client .Git .GetTree (ctx , owner , repo , ref , true )
722+ tree , response , err := client .Git .GetTree (ctx , owner , repo , ref , true )
729723 if err != nil {
730724 return ghErrors .NewGitHubAPIErrorResponse (ctx ,
731725 "failed to get git tree" ,
732- resp ,
726+ response ,
733727 err ,
734728 ), nil , nil
735729 }
736- defer func () { _ = resp .Body .Close () }()
730+ defer func () { _ = response .Body .Close () }()
737731
738732 // Step 2: Filter tree for matching paths
739733 const maxMatchingFiles = 3
0 commit comments