@@ -395,7 +395,8 @@ const allTools = [
395395 } ,
396396 {
397397 name : "get_repository_tree" ,
398- description : "Get the repository tree for a GitLab project (list files and directories)" ,
398+ description :
399+ "Get the repository tree for a GitLab project (list files and directories)" ,
399400 inputSchema : zodToJsonSchema ( GetRepositoryTreeSchema ) ,
400401 } ,
401402] ;
@@ -506,6 +507,7 @@ async function forkProject(
506507 projectId : string ,
507508 namespace ? : string
508509) : Promise < GitLabFork > {
510+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
509511 const url = new URL (
510512 `${ GITLAB_API_URL } /projects/${ encodeURIComponent ( projectId ) } /fork`
511513 ) ;
@@ -541,6 +543,7 @@ async function createBranch(
541543 projectId : string ,
542544 options : z . infer < typeof CreateBranchOptionsSchema >
543545) : Promise < GitLabReference > {
546+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
544547 const url = new URL (
545548 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
546549 projectId
@@ -568,6 +571,7 @@ async function createBranch(
568571 * @returns {Promise<string> } The name of the default branch
569572 */
570573async function getDefaultBranchRef ( projectId : string ) : Promise < string > {
574+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
571575 const url = new URL (
572576 `${ GITLAB_API_URL } /projects/${ encodeURIComponent ( projectId ) } `
573577 ) ;
@@ -595,6 +599,7 @@ async function getFileContents(
595599 filePath : string ,
596600 ref ? : string
597601) : Promise < GitLabContent > {
602+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
598603 const encodedPath = encodeURIComponent ( filePath ) ;
599604
600605 // ref가 없는 경우 default branch를 가져옴
@@ -646,6 +651,7 @@ async function createIssue(
646651 projectId : string ,
647652 options : z . infer < typeof CreateIssueOptionsSchema >
648653) : Promise < GitLabIssue > {
654+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
649655 const url = new URL (
650656 `${ GITLAB_API_URL } /projects/${ encodeURIComponent ( projectId ) } /issues`
651657 ) ;
@@ -685,6 +691,7 @@ async function listIssues(
685691 projectId : string ,
686692 options : Omit < z . infer < typeof ListIssuesSchema > , "project_id" > = { }
687693) : Promise < GitLabIssue [ ] > {
694+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
688695 const url = new URL (
689696 `${ GITLAB_API_URL } /projects/${ encodeURIComponent ( projectId ) } /issues`
690697 ) ;
@@ -722,6 +729,7 @@ async function getIssue(
722729 projectId : string ,
723730 issueIid : number
724731) : Promise < GitLabIssue > {
732+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
725733 const url = new URL (
726734 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
727735 projectId
@@ -751,6 +759,7 @@ async function updateIssue(
751759 issueIid : number ,
752760 options : Omit < z . infer < typeof UpdateIssueSchema > , "project_id" | "issue_iid" >
753761) : Promise < GitLabIssue > {
762+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
754763 const url = new URL (
755764 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
756765 projectId
@@ -783,6 +792,7 @@ async function updateIssue(
783792 * @returns {Promise<void> }
784793 */
785794async function deleteIssue ( projectId : string , issueIid : number ) : Promise < void > {
795+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
786796 const url = new URL (
787797 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
788798 projectId
@@ -809,6 +819,7 @@ async function listIssueLinks(
809819 projectId : string ,
810820 issueIid : number
811821) : Promise < GitLabIssueWithLinkDetails [ ] > {
822+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
812823 const url = new URL (
813824 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
814825 projectId
@@ -838,6 +849,7 @@ async function getIssueLink(
838849 issueIid : number ,
839850 issueLinkId : number
840851) : Promise < GitLabIssueLink > {
852+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
841853 const url = new URL (
842854 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
843855 projectId
@@ -871,6 +883,8 @@ async function createIssueLink(
871883 targetIssueIid : number ,
872884 linkType : "relates_to " | "blocks " | "is_blocked_by " = "relates_to"
873885) : Promise < GitLabIssueLink > {
886+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
887+ targetProjectId = decodeURIComponent ( targetProjectId ) ; // Decode target project ID as well
874888 const url = new URL (
875889 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
876890 projectId
@@ -906,6 +920,7 @@ async function deleteIssueLink(
906920 issueIid : number ,
907921 issueLinkId : number
908922) : Promise < void > {
923+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
909924 const url = new URL (
910925 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
911926 projectId
@@ -932,6 +947,7 @@ async function createMergeRequest(
932947 projectId : string ,
933948 options : z . infer < typeof CreateMergeRequestOptionsSchema >
934949) : Promise < GitLabMergeRequest > {
950+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
935951 const url = new URL (
936952 `${ GITLAB_API_URL } /projects/${ encodeURIComponent ( projectId ) } /merge_requests`
937953 ) ;
@@ -977,6 +993,7 @@ async function listMergeRequestDiscussions(
977993 projectId : string ,
978994 mergeRequestIid : number
979995) : Promise < GitLabDiscussion [ ] > {
996+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
980997 const url = new URL (
981998 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
982999 projectId
@@ -1013,6 +1030,7 @@ async function updateMergeRequestNote(
10131030 body : string ,
10141031 resolved ?: boolean
10151032) : Promise < GitLabDiscussionNote > {
1033+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
10161034 const url = new URL (
10171035 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
10181036 projectId
@@ -1057,6 +1075,7 @@ async function createOrUpdateFile(
10571075 last_commit_id ? : string ,
10581076 commit_id ? : string
10591077) : Promise < GitLabCreateUpdateFileResponse > {
1078+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
10601079 const encodedPath = encodeURIComponent ( filePath ) ;
10611080 const url = new URL (
10621081 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
@@ -1139,6 +1158,7 @@ async function createTree(
11391158 files : FileOperation [ ] ,
11401159 ref ? : string
11411160) : Promise < GitLabTree > {
1161+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
11421162 const url = new URL (
11431163 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
11441164 projectId
@@ -1193,6 +1213,7 @@ async function createCommit(
11931213 branch : string ,
11941214 actions : FileOperation [ ]
11951215) : Promise < GitLabCommit > {
1216+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
11961217 const url = new URL (
11971218 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
11981219 projectId
@@ -1325,6 +1346,7 @@ async function getMergeRequest(
13251346 mergeRequestIid ?: number ,
13261347 branchName ?: string
13271348) : Promise < GitLabMergeRequest > {
1349+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
13281350 let url : URL ;
13291351
13301352 if ( mergeRequestIid ) {
@@ -1375,6 +1397,7 @@ async function getMergeRequestDiffs(
13751397 branchName ?: string ,
13761398 view ?: "inline" | "parallel"
13771399) : Promise < GitLabMergeRequestDiff [ ] > {
1400+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
13781401 if ( ! mergeRequestIid && ! branchName ) {
13791402 throw new Error ( "Either mergeRequestIid or branchName must be provided" ) ;
13801403 }
@@ -1426,6 +1449,7 @@ async function updateMergeRequest(
14261449 mergeRequestIid ?: number ,
14271450 branchName ?: string
14281451) : Promise < GitLabMergeRequest > {
1452+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
14291453 if ( ! mergeRequestIid && ! branchName ) {
14301454 throw new Error ( "Either mergeRequestIid or branchName must be provided" ) ;
14311455 }
@@ -1472,6 +1496,7 @@ async function createNote(
14721496 noteableIid : number ,
14731497 body : string
14741498) : Promise < any > {
1499+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
14751500 // ⚙️ 응답 타입은 GitLab API 문서에 따라 조정 가능
14761501 const url = new URL (
14771502 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
@@ -1600,6 +1625,7 @@ async function getProject(
16001625 with_custom_attributes ?: boolean ;
16011626 } = { }
16021627) : Promise < GitLabProject > {
1628+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
16031629 const url = new URL (
16041630 `${ GITLAB_API_URL } /projects/${ encodeURIComponent ( projectId ) } `
16051631 ) ;
@@ -1674,6 +1700,7 @@ async function listLabels(
16741700 projectId : string ,
16751701 options : Omit < z . infer < typeof ListLabelsSchema > , "project_id "> = { }
16761702) : Promise < GitLabLabel [ ] > {
1703+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
16771704 // Construct the URL with project path
16781705 const url = new URL (
16791706 `${ GITLAB_API_URL } /projects/${ encodeURIComponent ( projectId ) } /labels`
@@ -1716,6 +1743,7 @@ async function getLabel(
17161743 labelId : number | string ,
17171744 includeAncestorGroups ?: boolean
17181745) : Promise < GitLabLabel > {
1746+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
17191747 const url = new URL (
17201748 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
17211749 projectId
@@ -1754,6 +1782,7 @@ async function createLabel(
17541782 projectId : string ,
17551783 options : Omit < z . infer < typeof CreateLabelSchema > , "project_id" >
17561784) : Promise < GitLabLabel > {
1785+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
17571786 // Make the API request
17581787 const response = await fetch (
17591788 `${ GITLAB_API_URL } /projects/${ encodeURIComponent ( projectId ) } /labels` ,
@@ -1785,6 +1814,7 @@ async function updateLabel(
17851814 labelId : number | string ,
17861815 options : Omit < z . infer < typeof UpdateLabelSchema > , "project_id " | "label_id ">
17871816) : Promise < GitLabLabel > {
1817+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
17881818 // Make the API request
17891819 const response = await fetch (
17901820 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
@@ -1815,6 +1845,7 @@ async function deleteLabel(
18151845 projectId : string ,
18161846 labelId : number | string
18171847) : Promise < void > {
1848+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
18181849 // Make the API request
18191850 const response = await fetch (
18201851 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
@@ -1908,6 +1939,7 @@ async function listWikiPages(
19081939 projectId : string ,
19091940 options : Omit < z . infer < typeof ListWikiPagesSchema > , "project_id "> = { }
19101941) : Promise < GitLabWikiPage [ ] > {
1942+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
19111943 const url = new URL (
19121944 `${ GITLAB_API_URL } /projects/${ encodeURIComponent ( projectId ) } /wikis`
19131945 ) ;
@@ -1929,6 +1961,7 @@ async function getWikiPage(
19291961 projectId : string ,
19301962 slug : string
19311963) : Promise < GitLabWikiPage > {
1964+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
19321965 const response = await fetch (
19331966 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
19341967 projectId
@@ -1949,6 +1982,7 @@ async function createWikiPage(
19491982 content : string ,
19501983 format ?: string
19511984) : Promise < GitLabWikiPage > {
1985+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
19521986 const body : Record < string , any> = { title, content } ;
19531987 if ( format ) body . format = format ;
19541988 const response = await fetch (
@@ -1974,6 +2008,7 @@ async function updateWikiPage(
19742008 content ?: string ,
19752009 format ?: string
19762010) : Promise < GitLabWikiPage > {
2011+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
19772012 const body : Record < string , any > = { } ;
19782013 if ( title ) body . title = title ;
19792014 if ( content ) body . content = content ;
@@ -1997,6 +2032,7 @@ async function updateWikiPage(
19972032 * Delete a wiki page
19982033 */
19992034async function deleteWikiPage ( projectId : string , slug : string ) : Promise < void > {
2035+ projectId = decodeURIComponent ( projectId ) ; // Decode project ID
20002036 const response = await fetch (
20012037 `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
20022038 projectId
@@ -2018,16 +2054,20 @@ async function deleteWikiPage(projectId: string, slug: string): Promise<void> {
20182054async function getRepositoryTree (
20192055 options : GetRepositoryTreeOptions
20202056) : Promise < GitLabTreeItem [ ] > {
2057+ options. project_id = decodeURIComponent ( options . project_id ) ; // Decode project_id within options
20212058 const queryParams = new URLSearchParams ( ) ;
20222059 if ( options . path ) queryParams . append ( "path" , options . path ) ;
20232060 if ( options . ref ) queryParams . append ( "ref" , options . ref ) ;
20242061 if ( options . recursive ) queryParams . append ( "recursive" , "true" ) ;
2025- if ( options . per_page ) queryParams . append ( "per_page" , options . per_page . toString ( ) ) ;
2062+ if ( options . per_page )
2063+ queryParams . append ( "per_page" , options . per_page . toString ( ) ) ;
20262064 if ( options . page_token ) queryParams . append ( "page_token" , options . page_token ) ;
20272065 if ( options . pagination ) queryParams . append ( "pagination" , options . pagination ) ;
20282066
20292067 const response = await fetch (
2030- `${ GITLAB_API_URL } /projects/${ encodeURIComponent ( options . project_id ) } /repository/tree?${ queryParams . toString ( ) } ` ,
2068+ `${ GITLAB_API_URL } /projects/${ encodeURIComponent (
2069+ options . project_id
2070+ ) } /repository/tree?${ queryParams . toString ( ) } `,
20312071 {
20322072 headers : {
20332073 Authorization : `Bearer ${ GITLAB_PERSONAL_ACCESS_TOKEN } ` ,
@@ -2054,12 +2094,33 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
20542094 ? allTools . filter ( ( tool ) => readOnlyTools . includes ( tool . name ) )
20552095 : allTools ;
20562096 // Toggle wiki tools by USE_GITLAB_WIKI flag
2057- const tools = USE_GITLAB_WIKI
2097+ let tools = USE_GITLAB_WIKI
20582098 ? tools0
20592099 : tools0 . filter ( ( tool ) => ! wikiToolNames . includes ( tool . name ) ) ;
20602100
2101+ // <<< START: Gemini 호환성을 위해 $schema 제거 >>>
2102+ tools = tools . map ( ( tool ) => {
2103+ // inputSchema가 존재하고 객체인지 확인
2104+ if (
2105+ tool . inputSchema &&
2106+ typeof tool . inputSchema === "object" &&
2107+ tool . inputSchema !== null
2108+ ) {
2109+ // $schema 키가 존재하면 삭제
2110+ if ( "$schema" in tool . inputSchema ) {
2111+ // 불변성을 위해 새로운 객체 생성 (선택적이지만 권장)
2112+ const modifiedSchema = { ...tool . inputSchema } ;
2113+ delete modifiedSchema . $schema ;
2114+ return { ...tool , inputSchema : modifiedSchema } ;
2115+ }
2116+ }
2117+ // 변경이 필요 없으면 그대로 반환
2118+ return tool ;
2119+ } ) ;
2120+ // <<< END: Gemini 호환성을 위해 $schema 제거 >>>
2121+
20612122 return {
2062- tools,
2123+ tools, // $schema가 제거된 도구 목록 반환
20632124 } ;
20642125} ) ;
20652126
0 commit comments