mirror of
https://github.com/BloopAI/dev-manager-mcp.git
synced 2026-08-23 11:58:33 +00:00
Increase the time before auto shutdown of dev server (vibe-kanban 8b5175a7)
Increase from 60s to 120s, allow to be overriden with CLI
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# MCP Dev Server Manager
|
# MCP Dev Server Manager
|
||||||
|
|
||||||
A daemon that accepts requests from MCP clients to start dev servers, allocating unique ports to avoid collisions and shutting down idle connections after 60s of inactivity.
|
A daemon that accepts requests from MCP clients to start dev servers, allocating unique ports to avoid collisions and shutting down idle connections after 120s of inactivity.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ A daemon that accepts requests from MCP clients to start dev servers, allocating
|
|||||||
- **Avoid port collisions**: when working with websites, it's often necessary to specify different ports if you want to run multiple dev servers
|
- **Avoid port collisions**: when working with websites, it's often necessary to specify different ports if you want to run multiple dev servers
|
||||||
- **Automatic port allocation** starting at 3010 with reuse
|
- **Automatic port allocation** starting at 3010 with reuse
|
||||||
- **Log capture** with 512KB ring buffers per server
|
- **Log capture** with 512KB ring buffers per server
|
||||||
- **Auto-cleanup** of idle sessions after 60 seconds
|
- **Auto-cleanup** of idle sessions after 120 seconds (configurable via `--idle-timeout`)
|
||||||
|
|
||||||
## Installation & Usage
|
## Installation & Usage
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ Get stdout/stderr logs for a development server session.
|
|||||||
- Single `Arc<Manager>` shared across all client connections
|
- Single `Arc<Manager>` shared across all client connections
|
||||||
- Each connection gets a fresh `DevManagerService` instance
|
- Each connection gets a fresh `DevManagerService` instance
|
||||||
- Mutex-protected HashMap for session storage
|
- Mutex-protected HashMap for session storage
|
||||||
- Background sweeper runs every 5 seconds to clean up idle sessions (>60s)
|
- Background sweeper runs every 5 seconds to clean up idle sessions (>120s by default)
|
||||||
|
|
||||||
### Session Keys
|
### Session Keys
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ use serde_json::Value;
|
|||||||
use service::DevManagerService;
|
use service::DevManagerService;
|
||||||
use std::net::{Ipv4Addr, SocketAddr};
|
use std::net::{Ipv4Addr, SocketAddr};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
fn inject_cwd_if_start_tool(
|
fn inject_cwd_if_start_tool(
|
||||||
@@ -48,8 +49,8 @@ fn inject_cwd_if_start_tool(
|
|||||||
msg
|
msg
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_daemon(port: u16) -> Result<()> {
|
pub async fn run_daemon(port: u16, idle_timeout_secs: u64) -> Result<()> {
|
||||||
let manager = Arc::new(Manager::new());
|
let manager = Arc::new(Manager::new(Duration::from_secs(idle_timeout_secs)));
|
||||||
let bind = SocketAddr::from((Ipv4Addr::LOCALHOST, port));
|
let bind = SocketAddr::from((Ipv4Addr::LOCALHOST, port));
|
||||||
|
|
||||||
println!("MCP daemon listening on {}", bind);
|
println!("MCP daemon listening on {}", bind);
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ enum Command {
|
|||||||
Daemon {
|
Daemon {
|
||||||
#[arg(long, env = "PORT", default_value_t = 3009)]
|
#[arg(long, env = "PORT", default_value_t = 3009)]
|
||||||
port: u16,
|
port: u16,
|
||||||
|
#[arg(long, env = "MCP_IDLE_TIMEOUT", default_value_t = 120)]
|
||||||
|
idle_timeout: u64,
|
||||||
},
|
},
|
||||||
#[command(about = "Run as STDIO proxy that connects to daemon")]
|
#[command(about = "Run as STDIO proxy that connects to daemon")]
|
||||||
Stdio {
|
Stdio {
|
||||||
@@ -30,8 +32,8 @@ enum Command {
|
|||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
||||||
match cli.command.unwrap_or(Command::Daemon { port: 3009 }) {
|
match cli.command.unwrap_or(Command::Daemon { port: 3009, idle_timeout: 120 }) {
|
||||||
Command::Daemon { port } => dev_manager_mcp::run_daemon(port).await,
|
Command::Daemon { port, idle_timeout } => dev_manager_mcp::run_daemon(port, idle_timeout).await,
|
||||||
Command::Stdio { daemon_url } => dev_manager_mcp::run_stdio_proxy(&daemon_url).await,
|
Command::Stdio { daemon_url } => dev_manager_mcp::run_stdio_proxy(&daemon_url).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ use tokio::process::Command;
|
|||||||
type SessionKey = String;
|
type SessionKey = String;
|
||||||
|
|
||||||
const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
const RUNNING_IDLE_SECS: u64 = 60;
|
|
||||||
const EXITED_RETENTION_SECS: u64 = 600;
|
const EXITED_RETENTION_SECS: u64 = 600;
|
||||||
|
|
||||||
fn generate_session_key() -> String {
|
fn generate_session_key() -> String {
|
||||||
@@ -31,7 +30,7 @@ pub struct Manager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn new() -> Self {
|
pub fn new(idle_timeout: Duration) -> Self {
|
||||||
let manager = Self {
|
let manager = Self {
|
||||||
inner: Arc::new(Mutex::new(ManagerInner {
|
inner: Arc::new(Mutex::new(ManagerInner {
|
||||||
servers: HashMap::new(),
|
servers: HashMap::new(),
|
||||||
@@ -39,11 +38,11 @@ impl Manager {
|
|||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
|
|
||||||
manager.start_sweeper();
|
manager.start_sweeper(idle_timeout);
|
||||||
manager
|
manager
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_sweeper(&self) {
|
fn start_sweeper(&self, idle_timeout: Duration) {
|
||||||
let inner = self.inner.clone();
|
let inner = self.inner.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut interval = tokio::time::interval(Duration::from_secs(5));
|
let mut interval = tokio::time::interval(Duration::from_secs(5));
|
||||||
@@ -57,7 +56,7 @@ impl Manager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let idle_threshold = Duration::from_secs(RUNNING_IDLE_SECS);
|
let idle_threshold = idle_timeout;
|
||||||
let retention_threshold = Duration::from_secs(EXITED_RETENTION_SECS);
|
let retention_threshold = Duration::from_secs(EXITED_RETENTION_SECS);
|
||||||
|
|
||||||
let mut to_stop = Vec::new();
|
let mut to_stop = Vec::new();
|
||||||
|
|||||||
Reference in New Issue
Block a user