Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/forge_api/src/forge_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ impl ForgeAPI<ForgeServices<ForgeRepo<ForgeInfra>>, ForgeRepo<ForgeInfra>> {
/// * `cwd` - The working directory path for environment and file resolution
/// * `config` - Pre-read application configuration (from startup)
/// * `services_url` - Pre-validated URL for the gRPC workspace server
pub fn init(cwd: PathBuf, config: ForgeConfig) -> Self {
pub fn init(cwd: PathBuf, config: ForgeConfig, skip_local_mcp: bool) -> Self {
let infra = Arc::new(ForgeInfra::new(cwd, config));
let repo = Arc::new(ForgeRepo::new(infra.clone()));
let app = Arc::new(ForgeServices::new(repo.clone()));
let app = Arc::new(ForgeServices::new(repo.clone(), skip_local_mcp));
ForgeAPI::new(app, repo)
}

Expand Down
2 changes: 1 addition & 1 deletion crates/forge_main/src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl Section {
/// # Output Format
///
/// ```text
///
///
/// CONFIGURATION
/// model gpt-4
/// provider openai
Expand Down
16 changes: 15 additions & 1 deletion crates/forge_main/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use forge_select::ForgeWidget;

use std::io::{IsTerminal, Read};
use std::panic;
use std::path::PathBuf;
Expand Down Expand Up @@ -120,10 +122,22 @@ async fn run() -> Result<()> {
Err(_) => panic!("Invalid path: {}", cli.display()),
},
(_, _) => std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")),
};

// Check for local .mcp.json and prompt for trust before UI starts
let local_mcp = cwd.join(".mcp.json");
let skip_local_mcp = if local_mcp.exists() {
!ForgeWidget::confirm("Untrusted .mcp.json found in current directory. Do you trust its contents?")
.with_default(false)
.prompt()
.unwrap_or(Some(false))
.unwrap_or(false)
} else {
false
};

let mut ui = UI::init(cli, config, move |config| {
ForgeAPI::init(cwd.clone(), config)
ForgeAPI::init(cwd.clone(), config, skip_local_mcp)
})?;
ui.run().await;

Expand Down
2 changes: 1 addition & 1 deletion crates/forge_repo/src/skill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ mod tests {
let skill_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("src/fixtures/skills_with_resources");
let config = ForgeConfig::read().unwrap_or_default();
let infra = Arc::new(ForgeInfra::new(std::env::current_dir().unwrap(), config));
let infra = Arc::new(ForgeInfra::new(std::env::current_dir().unwrap(), config, false));
let repo = ForgeSkillRepository::new(infra);
(repo, skill_dir)
}
Expand Down
4 changes: 2 additions & 2 deletions crates/forge_services/src/forge_services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ impl<
+ ValidationRepository,
> ForgeServices<F>
{
pub fn new(infra: Arc<F>) -> Self {
let mcp_manager = Arc::new(ForgeMcpManager::new(infra.clone()));
pub fn new(infra: Arc<F>, skip_local_mcp: bool) -> Self {
let mcp_manager = Arc::new(ForgeMcpManager::new(infra.clone(), skip_local_mcp));
let mcp_service = Arc::new(ForgeMcpService::new(mcp_manager.clone(), infra.clone()));
let template_service = Arc::new(ForgeTemplateService::new(infra.clone()));
let attachment_service = Arc::new(ForgeChatRequest::new(infra.clone()));
Expand Down
11 changes: 7 additions & 4 deletions crates/forge_services/src/mcp/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ use merge::Merge;

pub struct ForgeMcpManager<I> {
infra: Arc<I>,
skip_local_mcp: bool,
}

impl<I> ForgeMcpManager<I>
where
I: McpServerInfra + FileReaderInfra + FileInfoInfra + EnvironmentInfra + KVStore,
{
pub fn new(infra: Arc<I>) -> Self {
Self { infra }
pub fn new(infra: Arc<I>, skip_local_mcp: bool) -> Self {
Self { infra, skip_local_mcp }
}

async fn read_config(&self, path: &Path) -> anyhow::Result<McpConfig> {
Expand Down Expand Up @@ -58,15 +59,17 @@ where
}
}
None => {
// Read and merge all configurations (original behavior)
// Read and merge all configurations
let env = self.infra.get_environment();
let paths = vec![
// Configs at lower levels take precedence, so we read them in reverse order.
env.mcp_user_config().as_path().to_path_buf(),
env.mcp_local_config().as_path().to_path_buf(),
];
let mut config = McpConfig::default();
for path in paths {
if path == env.mcp_local_config() && self.skip_local_mcp {
continue;
}
if self.infra.is_file(&path).await.unwrap_or_default() {
let new_config = self.read_config(&path).await.context(format!(
"An error occurred while reading config at: {}",
Expand Down