- Notifications
You must be signed in to change notification settings - Fork1.4k
Tommy/expand-list-discussions-tool#690
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Open
tommaso-moro wants to merge19 commits intogithub:mainChoose a base branch fromtommaso-moro:tommy/expand-discussions-tools
base:main
Could not load branches
Branch not found:{{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline, and old review comments may become outdated.
+327 −121
Open
Changes fromall commits
Commits
Show all changes
19 commits Select commitHold shift + click to select a range
687ee8f
added updatedAt and Author (aka User) login to query and payload
tommaso-morodbbf724
added initial support for orderby and direction
tommaso-moro34a413d
sort by created at instead of updated at by default
tommaso-moro5d7230d
remove unused code
tommaso-moroc1afb88
refactor to map to most suitable query based on user inputs at runtime
tommaso-moro7eeb87c
updated readme with new description
tommaso-moro44f8f35
restore original categoryID code, simplify vars management
tommaso-morobcb82c8
quick fix
tommaso-moro751dfa5
update tests to account for recent changes (author login, updated at …
tommaso-morob064f7a
use switch statement for better readability
tommaso-moro6ab5137
remove comment
tommaso-moro25d39be
linting
tommaso-moro14dcf32
refactored logic, simplified switch statement
tommaso-moro49d0dea
linting
tommaso-moroeb78fe9
use original queries from discussions list tool for testing
tommaso-morod499668
linting
tommaso-moroc9a0572
Merge branch 'main' into tommy/expand-discussions-tools
tommaso-morode8583c
remove logging
tommaso-moro2783724
Merge branch 'tommy/expand-discussions-tools' of https://github.com/t…
tommaso-moroFile filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -13,6 +13,81 @@ import ( | ||
"github.com/shurcooL/githubv4" | ||
) | ||
type DiscussionFragment struct { | ||
Number githubv4.Int | ||
Title githubv4.String | ||
CreatedAt githubv4.DateTime | ||
UpdatedAt githubv4.DateTime | ||
Author struct { | ||
Login githubv4.String | ||
} | ||
Category struct { | ||
Name githubv4.String | ||
} `graphql:"category"` | ||
URL githubv4.String `graphql:"url"` | ||
} | ||
type BasicNoOrder struct { | ||
Repository struct { | ||
Discussions struct { | ||
Nodes []DiscussionFragment | ||
} `graphql:"discussions(first: 100)"` | ||
} `graphql:"repository(owner: $owner, name: $repo)"` | ||
} | ||
type BasicWithOrder struct { | ||
Repository struct { | ||
Discussions struct { | ||
Nodes []DiscussionFragment | ||
} `graphql:"discussions(first: 100, orderBy: { field: $orderByField, direction: $orderByDirection })"` | ||
} `graphql:"repository(owner: $owner, name: $repo)"` | ||
} | ||
type WithCategoryAndOrder struct { | ||
Repository struct { | ||
Discussions struct { | ||
Nodes []DiscussionFragment | ||
} `graphql:"discussions(first: 100, categoryId: $categoryId, orderBy: { field: $orderByField, direction: $orderByDirection })"` | ||
} `graphql:"repository(owner: $owner, name: $repo)"` | ||
} | ||
type WithCategoryNoOrder struct { | ||
Repository struct { | ||
Discussions struct { | ||
Nodes []DiscussionFragment | ||
} `graphql:"discussions(first: 100, categoryId: $categoryId)"` | ||
} `graphql:"repository(owner: $owner, name: $repo)"` | ||
} | ||
func fragmentToDiscussion(fragment DiscussionFragment) *github.Discussion { | ||
return &github.Discussion{ | ||
Number: github.Ptr(int(fragment.Number)), | ||
Title: github.Ptr(string(fragment.Title)), | ||
HTMLURL: github.Ptr(string(fragment.URL)), | ||
CreatedAt: &github.Timestamp{Time: fragment.CreatedAt.Time}, | ||
UpdatedAt: &github.Timestamp{Time: fragment.UpdatedAt.Time}, | ||
User: &github.User{ | ||
Login: github.Ptr(string(fragment.Author.Login)), | ||
}, | ||
DiscussionCategory: &github.DiscussionCategory{ | ||
Name: github.Ptr(string(fragment.Category.Name)), | ||
}, | ||
} | ||
} | ||
func getQueryType(useOrdering bool, categoryID *githubv4.ID) any { | ||
if categoryID != nil && useOrdering { | ||
return &WithCategoryAndOrder{} | ||
} | ||
if categoryID != nil && !useOrdering { | ||
return &WithCategoryNoOrder{} | ||
} | ||
if categoryID == nil && useOrdering { | ||
return &BasicWithOrder{} | ||
} | ||
return &BasicNoOrder{} | ||
} | ||
func ListDiscussions(getGQLClient GetGQLClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) { | ||
return mcp.NewTool("list_discussions", | ||
mcp.WithDescription(t("TOOL_LIST_DISCUSSIONS_DESCRIPTION", "List discussions for a repository")), | ||
@@ -31,9 +106,16 @@ func ListDiscussions(getGQLClient GetGQLClientFn, t translations.TranslationHelp | ||
mcp.WithString("category", | ||
mcp.Description("Optional filter by discussion category ID. If provided, only discussions with this category are listed."), | ||
), | ||
mcp.WithString("orderBy", | ||
mcp.Description("Order discussions by field. If provided, the 'direction' also needs to be provided."), | ||
mcp.Enum("CREATED_AT", "UPDATED_AT"), | ||
), | ||
mcp.WithString("direction", | ||
mcp.Description("Order direction."), | ||
mcp.Enum("ASC", "DESC"), | ||
), | ||
), | ||
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { | ||
owner, err := RequiredParam[string](request, "owner") | ||
if err != nil { | ||
return mcp.NewToolResultError(err.Error()), nil | ||
@@ -43,106 +125,80 @@ func ListDiscussions(getGQLClient GetGQLClientFn, t translations.TranslationHelp | ||
return mcp.NewToolResultError(err.Error()), nil | ||
} | ||
category, err := OptionalParam[string](request, "category") | ||
if err != nil { | ||
return mcp.NewToolResultError(err.Error()), nil | ||
} | ||
orderBy, err := OptionalParam[string](request, "orderBy") | ||
if err != nil { | ||
return mcp.NewToolResultError(err.Error()), nil | ||
} | ||
direction, err := OptionalParam[string](request, "direction") | ||
if err != nil { | ||
return mcp.NewToolResultError(err.Error()), nil | ||
} | ||
client, err := getGQLClient(ctx) | ||
if err != nil { | ||
return mcp.NewToolResultError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil | ||
} | ||
var categoryID *githubv4.ID | ||
if category != "" { | ||
id := githubv4.ID(category) | ||
categoryID = &id | ||
} | ||
vars := map[string]interface{}{ | ||
"owner": githubv4.String(owner), | ||
"repo": githubv4.String(repo), | ||
} | ||
// this is an extra check in case the tool description is misinterpreted, because | ||
// we shouldn't use ordering unless both a 'field' and 'direction' are provided | ||
useOrdering := orderBy != "" && direction != "" | ||
if useOrdering { | ||
vars["orderByField"] = githubv4.DiscussionOrderField(orderBy) | ||
vars["orderByDirection"] = githubv4.OrderDirection(direction) | ||
} | ||
if categoryID != nil { | ||
vars["categoryId"] = *categoryID | ||
} | ||
var discussions []*github.Discussion | ||
discussionQuery := getQueryType(useOrdering, categoryID) | ||
if err := client.Query(ctx, discussionQuery, vars); err != nil { | ||
return mcp.NewToolResultError(err.Error()), nil | ||
} | ||
// we need to check what user inputs we received at runtime, and use the | ||
// most appropriate query based on that | ||
switch queryType := discussionQuery.(type) { | ||
tommaso-moro marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
case *WithCategoryAndOrder: | ||
for _, node := range queryType.Repository.Discussions.Nodes { | ||
discussions = append(discussions, fragmentToDiscussion(node)) | ||
} | ||
case *WithCategoryNoOrder: | ||
for _, node := range queryType.Repository.Discussions.Nodes { | ||
discussions = append(discussions, fragmentToDiscussion(node)) | ||
} | ||
case *BasicWithOrder: | ||
for _, node := range queryType.Repository.Discussions.Nodes { | ||
discussions = append(discussions, fragmentToDiscussion(node)) | ||
} | ||
case *BasicNoOrder: | ||
for _, node := range queryType.Repository.Discussions.Nodes { | ||
discussions = append(discussions, fragmentToDiscussion(node)) | ||
} | ||
} | ||
out, err := json.Marshal(discussions) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to marshal discussions: %w", err) | ||
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.