@@ -139,6 +139,7 @@ pub(crate) fn call(input: CallToolRequest) -> Result<CallToolResult, Error> {
139
139
// Files
140
140
"gl_get_file_contents" => get_file_contents ( input) ,
141
141
"gl_create_or_update_file" => create_or_update_file ( input) ,
142
+ "gl_delete_file" => delete_file ( input) ,
142
143
143
144
// Branches
144
145
"gl_create_branch" => create_branch ( input) ,
@@ -597,6 +598,97 @@ fn get_file_contents(input: CallToolRequest) -> Result<CallToolResult, Error> {
597
598
}
598
599
}
599
600
601
+ fn delete_file ( input : CallToolRequest ) -> Result < CallToolResult , Error > {
602
+ let args = input. params . arguments . clone ( ) . unwrap_or_default ( ) ;
603
+ let ( token, gitlab_url) = get_gitlab_config ( ) ?;
604
+
605
+ if let (
606
+ Some ( Value :: String ( project_id) ) ,
607
+ Some ( Value :: String ( file_path) ) ,
608
+ Some ( Value :: String ( branch) ) ,
609
+ ) = (
610
+ args. get ( "project_id" ) ,
611
+ args. get ( "file_path" ) ,
612
+ args. get ( "branch" ) ,
613
+ ) {
614
+ let commit_message = args
615
+ . get ( "commit_message" )
616
+ . and_then ( |v| v. as_str ( ) )
617
+ . unwrap_or ( "Delete file via API" )
618
+ . to_string ( ) ;
619
+
620
+ let url = format ! (
621
+ "{}/projects/{}/repository/files/{}" ,
622
+ gitlab_url,
623
+ urlencode_if_needed( project_id) ,
624
+ urlencode_if_needed( file_path)
625
+ ) ;
626
+
627
+ let mut headers = BTreeMap :: new ( ) ;
628
+ headers. insert ( "PRIVATE-TOKEN" . to_string ( ) , token) ;
629
+ headers. insert ( "Content-Type" . to_string ( ) , "application/json" . to_string ( ) ) ;
630
+ headers. insert ( "User-Agent" . to_string ( ) , "hyper-mcp/0.1.0" . to_string ( ) ) ;
631
+
632
+ let mut body_map = serde_json:: Map :: new ( ) ;
633
+ body_map. insert ( "branch" . to_string ( ) , json ! ( branch) ) ;
634
+ body_map. insert ( "commit_message" . to_string ( ) , json ! ( commit_message) ) ;
635
+ if let Some ( Value :: String ( author_email) ) = args. get ( "author_email" ) {
636
+ body_map. insert ( "author_email" . to_string ( ) , json ! ( author_email) ) ;
637
+ }
638
+ if let Some ( Value :: String ( author_name) ) = args. get ( "author_name" ) {
639
+ body_map. insert ( "author_name" . to_string ( ) , json ! ( author_name) ) ;
640
+ }
641
+ let body = Value :: Object ( body_map) ;
642
+
643
+ let req = HttpRequest {
644
+ url,
645
+ headers,
646
+ method : Some ( "DELETE" . to_string ( ) ) ,
647
+ } ;
648
+
649
+ let res = http:: request ( & req, Some ( & body. to_string ( ) ) ) ?;
650
+
651
+ if is_success_status ( res. status_code ( ) ) {
652
+ Ok ( CallToolResult {
653
+ is_error : None ,
654
+ content : vec ! [ Content {
655
+ annotations: None ,
656
+ text: Some ( String :: from_utf8_lossy( & res. body( ) ) . to_string( ) ) ,
657
+ mime_type: Some ( "application/json" . to_string( ) ) ,
658
+ r#type: ContentType :: Text ,
659
+ data: None ,
660
+ } ] ,
661
+ } )
662
+ } else {
663
+ Ok ( CallToolResult {
664
+ is_error : Some ( true ) ,
665
+ content : vec ! [ Content {
666
+ annotations: None ,
667
+ text: Some ( format!(
668
+ "Failed to delete file (status {}): {}" ,
669
+ res. status_code( ) ,
670
+ String :: from_utf8_lossy( & res. body( ) )
671
+ ) ) ,
672
+ mime_type: None ,
673
+ r#type: ContentType :: Text ,
674
+ data: None ,
675
+ } ] ,
676
+ } )
677
+ }
678
+ } else {
679
+ Ok ( CallToolResult {
680
+ is_error : Some ( true ) ,
681
+ content : vec ! [ Content {
682
+ annotations: None ,
683
+ text: Some ( "Please provide project_id, file_path, and branch" . into( ) ) ,
684
+ mime_type: None ,
685
+ r#type: ContentType :: Text ,
686
+ data: None ,
687
+ } ] ,
688
+ } )
689
+ }
690
+ }
691
+
600
692
fn create_or_update_file ( input : CallToolRequest ) -> Result < CallToolResult , Error > {
601
693
let args = input. params . arguments . clone ( ) . unwrap_or_default ( ) ;
602
694
let ( token, gitlab_url) = get_gitlab_config ( ) ?;
@@ -1722,6 +1814,43 @@ fn gl_get_repo_members(input: CallToolRequest) -> Result<CallToolResult, Error>
1722
1814
pub ( crate ) fn describe ( ) -> Result < ListToolsResult , Error > {
1723
1815
Ok ( ListToolsResult {
1724
1816
tools : vec ! [
1817
+ ToolDescription {
1818
+ name: "gl_delete_file" . into( ) ,
1819
+ description: "Delete a file in a GitLab project repository. Requires project_id, file_path, branch, and optional commit_message." . into( ) ,
1820
+ input_schema: json!( {
1821
+ "type" : "object" ,
1822
+ "properties" : {
1823
+ "project_id" : {
1824
+ "type" : "string" ,
1825
+ "description" : "The project identifier - can be a numeric project ID (e.g. '123') or a URL-encoded path (e.g. 'group%2Fproject')" ,
1826
+ } ,
1827
+ "file_path" : {
1828
+ "type" : "string" ,
1829
+ "description" : "The path to the file in the project" ,
1830
+ } ,
1831
+ "branch" : {
1832
+ "type" : "string" ,
1833
+ "description" : "The name of the branch to delete the file from" ,
1834
+ } ,
1835
+ "commit_message" : {
1836
+ "type" : "string" ,
1837
+ "description" : "The commit message. Optional, defaults to 'Delete file via API'" ,
1838
+ } ,
1839
+ "author_email" : {
1840
+ "type" : "string" ,
1841
+ "description" : "The email of the commit author. Optional." ,
1842
+ } ,
1843
+ "author_name" : {
1844
+ "type" : "string" ,
1845
+ "description" : "The name of the commit author. Optional." ,
1846
+ } ,
1847
+ } ,
1848
+ "required" : [ "project_id" , "file_path" , "branch" ] ,
1849
+ } )
1850
+ . as_object( )
1851
+ . unwrap( )
1852
+ . clone( ) ,
1853
+ } ,
1725
1854
ToolDescription {
1726
1855
name: "gl_create_issue" . into( ) ,
1727
1856
description: "Create a new issue in a GitLab project" . into( ) ,
0 commit comments