@@ -100,6 +100,7 @@ import {
100100 // Discussion Schemas
101101 GitLabDiscussionNoteSchema , // Added
102102 GitLabDiscussionSchema ,
103+ PaginatedDiscussionsResponseSchema ,
103104 UpdateMergeRequestNoteSchema , // Added
104105 CreateMergeRequestNoteSchema , // Added
105106 ListMergeRequestDiscussionsSchema ,
@@ -142,8 +143,10 @@ import {
142143 type PromoteProjectMilestoneOptions ,
143144 type GetMilestoneBurndownEventsOptions ,
144145 // Discussion Types
145- type GitLabDiscussionNote , // Added
146+ type GitLabDiscussionNote ,
146147 type GitLabDiscussion ,
148+ type PaginatedDiscussionsResponse ,
149+ type PaginationOptions ,
147150 type MergeRequestThreadPosition ,
148151 type GetWikiPageOptions ,
149152 type CreateWikiPageOptions ,
@@ -1209,80 +1212,90 @@ async function createMergeRequest(
12091212}
12101213
12111214/**
1212- * List merge request discussion items
1213- * 병합 요청 토론 목록 조회
1215+ * Shared helper function for listing discussions
1216+ * 토론 목록 조회를 위한 공유 헬퍼 함수
12141217 *
12151218 * @param {string } projectId - The ID or URL-encoded path of the project
1216- * @param {number } mergeRequestIid - The IID of a merge request
1217- * @returns {Promise<GitLabDiscussion[]> } List of discussions
1219+ * @param {"issues" | "merge_requests" } resourceType - The type of resource (issues or merge_requests)
1220+ * @param {number } resourceIid - The IID of the issue or merge request
1221+ * @param {PaginationOptions } options - Pagination and sorting options
1222+ * @returns {Promise<PaginatedDiscussionsResponse> } Paginated list of discussions
12181223 */
1219- async function listMergeRequestDiscussions (
1224+ async function listDiscussions (
12201225 projectId : string ,
1221- mergeRequestIid : number
1222- ) : Promise < GitLabDiscussion [ ] > {
1226+ resourceType : "issues" | "merge_requests" ,
1227+ resourceIid : number ,
1228+ options : PaginationOptions = { }
1229+ ) : Promise < PaginatedDiscussionsResponse > {
12231230 projectId = decodeURIComponent ( projectId ) ; // Decode project ID
12241231 const url = new URL (
12251232 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
12261233 projectId
1227- ) } /merge_requests /${ mergeRequestIid } /discussions`
1234+ ) } /${ resourceType } /${ resourceIid } /discussions`
12281235 ) ;
12291236
1237+ // Add query parameters for pagination and sorting
1238+ if ( options . page ) {
1239+ url . searchParams . append ( "page" , options . page . toString ( ) ) ;
1240+ }
1241+ if ( options . per_page ) {
1242+ url . searchParams . append ( "per_page" , options . per_page . toString ( ) ) ;
1243+ }
1244+
12301245 const response = await fetch ( url . toString ( ) , {
12311246 ...DEFAULT_FETCH_CONFIG ,
12321247 } ) ;
12331248
12341249 await handleGitLabError ( response ) ;
1235- const data = await response . json ( ) ;
1236- // Ensure the response is parsed as an array of discussions
1237- return z . array ( GitLabDiscussionSchema ) . parse ( data ) ;
1250+ const discussions = await response . json ( ) ;
1251+
1252+ // Extract pagination headers
1253+ const pagination = {
1254+ x_next_page : response . headers . get ( "x-next-page" ) ? parseInt ( response . headers . get ( "x-next-page" ) ! ) : null ,
1255+ x_page : response . headers . get ( "x-page" ) ? parseInt ( response . headers . get ( "x-page" ) ! ) : undefined ,
1256+ x_per_page : response . headers . get ( "x-per-page" ) ? parseInt ( response . headers . get ( "x-per-page" ) ! ) : undefined ,
1257+ x_prev_page : response . headers . get ( "x-prev-page" ) ? parseInt ( response . headers . get ( "x-prev-page" ) ! ) : null ,
1258+ x_total : response . headers . get ( "x-total" ) ? parseInt ( response . headers . get ( "x-total" ) ! ) : null ,
1259+ x_total_pages : response . headers . get ( "x-total-pages" ) ? parseInt ( response . headers . get ( "x-total-pages" ) ! ) : null ,
1260+ } ;
1261+
1262+ return PaginatedDiscussionsResponseSchema . parse ( {
1263+ items : discussions ,
1264+ pagination : pagination ,
1265+ } ) ;
1266+ }
1267+
1268+ /**
1269+ * List merge request discussion items
1270+ * 병합 요청 토론 목록 조회
1271+ *
1272+ * @param {string } projectId - The ID or URL-encoded path of the project
1273+ * @param {number } mergeRequestIid - The IID of a merge request
1274+ * @param {DiscussionPaginationOptions } options - Pagination and sorting options
1275+ * @returns {Promise<GitLabDiscussion[]> } List of discussions
1276+ */
1277+ async function listMergeRequestDiscussions (
1278+ projectId : string ,
1279+ mergeRequestIid : number ,
1280+ options : PaginationOptions = { }
1281+ ) : Promise < PaginatedDiscussionsResponse > {
1282+ return listDiscussions ( projectId , "merge_requests" , mergeRequestIid , options ) ;
12381283}
12391284
12401285/**
12411286 * List discussions for an issue
12421287 *
12431288 * @param {string } projectId - The ID or URL-encoded path of the project
12441289 * @param {number } issueIid - The internal ID of the project issue
1245- * @param {Object } options - Pagination and sorting options
1290+ * @param {DiscussionPaginationOptions } options - Pagination and sorting options
12461291 * @returns {Promise<GitLabDiscussion[]> } List of issue discussions
12471292 */
12481293async function listIssueDiscussions (
12491294 projectId : string ,
12501295 issueIid : number ,
1251- options : {
1252- page ?: number ;
1253- per_page ?: number ;
1254- sort ?: "asc" | "desc" ;
1255- order_by ?: "created_at" | "updated_at" ;
1256- } = { }
1257- ) : Promise < GitLabDiscussion [ ] > {
1258- projectId = decodeURIComponent ( projectId ) ; // Decode project ID
1259- const url = new URL (
1260- `${ GITLAB_API_URL } /projects/${ encodeURIComponent ( projectId ) } /issues/${ issueIid } /discussions`
1261- ) ;
1262-
1263- // Add query parameters for pagination and sorting
1264- if ( options . page ) {
1265- url . searchParams . append ( "page" , options . page . toString ( ) ) ;
1266- }
1267- if ( options . per_page ) {
1268- url . searchParams . append ( "per_page" , options . per_page . toString ( ) ) ;
1269- }
1270- if ( options . sort ) {
1271- url . searchParams . append ( "sort" , options . sort ) ;
1272- }
1273- if ( options . order_by ) {
1274- url . searchParams . append ( "order_by" , options . order_by ) ;
1275- }
1276-
1277- const response = await fetch ( url . toString ( ) , {
1278- ...DEFAULT_FETCH_CONFIG ,
1279- } ) ;
1280-
1281- await handleGitLabError ( response ) ;
1282- const data = await response . json ( ) ;
1283-
1284- // Parse the response as an array of discussions
1285- return z . array ( GitLabDiscussionSchema ) . parse ( data ) ;
1296+ options : PaginationOptions = { }
1297+ ) : Promise < PaginatedDiscussionsResponse > {
1298+ return listDiscussions ( projectId , "issues" , issueIid , options ) ;
12861299}
12871300
12881301/**
@@ -3284,9 +3297,11 @@ server.setRequestHandler(CallToolRequestSchema, async request => {
32843297
32853298 case "mr_discussions" : {
32863299 const args = ListMergeRequestDiscussionsSchema . parse ( request . params . arguments ) ;
3300+ const { project_id, merge_request_iid, ...options } = args ;
32873301 const discussions = await listMergeRequestDiscussions (
3288- args . project_id ,
3289- args . merge_request_iid
3302+ project_id ,
3303+ merge_request_iid ,
3304+ options
32903305 ) ;
32913306 return {
32923307 content : [ { type : "text" , text : JSON . stringify ( discussions , null , 2 ) } ] ,
0 commit comments