diff --git a/README.md b/README.md index 0bb054355..68742752f 100644 --- a/README.md +++ b/README.md @@ -478,15 +478,15 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description - **list_workflow_jobs** - List workflow jobs - `filter`: Filters jobs by their completed_at timestamp (string, optional) - `owner`: Repository owner (string, required) - - `page`: The page number of the results to fetch (number, optional) - - `per_page`: The number of results per page (max 100) (number, optional) + - `page`: Page number for pagination (min 1) (number, optional) + - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - `repo`: Repository name (string, required) - `run_id`: The unique identifier of the workflow run (number, required) - **list_workflow_run_artifacts** - List workflow artifacts - `owner`: Repository owner (string, required) - - `page`: The page number of the results to fetch (number, optional) - - `per_page`: The number of results per page (max 100) (number, optional) + - `page`: Page number for pagination (min 1) (number, optional) + - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - `repo`: Repository name (string, required) - `run_id`: The unique identifier of the workflow run (number, required) @@ -495,16 +495,16 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description - `branch`: Returns workflow runs associated with a branch. Use the name of the branch. (string, optional) - `event`: Returns workflow runs for a specific event type (string, optional) - `owner`: Repository owner (string, required) - - `page`: The page number of the results to fetch (number, optional) - - `per_page`: The number of results per page (max 100) (number, optional) + - `page`: Page number for pagination (min 1) (number, optional) + - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - `repo`: Repository name (string, required) - `status`: Returns workflow runs with the check run status (string, optional) - `workflow_id`: The workflow ID or workflow file name (string, required) - **list_workflows** - List workflows - `owner`: Repository owner (string, required) - - `page`: The page number of the results to fetch (number, optional) - - `per_page`: The number of results per page (max 100) (number, optional) + - `page`: Page number for pagination (min 1) (number, optional) + - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - `repo`: Repository name (string, required) - **rerun_failed_jobs** - Rerun failed jobs @@ -632,8 +632,8 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description - **get_issue_comments** - Get issue comments - `issue_number`: Issue number (number, required) - `owner`: Repository owner (string, required) - - `page`: Page number (number, optional) - - `per_page`: Number of records per page (number, optional) + - `page`: Page number for pagination (min 1) (number, optional) + - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - `repo`: Repository name (string, required) - **list_issues** - List issues diff --git a/pkg/github/__toolsnaps__/get_issue_comments.snap b/pkg/github/__toolsnaps__/get_issue_comments.snap index fa1fb0d6c..b28f45204 100644 --- a/pkg/github/__toolsnaps__/get_issue_comments.snap +++ b/pkg/github/__toolsnaps__/get_issue_comments.snap @@ -15,11 +15,14 @@ "type": "string" }, "page": { - "description": "Page number", + "description": "Page number for pagination (min 1)", + "minimum": 1, "type": "number" }, - "per_page": { - "description": "Number of records per page", + "perPage": { + "description": "Results per page for pagination (min 1, max 100)", + "maximum": 100, + "minimum": 1, "type": "number" }, "repo": { diff --git a/pkg/github/actions.go b/pkg/github/actions.go index 8c7b08a85..95b1ec7ba 100644 --- a/pkg/github/actions.go +++ b/pkg/github/actions.go @@ -37,12 +37,7 @@ func ListWorkflows(getClient GetClientFn, t translations.TranslationHelperFunc) mcp.Required(), mcp.Description(DescriptionRepositoryName), ), - mcp.WithNumber("per_page", - mcp.Description("The number of results per page (max 100)"), - ), - mcp.WithNumber("page", - mcp.Description("The page number of the results to fetch"), - ), + WithPagination(), ), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { owner, err := RequiredParam[string](request, "owner") @@ -55,11 +50,7 @@ func ListWorkflows(getClient GetClientFn, t translations.TranslationHelperFunc) } // Get optional pagination parameters - perPage, err := OptionalIntParam(request, "per_page") - if err != nil { - return mcp.NewToolResultError(err.Error()), nil - } - page, err := OptionalIntParam(request, "page") + pagination, err := OptionalPaginationParams(request) if err != nil { return mcp.NewToolResultError(err.Error()), nil } @@ -71,8 +62,8 @@ func ListWorkflows(getClient GetClientFn, t translations.TranslationHelperFunc) // Set up list options opts := &github.ListOptions{ - PerPage: perPage, - Page: page, + PerPage: pagination.perPage, + Page: pagination.page, } workflows, resp, err := client.Actions.ListWorkflows(ctx, owner, repo, opts) @@ -157,12 +148,7 @@ func ListWorkflowRuns(getClient GetClientFn, t translations.TranslationHelperFun mcp.Description("Returns workflow runs with the check run status"), mcp.Enum("queued", "in_progress", "completed", "requested", "waiting"), ), - mcp.WithNumber("per_page", - mcp.Description("The number of results per page (max 100)"), - ), - mcp.WithNumber("page", - mcp.Description("The page number of the results to fetch"), - ), + WithPagination(), ), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { owner, err := RequiredParam[string](request, "owner") @@ -197,11 +183,7 @@ func ListWorkflowRuns(getClient GetClientFn, t translations.TranslationHelperFun } // Get optional pagination parameters - perPage, err := OptionalIntParam(request, "per_page") - if err != nil { - return mcp.NewToolResultError(err.Error()), nil - } - page, err := OptionalIntParam(request, "page") + pagination, err := OptionalPaginationParams(request) if err != nil { return mcp.NewToolResultError(err.Error()), nil } @@ -218,8 +200,8 @@ func ListWorkflowRuns(getClient GetClientFn, t translations.TranslationHelperFun Event: event, Status: status, ListOptions: github.ListOptions{ - PerPage: perPage, - Page: page, + PerPage: pagination.perPage, + Page: pagination.page, }, } @@ -483,12 +465,7 @@ func ListWorkflowJobs(getClient GetClientFn, t translations.TranslationHelperFun mcp.Description("Filters jobs by their completed_at timestamp"), mcp.Enum("latest", "all"), ), - mcp.WithNumber("per_page", - mcp.Description("The number of results per page (max 100)"), - ), - mcp.WithNumber("page", - mcp.Description("The page number of the results to fetch"), - ), + WithPagination(), ), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { owner, err := RequiredParam[string](request, "owner") @@ -512,11 +489,7 @@ func ListWorkflowJobs(getClient GetClientFn, t translations.TranslationHelperFun } // Get optional pagination parameters - perPage, err := OptionalIntParam(request, "per_page") - if err != nil { - return mcp.NewToolResultError(err.Error()), nil - } - page, err := OptionalIntParam(request, "page") + pagination, err := OptionalPaginationParams(request) if err != nil { return mcp.NewToolResultError(err.Error()), nil } @@ -530,8 +503,8 @@ func ListWorkflowJobs(getClient GetClientFn, t translations.TranslationHelperFun opts := &github.ListWorkflowJobsOptions{ Filter: filter, ListOptions: github.ListOptions{ - PerPage: perPage, - Page: page, + PerPage: pagination.perPage, + Page: pagination.page, }, } @@ -1022,12 +995,7 @@ func ListWorkflowRunArtifacts(getClient GetClientFn, t translations.TranslationH mcp.Required(), mcp.Description("The unique identifier of the workflow run"), ), - mcp.WithNumber("per_page", - mcp.Description("The number of results per page (max 100)"), - ), - mcp.WithNumber("page", - mcp.Description("The page number of the results to fetch"), - ), + WithPagination(), ), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { owner, err := RequiredParam[string](request, "owner") @@ -1045,11 +1013,7 @@ func ListWorkflowRunArtifacts(getClient GetClientFn, t translations.TranslationH runID := int64(runIDInt) // Get optional pagination parameters - perPage, err := OptionalIntParam(request, "per_page") - if err != nil { - return mcp.NewToolResultError(err.Error()), nil - } - page, err := OptionalIntParam(request, "page") + pagination, err := OptionalPaginationParams(request) if err != nil { return mcp.NewToolResultError(err.Error()), nil } @@ -1061,8 +1025,8 @@ func ListWorkflowRunArtifacts(getClient GetClientFn, t translations.TranslationH // Set up list options opts := &github.ListOptions{ - PerPage: perPage, - Page: page, + PerPage: pagination.perPage, + Page: pagination.page, } artifacts, resp, err := client.Actions.ListWorkflowRunArtifacts(ctx, owner, repo, runID, opts) diff --git a/pkg/github/actions_test.go b/pkg/github/actions_test.go index 1b904b9b1..f885ec5b9 100644 --- a/pkg/github/actions_test.go +++ b/pkg/github/actions_test.go @@ -23,7 +23,7 @@ func Test_ListWorkflows(t *testing.T) { assert.NotEmpty(t, tool.Description) assert.Contains(t, tool.InputSchema.Properties, "owner") assert.Contains(t, tool.InputSchema.Properties, "repo") - assert.Contains(t, tool.InputSchema.Properties, "per_page") + assert.Contains(t, tool.InputSchema.Properties, "perPage") assert.Contains(t, tool.InputSchema.Properties, "page") assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo"}) @@ -393,7 +393,7 @@ func Test_ListWorkflowRunArtifacts(t *testing.T) { assert.Contains(t, tool.InputSchema.Properties, "owner") assert.Contains(t, tool.InputSchema.Properties, "repo") assert.Contains(t, tool.InputSchema.Properties, "run_id") - assert.Contains(t, tool.InputSchema.Properties, "per_page") + assert.Contains(t, tool.InputSchema.Properties, "perPage") assert.Contains(t, tool.InputSchema.Properties, "page") assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "run_id"}) diff --git a/pkg/github/issues.go b/pkg/github/issues.go index 6121786d2..9d51aeb50 100644 --- a/pkg/github/issues.go +++ b/pkg/github/issues.go @@ -608,12 +608,7 @@ func GetIssueComments(getClient GetClientFn, t translations.TranslationHelperFun mcp.Required(), mcp.Description("Issue number"), ), - mcp.WithNumber("page", - mcp.Description("Page number"), - ), - mcp.WithNumber("per_page", - mcp.Description("Number of records per page"), - ), + WithPagination(), ), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { owner, err := RequiredParam[string](request, "owner") @@ -628,19 +623,15 @@ func GetIssueComments(getClient GetClientFn, t translations.TranslationHelperFun if err != nil { return mcp.NewToolResultError(err.Error()), nil } - page, err := OptionalIntParamWithDefault(request, "page", 1) - if err != nil { - return mcp.NewToolResultError(err.Error()), nil - } - perPage, err := OptionalIntParamWithDefault(request, "per_page", 30) + pagination, err := OptionalPaginationParams(request) if err != nil { return mcp.NewToolResultError(err.Error()), nil } opts := &github.IssueListCommentsOptions{ ListOptions: github.ListOptions{ - Page: page, - PerPage: perPage, + Page: pagination.page, + PerPage: pagination.perPage, }, } diff --git a/pkg/github/issues_test.go b/pkg/github/issues_test.go index 056fa7ed8..a6facbe2f 100644 --- a/pkg/github/issues_test.go +++ b/pkg/github/issues_test.go @@ -1087,7 +1087,7 @@ func Test_GetIssueComments(t *testing.T) { assert.Contains(t, tool.InputSchema.Properties, "repo") assert.Contains(t, tool.InputSchema.Properties, "issue_number") assert.Contains(t, tool.InputSchema.Properties, "page") - assert.Contains(t, tool.InputSchema.Properties, "per_page") + assert.Contains(t, tool.InputSchema.Properties, "perPage") assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "issue_number"}) // Setup mock comments for success case @@ -1152,7 +1152,7 @@ func Test_GetIssueComments(t *testing.T) { "repo": "repo", "issue_number": float64(42), "page": float64(2), - "per_page": float64(10), + "perPage": float64(10), }, expectError: false, expectedComments: mockComments,