diff --git a/crates/goose-server/src/state.rs b/crates/goose-server/src/state.rs index 85f4ab76..57f104d4 100644 --- a/crates/goose-server/src/state.rs +++ b/crates/goose-server/src/state.rs @@ -1,8 +1,11 @@ use axum::http::StatusCode; -use goose::builtin_extension::register_builtin_extensions; +use goose::builtin_extension::{register_builtin_extension, register_builtin_extensions}; +use goose::config::paths::Paths; use goose::execution::manager::AgentManager; use goose::scheduler_trait::SchedulerTrait; use goose::session::SessionManager; +use goose_mcp::DeveloperServer; +use rmcp::ServiceExt; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use std::sync::Arc; @@ -25,9 +28,25 @@ pub struct AppState { pub extension_loading_tasks: ExtensionLoadingTasks, } +fn spawn_developer(r: tokio::io::DuplexStream, w: tokio::io::DuplexStream) { + let bash_env = Paths::config_dir().join(".bash_env"); + let server = DeveloperServer::new() + .extend_path_with_shell(true) + .bash_env_file(Some(bash_env)); + tokio::spawn(async move { + match server.serve((r, w)).await { + Ok(running) => { + let _ = running.waiting().await; + } + Err(e) => tracing::error!(builtin = "developer", error = %e, "server error"), + } + }); +} + impl AppState { pub async fn new() -> anyhow::Result> { register_builtin_extensions(goose_mcp::BUILTIN_EXTENSIONS.clone()); + register_builtin_extension("developer", spawn_developer); let agent_manager = AgentManager::instance().await?; let tunnel_manager = Arc::new(TunnelManager::new());