Skip to main content

winx_code_agent/
server.rs

1//! Winx MCP server facade.
2//!
3//! Protocol catalog, session lifecycle, task handling, MCP dispatch, and tool
4//! adapters live in focused submodules under `server/`.
5
6mod catalog;
7mod coherence;
8mod handler;
9mod mutations;
10mod outcomes;
11mod principal;
12mod recovery;
13mod sessions;
14mod tasks;
15mod tool_dispatch;
16mod usage;
17
18#[cfg(test)]
19mod tests;
20
21use std::sync::Arc;
22
23use rmcp::{
24    transport::{async_rw::AsyncRwTransport, stdio},
25    ServiceExt,
26};
27use tokio::sync::Mutex;
28use tracing::info;
29
30use crate::runtime::{configured_shell_runtime, ShellRuntime};
31use crate::state::task_state::TaskRegistry;
32use crate::state::BashState;
33use sessions::SessionRegistry;
34
35pub use sessions::SessionIsolation;
36
37/// Shared shell state for one logical Winx session.
38pub type SharedBashState = Arc<Mutex<Option<BashState>>>;
39
40/// Winx service shared by stdio or HTTP transports.
41#[derive(Clone)]
42pub struct WinxService {
43    sessions: Arc<Mutex<SessionRegistry>>,
44    tasks: Arc<Mutex<TaskRegistry>>,
45    root_bootstrap: Arc<Mutex<()>>,
46    shell_runtime: Arc<dyn ShellRuntime>,
47    mutations: mutations::MutationCoordinator,
48    /// Version information advertised in the MCP handshake.
49    pub version: String,
50    isolation: SessionIsolation,
51}
52
53/// Create and start the Winx MCP server.
54pub async fn start_winx_server() -> Result<(), Box<dyn std::error::Error>> {
55    start_winx_server_with_runtime(configured_shell_runtime().await?).await
56}
57
58/// Create and start the stdio MCP server with an explicit shell runtime.
59pub async fn start_winx_server_with_runtime(
60    runtime: Arc<dyn ShellRuntime>,
61) -> Result<(), Box<dyn std::error::Error>> {
62    info!("Starting Winx MCP Server");
63    let service = WinxService::with_runtime(SessionIsolation::Lenient, runtime);
64    let (stdin, stdout) = stdio();
65    let transport = AsyncRwTransport::new_server(stdin, stdout);
66    let server = service.serve(transport).await?;
67    server.waiting().await?;
68    Ok(())
69}