Skip to content

Commit 0d0d7b2

Browse files
committed
poc gql tool create label
1 parent 2a0c7bf commit 0d0d7b2

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

pkg/github/issues.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
17031827
type ReplaceActorsForAssignableInput struct {
17041828
AssignableID githubv4.ID `json:"assignableId"`
17051829
ActorIDs []githubv4.ID `json:"actorIds"`

pkg/github/tools.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG
7070
toolsets.NewServerTool(AddSubIssue(getClient, t)),
7171
toolsets.NewServerTool(RemoveSubIssue(getClient, t)),
7272
toolsets.NewServerTool(ReprioritizeSubIssue(getClient, t)),
73+
toolsets.NewServerTool(CreateLabel(getGQLClient, t)),
7374
).AddPrompts(
7475
toolsets.NewServerPrompt(AssignCodingAgentPrompt(t)),
7576
toolsets.NewServerPrompt(IssueToFixWorkflowPrompt(t)),

0 commit comments

Comments
 (0)