refactor: migrate functions and MCP servers to AppConfig

This commit is contained in:
2026-04-19 18:14:16 -06:00
parent 39a16f8d56
commit ff42460cb4
8 changed files with 355 additions and 8 deletions
+65 -3
View File
@@ -28,12 +28,15 @@
//! additive scaffolding that Step 8+ will connect when the entry
//! points migrate. See `docs/PHASE-1-IMPLEMENTATION-PLAN.md`.
use super::mcp_factory::McpFactory;
use super::mcp_factory::{McpFactory, McpServerKey};
use super::rag_cache::RagCache;
use crate::config::AppConfig;
use crate::mcp::McpServersConfig;
use crate::vault::GlobalVault;
use crate::function::Functions;
use crate::mcp::{McpRegistry, McpServersConfig};
use crate::utils::AbortSignal;
use crate::vault::{GlobalVault, Vault};
use anyhow::Result;
use std::path::PathBuf;
use std::sync::Arc;
@@ -46,4 +49,63 @@ pub struct AppState {
pub rag_cache: Arc<RagCache>,
pub mcp_config: Option<McpServersConfig>,
pub mcp_log_path: Option<PathBuf>,
pub mcp_registry: Option<Arc<McpRegistry>>,
pub functions: Functions,
}
impl AppState {
#[allow(dead_code)]
pub async fn init(
config: Arc<AppConfig>,
log_path: Option<PathBuf>,
start_mcp_servers: bool,
abort_signal: AbortSignal,
) -> Result<Self> {
let vault = Arc::new(Vault::init(&config));
let mcp_registry = McpRegistry::init(
log_path,
start_mcp_servers,
config.enabled_mcp_servers.clone(),
abort_signal,
&config,
&vault,
)
.await?;
let mcp_config = mcp_registry.mcp_config().cloned();
let mcp_log_path = mcp_registry.log_path().cloned();
let mcp_factory = Arc::new(McpFactory::default());
if let Some(mcp_servers_config) = &mcp_config {
for (id, handle) in mcp_registry.running_servers() {
if let Some(spec) = mcp_servers_config.mcp_servers.get(id) {
let key = McpServerKey::from_spec(id, spec);
mcp_factory.insert_active(key, handle);
}
}
}
let mut functions = Functions::init(config.visible_tools.as_ref().unwrap_or(&Vec::new()))?;
if !mcp_registry.is_empty() && config.mcp_server_support {
functions.append_mcp_meta_functions(mcp_registry.list_started_servers());
}
let mcp_registry = if mcp_registry.is_empty() {
None
} else {
Some(Arc::new(mcp_registry))
};
Ok(Self {
config,
vault,
mcp_factory,
rag_cache: Arc::new(RagCache::default()),
mcp_config,
mcp_log_path,
mcp_registry,
functions,
})
}
}
+3 -1
View File
@@ -729,12 +729,14 @@ impl Config {
start_mcp_servers: bool,
abort_signal: AbortSignal,
) -> Result<()> {
let app_config = self.to_app_config();
let mcp_registry = McpRegistry::init(
log_path,
start_mcp_servers,
self.enabled_mcp_servers.clone(),
abort_signal.clone(),
self,
&app_config,
&self.vault,
)
.await?;
match mcp_registry.is_empty() {
+2
View File
@@ -2408,6 +2408,8 @@ mod tests {
rag_cache: Arc::new(RagCache::default()),
mcp_config: None,
mcp_log_path: None,
mcp_registry: None,
functions: cfg.functions.clone(),
})
}
+2
View File
@@ -697,6 +697,8 @@ mod tests {
rag_cache: Arc::new(rag_cache::RagCache::default()),
mcp_config: None,
mcp_log_path: None,
mcp_registry: None,
functions: cfg.functions.clone(),
});
let ctx = cfg.to_request_context(app_state);
let session = Session::new_from_ctx(&ctx, &app_config, "test-session");
+2
View File
@@ -486,6 +486,8 @@ async fn handle_spawn(ctx: &mut RequestContext, args: &Value) -> Result<Value> {
rag_cache: ctx.app.rag_cache.clone(),
mcp_config: ctx.app.mcp_config.clone(),
mcp_log_path: ctx.app.mcp_log_path.clone(),
mcp_registry: ctx.app.mcp_registry.clone(),
functions: ctx.app.functions.clone(),
});
let agent = Agent::init(
app_config.as_ref(),
+4
View File
@@ -111,6 +111,8 @@ async fn main() -> Result<()> {
Some(reg) => (reg.mcp_config().cloned(), reg.log_path().cloned()),
None => (None, None),
};
let mcp_registry = cfg.mcp_registry.clone().map(Arc::new);
let functions = cfg.functions.clone();
let app_state: Arc<AppState> = Arc::new(AppState {
config: app_config,
vault: cfg.vault.clone(),
@@ -118,6 +120,8 @@ async fn main() -> Result<()> {
rag_cache: Default::default(),
mcp_config,
mcp_log_path,
mcp_registry,
functions,
});
let ctx = cfg.to_request_context(app_state);
+6 -4
View File
@@ -1,6 +1,7 @@
use crate::config::Config;
use crate::config::AppConfig;
use crate::config::paths;
use crate::utils::{AbortSignal, abortable_run_with_spinner};
use crate::vault::Vault;
use crate::vault::interpolate_secrets;
use anyhow::{Context, Result, anyhow};
use futures_util::{StreamExt, TryStreamExt, stream};
@@ -78,7 +79,8 @@ impl McpRegistry {
start_mcp_servers: bool,
enabled_mcp_servers: Option<String>,
abort_signal: AbortSignal,
config: &Config,
app_config: &AppConfig,
vault: &Vault,
) -> Result<Self> {
let mut registry = Self {
log_path,
@@ -111,7 +113,7 @@ impl McpRegistry {
return Ok(registry);
}
let (parsed_content, missing_secrets) = interpolate_secrets(&content, &config.vault);
let (parsed_content, missing_secrets) = interpolate_secrets(&content, vault);
if !missing_secrets.is_empty() {
return Err(anyhow!(formatdoc!(
@@ -126,7 +128,7 @@ impl McpRegistry {
serde_json::from_str(&parsed_content).with_context(err)?;
registry.config = Some(mcp_servers_config);
if start_mcp_servers && config.mcp_server_support {
if start_mcp_servers && app_config.mcp_server_support {
abortable_run_with_spinner(
registry.start_select_mcp_servers(enabled_mcp_servers),
"Loading MCP servers",