@@ -121,6 +121,8 @@ import {
121121 GetRepositoryTreeSchema ,
122122 type GitLabTreeItem ,
123123 type GetRepositoryTreeOptions ,
124+ UpdateIssueNoteSchema ,
125+ CreateIssueNoteSchema ,
124126} from "./schemas.js" ;
125127
126128/**
@@ -287,6 +289,16 @@ const allTools = [
287289 description : "Add a new note to an existing merge request thread" ,
288290 inputSchema : zodToJsonSchema ( CreateMergeRequestNoteSchema ) ,
289291 } ,
292+ {
293+ name : "update_issue_note" ,
294+ description : "Modify an existing issue thread note" ,
295+ inputSchema : zodToJsonSchema ( UpdateIssueNoteSchema ) ,
296+ } ,
297+ {
298+ name : "create_issue_note" ,
299+ description : "Add a new note to an existing issue thread" ,
300+ inputSchema : zodToJsonSchema ( CreateIssueNoteSchema ) ,
301+ } ,
290302 {
291303 name : "list_issues" ,
292304 description : "List issues in a GitLab project with filtering options" ,
@@ -1126,6 +1138,81 @@ async function updateMergeRequestNote(
11261138 return GitLabDiscussionNoteSchema . parse ( data ) ;
11271139}
11281140
1141+ /**
1142+ * Update an issue discussion note
1143+ * @param {string } projectId - The ID or URL-encoded path of the project
1144+ * @param {number } issueIid - The IID of an issue
1145+ * @param {string } discussionId - The ID of a thread
1146+ * @param {number } noteId - The ID of a thread note
1147+ * @param {string } body - The new content of the note
1148+ * @returns {Promise<GitLabDiscussionNote> } The updated note
1149+ */
1150+ async function updateIssueNote (
1151+ projectId : string ,
1152+ issueIid : number ,
1153+ discussionId : string ,
1154+ noteId : number ,
1155+ body : string
1156+ ) : Promise < GitLabDiscussionNote > {
1157+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
1158+ const url = new URL (
1159+ `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
1160+ projectId
1161+ ) } /issues/${ issueIid } /discussions/${ discussionId } /notes/${ noteId } `
1162+ ) ;
1163+
1164+ const payload = { body } ;
1165+
1166+ const response = await fetch ( url . toString ( ) , {
1167+ ...DEFAULT_FETCH_CONFIG ,
1168+ method : "PUT" ,
1169+ body : JSON . stringify ( payload ) ,
1170+ } ) ;
1171+
1172+ await handleGitLabError ( response ) ;
1173+ const data = await response . json ( ) ;
1174+ return GitLabDiscussionNoteSchema . parse ( data ) ;
1175+ }
1176+
1177+ /**
1178+ * Create a note in an issue discussion
1179+ * @param {string } projectId - The ID or URL-encoded path of the project
1180+ * @param {number } issueIid - The IID of an issue
1181+ * @param {string } discussionId - The ID of a thread
1182+ * @param {string } body - The content of the new note
1183+ * @param {string } [createdAt] - The creation date of the note (ISO 8601 format)
1184+ * @returns {Promise<GitLabDiscussionNote> } The created note
1185+ */
1186+ async function createIssueNote (
1187+ projectId : string ,
1188+ issueIid : number ,
1189+ discussionId : string ,
1190+ body : string ,
1191+ createdAt ?: string
1192+ ) : Promise < GitLabDiscussionNote > {
1193+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
1194+ const url = new URL (
1195+ `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
1196+ projectId
1197+ ) } /issues/${ issueIid } /discussions/${ discussionId } /notes`
1198+ ) ;
1199+
1200+ const payload : { body : string ; created_at ?: string } = { body } ;
1201+ if ( createdAt ) {
1202+ payload . created_at = createdAt ;
1203+ }
1204+
1205+ const response = await fetch ( url . toString ( ) , {
1206+ ...DEFAULT_FETCH_CONFIG ,
1207+ method : "POST" ,
1208+ body : JSON . stringify ( payload ) ,
1209+ } ) ;
1210+
1211+ await handleGitLabError ( response ) ;
1212+ const data = await response . json ( ) ;
1213+ return GitLabDiscussionNoteSchema . parse ( data ) ;
1214+ }
1215+
11291216/**
11301217 * Add a new note to an existing merge request thread
11311218 * 기존 병합 요청 스레드에 새 노트 추가
@@ -2461,6 +2548,38 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
24612548 } ;
24622549 }
24632550
2551+ case "update_issue_note" : {
2552+ const args = UpdateIssueNoteSchema . parse (
2553+ request . params . arguments
2554+ ) ;
2555+ const note = await updateIssueNote (
2556+ args . project_id ,
2557+ args . issue_iid ,
2558+ args . discussion_id ,
2559+ args . note_id ,
2560+ args . body
2561+ ) ;
2562+ return {
2563+ content : [ { type : "text" , text : JSON . stringify ( note , null , 2 ) } ] ,
2564+ } ;
2565+ }
2566+
2567+ case "create_issue_note" : {
2568+ const args = CreateIssueNoteSchema . parse (
2569+ request . params . arguments
2570+ ) ;
2571+ const note = await createIssueNote (
2572+ args . project_id ,
2573+ args . issue_iid ,
2574+ args . discussion_id ,
2575+ args . body ,
2576+ args . created_at
2577+ ) ;
2578+ return {
2579+ content : [ { type : "text" , text : JSON . stringify ( note , null , 2 ) } ] ,
2580+ } ;
2581+ }
2582+
24642583 case "get_merge_request" : {
24652584 const args = GetMergeRequestSchema . parse ( request . params . arguments ) ;
24662585 const mergeRequest = await getMergeRequest (
0 commit comments