@@ -612,6 +612,128 @@ func CreateRepository(t translations.TranslationHelperFunc) inventory.ServerTool
612612 )
613613}
614614
615+ // CreateRepositoryFromTemplate creates a tool to create a new GitHub repository from a template.
616+ func CreateRepositoryFromTemplate (t translations.TranslationHelperFunc ) inventory.ServerTool {
617+ return NewTool (
618+ ToolsetMetadataRepos ,
619+ mcp.Tool {
620+ Name : "create_repository_from_template" ,
621+ Description : t ("TOOL_CREATE_REPOSITORY_FROM_TEMPLATE_DESCRIPTION" , "Create a new GitHub repository from a template repository" ),
622+ Annotations : & mcp.ToolAnnotations {
623+ Title : t ("TOOL_CREATE_REPOSITORY_FROM_TEMPLATE_USER_TITLE" , "Create repository from template" ),
624+ ReadOnlyHint : false ,
625+ },
626+ InputSchema : & jsonschema.Schema {
627+ Type : "object" ,
628+ Properties : map [string ]* jsonschema.Schema {
629+ "template_owner" : {
630+ Type : "string" ,
631+ Description : "Owner of the template repository" ,
632+ },
633+ "template_repo" : {
634+ Type : "string" ,
635+ Description : "Name of the template repository" ,
636+ },
637+ "name" : {
638+ Type : "string" ,
639+ Description : "Name for the new repository" ,
640+ },
641+ "description" : {
642+ Type : "string" ,
643+ Description : "Description for the new repository" ,
644+ },
645+ "owner" : {
646+ Type : "string" ,
647+ Description : "Owner for the new repository (username or organization). Omit to create in your personal account" ,
648+ },
649+ "private" : {
650+ Type : "boolean" ,
651+ Description : "Whether the new repository should be private" ,
652+ },
653+ "include_all_branches" : {
654+ Type : "boolean" ,
655+ Description : "Whether to include all branches from template (default: false, only default branch)" ,
656+ },
657+ },
658+ Required : []string {"template_owner" , "template_repo" , "name" },
659+ },
660+ },
661+ func (ctx context.Context , deps ToolDependencies , _ * mcp.CallToolRequest , args map [string ]any ) (* mcp.CallToolResult , any , error ) {
662+ templateOwner , err := RequiredParam [string ](args , "template_owner" )
663+ if err != nil {
664+ return utils .NewToolResultError (err .Error ()), nil , nil
665+ }
666+ templateRepo , err := RequiredParam [string ](args , "template_repo" )
667+ if err != nil {
668+ return utils .NewToolResultError (err .Error ()), nil , nil
669+ }
670+ name , err := RequiredParam [string ](args , "name" )
671+ if err != nil {
672+ return utils .NewToolResultError (err .Error ()), nil , nil
673+ }
674+ description , err := OptionalParam [string ](args , "description" )
675+ if err != nil {
676+ return utils .NewToolResultError (err .Error ()), nil , nil
677+ }
678+ owner , err := OptionalParam [string ](args , "owner" )
679+ if err != nil {
680+ return utils .NewToolResultError (err .Error ()), nil , nil
681+ }
682+ private , err := OptionalParam [bool ](args , "private" )
683+ if err != nil {
684+ return utils .NewToolResultError (err .Error ()), nil , nil
685+ }
686+ includeAllBranches , err := OptionalParam [bool ](args , "include_all_branches" )
687+ if err != nil {
688+ return utils .NewToolResultError (err .Error ()), nil , nil
689+ }
690+
691+ templateReq := & github.TemplateRepoRequest {
692+ Name : github .Ptr (name ),
693+ Owner : github .Ptr (owner ),
694+ Description : github .Ptr (description ),
695+ Private : github .Ptr (private ),
696+ IncludeAllBranches : github .Ptr (includeAllBranches ),
697+ }
698+
699+ client , err := deps .GetClient (ctx )
700+ if err != nil {
701+ return nil , nil , fmt .Errorf ("failed to get GitHub client: %w" , err )
702+ }
703+ createdRepo , resp , err := client .Repositories .CreateFromTemplate (ctx , templateOwner , templateRepo , templateReq )
704+ if err != nil {
705+ return ghErrors .NewGitHubAPIErrorResponse (ctx ,
706+ "failed to create repository from template" ,
707+ resp ,
708+ err ,
709+ ), nil , nil
710+ }
711+ defer func () { _ = resp .Body .Close () }()
712+
713+ if resp .StatusCode != http .StatusCreated {
714+ body , err := io .ReadAll (resp .Body )
715+ if err != nil {
716+ return nil , nil , fmt .Errorf ("failed to read response body: %w" , err )
717+ }
718+ return ghErrors .NewGitHubAPIStatusErrorResponse (ctx , "failed to create repository from template" , resp , body ), nil , nil
719+ }
720+
721+ // Return minimal response with just essential information
722+ minimalResponse := MinimalResponse {
723+ ID : fmt .Sprintf ("%d" , createdRepo .GetID ()),
724+ URL : createdRepo .GetHTMLURL (),
725+ }
726+
727+ r , err := json .Marshal (minimalResponse )
728+ if err != nil {
729+ return nil , nil , fmt .Errorf ("failed to marshal response: %w" , err )
730+ }
731+
732+ return utils .NewToolResultText (string (r )), nil , nil
733+ },
734+ )
735+ }
736+
615737// GetFileContents creates a tool to get the contents of a file or directory from a GitHub repository.
616738func GetFileContents (t translations.TranslationHelperFunc ) inventory.ServerTool {
617739 return NewTool (
0 commit comments