kodegen_tools_git/tools/
remote_remove.rs1use kodegen_mcp_tool::{Tool, ToolExecutionContext, ToolResponse, error::McpError};
4use kodegen_mcp_schema::git::{GitRemoteRemoveArgs, GitRemoteRemovePromptArgs, GitRemoteRemoveOutput};
5use rmcp::model::{PromptArgument, PromptMessage, PromptMessageContent, PromptMessageRole};
6use std::path::Path;
7
8#[derive(Clone)]
10pub struct GitRemoteRemoveTool;
11
12impl Tool for GitRemoteRemoveTool {
13 type Args = GitRemoteRemoveArgs;
14 type PromptArgs = GitRemoteRemovePromptArgs;
15
16 fn name() -> &'static str {
17 kodegen_mcp_schema::git::GIT_REMOTE_REMOVE
18 }
19
20 fn description() -> &'static str {
21 "Remove a configured remote repository. \
22 Deletes the remote from repository configuration."
23 }
24
25 fn read_only() -> bool {
26 false }
28
29 fn destructive() -> bool {
30 true }
32
33 fn idempotent() -> bool {
34 false }
36
37 async fn execute(&self, args: Self::Args, _ctx: ToolExecutionContext) -> Result<ToolResponse<<Self::Args as kodegen_mcp_tool::ToolArgs>::Output>, McpError> {
38 let path = Path::new(&args.path);
39
40 let repo = crate::open_repo(path)
42 .await
43 .map_err(|e| McpError::Other(anyhow::anyhow!("Task execution failed: {e}")))?
44 .map_err(|e| McpError::Other(anyhow::anyhow!("{e}")))?;
45
46 crate::remove_remote(repo, &args.name)
48 .await
49 .map_err(|e| McpError::Other(anyhow::anyhow!("{e}")))?;
50
51 let summary = format!(
53 "\x1b[32m Remote Removed\x1b[0m\n\
54 {} deleted from configuration",
55 args.name
56 );
57
58 Ok(ToolResponse::new(summary, GitRemoteRemoveOutput {
59 success: true,
60 name: args.name.clone(),
61 message: format!("Remote '{}' removed", args.name),
62 }))
63 }
64
65 fn prompt_arguments() -> Vec<PromptArgument> {
66 vec![]
67 }
68
69 async fn prompt(&self, _args: Self::PromptArgs) -> Result<Vec<PromptMessage>, McpError> {
70 Ok(vec![
71 PromptMessage {
72 role: PromptMessageRole::User,
73 content: PromptMessageContent::text("How do I remove a Git remote?"),
74 },
75 PromptMessage {
76 role: PromptMessageRole::Assistant,
77 content: PromptMessageContent::text(
78 "The git_remote_remove tool deletes a configured remote from your Git \
79 repository. This is useful for:\n\n\
80 1. **Fork workflows**: After merging PR branches and finishing contribution, \
81 remove the upstream or fork remote\n\n\
82 2. **Cleanup**: Remove stale, incorrect, or abandoned remote references\n\n\
83 3. **Migration**: Reorganizing remotes when moving repositories or changing \
84 Git hosting\n\n\
85 4. **Multiple remotes**: Cleaning up when you have too many remotes configured\n\n\
86 USAGE: git_remote_remove({\"path\": \"/path/to/repo\", \"name\": \"origin\"})\n\n\
87 PARAMETERS:\n\
88 - path: Path to the Git repository (required)\n\
89 - name: Name of the remote to remove, e.g., \"origin\", \"upstream\", \
90 \"fork\" (required)\n\n\
91 COMMON SCENARIOS:\n\n\
92 **Scenario 1: Remove upstream after fork contribution**\n\
93 Workflow: Clone fork -> add upstream -> fetch -> merge -> remove upstream\n\
94 git_remote_remove({\"path\": \".\", \"name\": \"upstream\"})\n\n\
95 **Scenario 2: Remove fork origin and switch to main repo**\n\
96 After contributing to a project, use the main repository:\n\
97 git_remote_remove({\"path\": \".\", \"name\": \"origin\"})\n\
98 Then add the main repo as origin\n\n\
99 **Scenario 3: Cleanup multiple test remotes**\n\
100 First, list remotes: git_remote_list({\"path\": \".\"})\n\
101 Then remove unwanted ones:\n\
102 git_remote_remove({\"path\": \".\", \"name\": \"test-remote\"})\n\n\
103 IMPORTANT WARNINGS:\n\n\
104 DESTRUCTIVE: This operation deletes the remote configuration entry. \
105 You cannot undo this without manually re-adding the remote.\n\n\
106 NON-IDEMPOTENT: Attempting to remove a remote that doesn't exist will \
107 fail. Always verify the remote exists before removing.\n\n\
108 CONNECTIVITY: Removing a remote doesn't affect branches that were created \
109 from that remote. Those branches remain in your repository.\n\n\
110 BEST PRACTICES:\n\n\
111 1. **Always verify first**: Use git_remote_list to see all configured \
112 remotes before removing\n\
113 2. **Understand the context**: Know why the remote was added and what it's \
114 used for\n\
115 3. **Document locally**: If removing a shared remote, ensure team knows about \
116 the change\n\
117 4. **Consider force sync**: After removing, use git_fetch to update your \
118 repository state\n\n\
119 ERROR CASES:\n\
120 - Remote not found: \"error: Could not remove config section 'remote.xxx'\" \
121 -> Check spelling with git_remote_list\n\
122 - Permission denied: Check directory permissions on .git/config\n\
123 - Not in repo: Run from repository root or provide correct path\n\n\
124 RECOVERY:\n\
125 If you accidentally remove a remote, re-add it with the original URL \
126 using git_remote_add.",
127 ),
128 },
129 ])
130 }
131}