@@ -1700,6 +1700,130 @@ func AssignCopilotToIssue(getGQLClient GetGQLClientFn, t translations.Translatio
17001700 }
17011701}
17021702
1703+ // Label Management
1704+
1705+ // Create label
1706+ func CreateLabel (getGQLClient GetGQLClientFn , t translations.TranslationHelperFunc ) (mcp.Tool , server.ToolHandlerFunc ) {
1707+ return mcp .NewTool ("create_label" ,
1708+ mcp .WithDescription (t ("TOOL_CREATE_LABEL_DESCRIPTION" , "Create a new label in a GitHub repository." )),
1709+ mcp .WithToolAnnotation (mcp.ToolAnnotation {
1710+ Title : t ("TOOL_CREATE_LABEL_TITLE" , "Create label" ),
1711+ ReadOnlyHint : ToBoolPtr (false ),
1712+ }),
1713+ mcp .WithString ("owner" ,
1714+ mcp .Required (),
1715+ mcp .Description ("Repository owner" ),
1716+ ),
1717+ mcp .WithString ("repo" ,
1718+ mcp .Required (),
1719+ mcp .Description ("Repository name" ),
1720+ ),
1721+ mcp .WithString ("name" ,
1722+ mcp .Required (),
1723+ mcp .Description ("Name of the label to create" ),
1724+ ),
1725+ mcp .WithString ("color" ,
1726+ mcp .Required (),
1727+ mcp .Description ("Label color as a 6-character hex code without '#', e.g. 'f29513'" ),
1728+ ),
1729+ mcp .WithString ("description" ,
1730+ mcp .Description ("Label description" ),
1731+ ),
1732+ ),
1733+ func (ctx context.Context , request mcp.CallToolRequest ) (* mcp.CallToolResult , error ) {
1734+ owner , err := RequiredParam [string ](request , "owner" )
1735+ if err != nil {
1736+ return mcp .NewToolResultError (err .Error ()), nil
1737+ }
1738+ repo , err := RequiredParam [string ](request , "repo" )
1739+ if err != nil {
1740+ return mcp .NewToolResultError (err .Error ()), nil
1741+ }
1742+ name , err := RequiredParam [string ](request , "name" )
1743+ if err != nil {
1744+ return mcp .NewToolResultError (err .Error ()), nil
1745+ }
1746+ color , err := OptionalParam [string ](request , "color" )
1747+ if err != nil {
1748+ return mcp .NewToolResultError (err .Error ()), nil
1749+ }
1750+ description , err := OptionalParam [string ](request , "description" )
1751+ if err != nil {
1752+ return mcp .NewToolResultError (err .Error ()), nil
1753+ }
1754+
1755+ client , err := getGQLClient (ctx )
1756+ if err != nil {
1757+ return nil , fmt .Errorf ("failed to get GitHub client: %w" , err )
1758+ }
1759+
1760+ // First fetch the repository node ID since createLabel requires a repositoryId
1761+ var repoQuery struct {
1762+ Repository struct {
1763+ ID githubv4.ID
1764+ } `graphql:"repository(owner: $owner, name: $repo)"`
1765+ }
1766+
1767+ vars := map [string ]any {
1768+ "owner" : githubv4 .String (owner ),
1769+ "repo" : githubv4 .String (repo ),
1770+ }
1771+
1772+ if err := client .Query (ctx , & repoQuery , vars ); err != nil {
1773+ return ghErrors .NewGitHubGraphQLErrorResponse (ctx , "Failed to find repository" , err ), nil
1774+ }
1775+
1776+ // Build the input for createLabel. Only set optional fields when provided.
1777+ input := githubv4.CreateLabelInput {
1778+ RepositoryID : repoQuery .Repository .ID ,
1779+ Name : githubv4 .String (name ),
1780+ }
1781+ if color != "" {
1782+ input .Color = githubv4 .String (color )
1783+ }
1784+ if description != "" {
1785+ d := githubv4 .String (description )
1786+ input .Description = & d
1787+ }
1788+
1789+ var mutation struct {
1790+ CreateLabel struct {
1791+ Label struct {
1792+ ID githubv4.ID
1793+ Name githubv4.String
1794+ Color githubv4.String
1795+ Description githubv4.String
1796+ }
1797+ } `graphql:"createLabel(input: $input)"`
1798+ }
1799+
1800+ if err := client .Mutate (ctx , & mutation , input , nil ); err != nil {
1801+ return ghErrors .NewGitHubGraphQLErrorResponse (ctx , "Failed to create label" , err ), nil
1802+ }
1803+
1804+ out := map [string ]any {
1805+ "id" : fmt .Sprintf ("%v" , mutation .CreateLabel .Label .ID ),
1806+ "name" : string (mutation .CreateLabel .Label .Name ),
1807+ "color" : string (mutation .CreateLabel .Label .Color ),
1808+ "description" : string (mutation .CreateLabel .Label .Description ),
1809+ }
1810+
1811+ r , err := json .Marshal (out )
1812+ if err != nil {
1813+ return nil , fmt .Errorf ("failed to marshal response: %w" , err )
1814+ }
1815+
1816+ return mcp .NewToolResultText (string (r )), nil
1817+ }
1818+ }
1819+
1820+ // Get label
1821+ //func GetLabel(getGQLClient GetGQLClientFn, t translations.TranslationHelperFunc) (mcp.Tool, server.ToolHandlerFunc) {}
1822+ // Update label
1823+ //func UpdateLabel(getGQLClient GetGQLClientFn, t translations.TranslationHelperFunc) (mcp.Tool, server.ToolHandlerFunc) {}
1824+ // Delete label
1825+ //func DeleteLabel(getGQLClient GetGQLClientFn, t translations.TranslationHelperFunc) (mcp.Tool, server.ToolHandlerFunc) {}
1826+
17031827type ReplaceActorsForAssignableInput struct {
17041828 AssignableID githubv4.ID `json:"assignableId"`
17051829 ActorIDs []githubv4.ID `json:"actorIds"`
0 commit comments