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