use anyhow::{Context, Result};
use inquire::{Confirm, Select, Text};
use std::fs;
use std::path::{Path, PathBuf};
use crate::cli_format::print_client_snippets;
pub fn run_wizard(output_path: &Path) -> Result<PathBuf> {
println!("\n================================================================================");
println!(" Welcome to fs-mcp-rs Interactive Setup Wizard ");
println!("================================================================================");
println!("This wizard will generate a customized `config.toml` for your MCP server.\n");
let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
let default_root = current_dir.to_string_lossy().to_string();
let root_path_str = Text::new("Root Directory to expose over MCP:")
.with_default(&default_root)
.with_help_message("Allowed directory path. Relative or absolute.")
.prompt()
.context("Wizard cancelled")?;
let root_path = PathBuf::from(root_path_str.trim());
let read_only_options = vec![
"Read-Write Mode (Allow creating, editing, and removing files)",
"Read-Only Mode (Safe mode - disable all file mutations)",
];
let selected_mode = Select::new("Select Filesystem Access Mode:", read_only_options)
.prompt()
.context("Wizard cancelled")?;
let read_only = selected_mode.starts_with("Read-Only");
let terminal_options = vec![
"Disabled (Safe - terminal execution tools unavailable)",
"Enabled (Warning: allows AI clients to run shell commands)",
];
let selected_terminal =
Select::new("Select Terminal Command Execution Mode:", terminal_options)
.prompt()
.context("Wizard cancelled")?;
let terminal_enabled = selected_terminal.starts_with("Enabled");
let log_options = vec![
"Enabled (Concise [OK]/[WARN] log lines for every tool call)",
"Disabled (Quiet mode - no tool call logs)",
];
let selected_log = Select::new("Select Tool Call Logging Mode:", log_options)
.prompt()
.context("Wizard cancelled")?;
let log_tools = selected_log.starts_with("Enabled");
let host_str = Text::new("Server Host IP:")
.with_default("127.0.0.1")
.prompt()
.context("Wizard cancelled")?;
let port_str = Text::new("Server Port:")
.with_default("8000")
.prompt()
.context("Wizard cancelled")?;
let port: u16 = port_str.trim().parse().unwrap_or(8000);
let output_str = Text::new("Save Configuration File to:")
.with_default(&output_path.to_string_lossy())
.prompt()
.context("Wizard cancelled")?;
let final_output_path = PathBuf::from(output_str.trim());
let root_formatted = root_path.to_string_lossy().replace('\\', "/");
let config_content = format!(
r#"# Generated by fs-mcp-rs interactive wizard
# Config file for fs-mcp-rs Model Context Protocol server
[server]
host = "{host}"
port = {port}
max_concurrency = 32
max_io_concurrency = 16
log_tools = {log_tools}
[filesystem]
roots = ["{root}"]
read_only = {read_only}
max_read_bytes = 8388608
max_write_bytes = 8388608
follow_links = false
tree_max_depth = 8
tree_max_entries = 1000
tree_max_warnings = 32
patch_max_bytes = 1048576
patch_preview_bytes = 16384
[search]
max_results = 1000
max_concurrency = 4
worker_threads = 4
regex_cache_capacity = 64
include_hidden = false
respect_gitignore = true
[terminal]
enabled = {terminal_enabled}
max_concurrency = 2
default_timeout_ms = 30000
max_timeout_ms = 300000
max_output_bytes = 4194304
max_read_bytes = 262144
max_wait_ms = 30000
session_retention_ms = 300000
[oauth]
enabled = true
require_auth = false
"#,
host = host_str.trim(),
port = port,
log_tools = log_tools,
root = root_formatted,
read_only = read_only,
terminal_enabled = terminal_enabled
);
if let Some(parent) = final_output_path.parent() {
if !parent.as_os_str().is_empty() && !parent.exists() {
fs::create_dir_all(parent)
.with_context(|| format!("Failed to create directory {}", parent.display()))?;
}
}
fs::write(&final_output_path, config_content).with_context(|| {
format!(
"Failed to write configuration to {}",
final_output_path.display()
)
})?;
println!(
"\n[OK] Configuration successfully saved to: {}",
final_output_path.display()
);
let show_snippets =
Confirm::new("Would you like to view AI client configuration snippets now?")
.with_default(true)
.prompt()
.unwrap_or(false);
if show_snippets {
print_client_snippets(&final_output_path, "fs-mcp-rs");
}
Ok(final_output_path)
}