chore(mcp): convert computercontroller server to use the rust sdk (#4772)
This commit is contained in:
@@ -7,7 +7,6 @@ use crate::commands::acp::run_acp_agent;
|
|||||||
use crate::commands::bench::agent_generator;
|
use crate::commands::bench::agent_generator;
|
||||||
use crate::commands::configure::handle_configure;
|
use crate::commands::configure::handle_configure;
|
||||||
use crate::commands::info::handle_info;
|
use crate::commands::info::handle_info;
|
||||||
use crate::commands::mcp::run_server;
|
|
||||||
use crate::commands::project::{handle_project_default, handle_projects_interactive};
|
use crate::commands::project::{handle_project_default, handle_projects_interactive};
|
||||||
use crate::commands::recipe::{handle_deeplink, handle_list, handle_validate};
|
use crate::commands::recipe::{handle_deeplink, handle_list, handle_validate};
|
||||||
// Import the new handlers from commands::schedule
|
// Import the new handlers from commands::schedule
|
||||||
@@ -743,7 +742,8 @@ pub async fn cli() -> Result<()> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(Command::Mcp { name }) => {
|
Some(Command::Mcp { name }) => {
|
||||||
let _ = run_server(&name).await;
|
crate::logging::setup_logging(Some(&format!("mcp-{name}")), None)?;
|
||||||
|
let _ = goose_mcp::mcp_server_runner::run_mcp_server(&name).await;
|
||||||
}
|
}
|
||||||
Some(Command::Acp {}) => {
|
Some(Command::Acp {}) => {
|
||||||
let _ = run_acp_agent().await;
|
let _ = run_acp_agent().await;
|
||||||
|
|||||||
@@ -1,123 +0,0 @@
|
|||||||
use anyhow::{anyhow, Result};
|
|
||||||
use goose_mcp::{
|
|
||||||
AutoVisualiserRouter, ComputerControllerRouter, DeveloperServer, MemoryServer, TutorialServer,
|
|
||||||
};
|
|
||||||
use mcp_server::router::RouterService;
|
|
||||||
use mcp_server::{BoundedService, ByteTransport, Server};
|
|
||||||
use rmcp::{transport::stdio, ServiceExt};
|
|
||||||
use tokio::io::{stdin, stdout};
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
use tokio::sync::Notify;
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
use nix::sys::signal::{kill, Signal};
|
|
||||||
#[cfg(unix)]
|
|
||||||
use nix::unistd::getpgrp;
|
|
||||||
#[cfg(unix)]
|
|
||||||
use nix::unistd::Pid;
|
|
||||||
|
|
||||||
pub async fn run_server(name: &str) -> Result<()> {
|
|
||||||
crate::logging::setup_logging(Some(&format!("mcp-{name}")), None)?;
|
|
||||||
|
|
||||||
if name == "googledrive" || name == "google_drive" {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"the built-in Google Drive extension has been removed"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
tracing::info!("Starting MCP server");
|
|
||||||
|
|
||||||
// Handle RMCP-based servers
|
|
||||||
if name == "developer" {
|
|
||||||
let service = DeveloperServer::new()
|
|
||||||
.serve(stdio())
|
|
||||||
.await
|
|
||||||
.inspect_err(|e| {
|
|
||||||
tracing::error!("serving error: {:?}", e);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
service.waiting().await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if name == "autovisualiser" {
|
|
||||||
let service = AutoVisualiserRouter::new()
|
|
||||||
.serve(stdio())
|
|
||||||
.await
|
|
||||||
.inspect_err(|e| {
|
|
||||||
tracing::error!("serving error: {:?}", e);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
service.waiting().await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if name == "tutorial" {
|
|
||||||
let service = TutorialServer::new()
|
|
||||||
.serve(stdio())
|
|
||||||
.await
|
|
||||||
.inspect_err(|e| {
|
|
||||||
tracing::error!("serving error: {:?}", e);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
service.waiting().await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if name == "memory" {
|
|
||||||
let service = MemoryServer::new().serve(stdio()).await.inspect_err(|e| {
|
|
||||||
tracing::error!("serving error: {:?}", e);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
service.waiting().await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle old MCP-based servers
|
|
||||||
if name == "memory" {
|
|
||||||
let service = MemoryServer::new().serve(stdio()).await.inspect_err(|e| {
|
|
||||||
tracing::error!("serving error: {:?}", e);
|
|
||||||
})?;
|
|
||||||
service.waiting().await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle old MCP-based servers
|
|
||||||
let router: Option<Box<dyn BoundedService>> = match name {
|
|
||||||
"computercontroller" => Some(Box::new(RouterService(ComputerControllerRouter::new()))),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let shutdown = Arc::new(Notify::new());
|
|
||||||
let shutdown_clone = shutdown.clone();
|
|
||||||
|
|
||||||
tokio::spawn(async move {
|
|
||||||
crate::signal::shutdown_signal().await;
|
|
||||||
shutdown_clone.notify_one();
|
|
||||||
});
|
|
||||||
|
|
||||||
let server = Server::new(router.unwrap_or_else(|| panic!("Unknown server requested {}", name)));
|
|
||||||
let transport = ByteTransport::new(stdin(), stdout());
|
|
||||||
|
|
||||||
tracing::info!("Server initialized and ready to handle requests");
|
|
||||||
|
|
||||||
tokio::select! {
|
|
||||||
result = server.run(transport) => {
|
|
||||||
Ok(result?)
|
|
||||||
}
|
|
||||||
_ = shutdown.notified() => {
|
|
||||||
// On Unix systems, kill the entire process group
|
|
||||||
#[cfg(unix)]
|
|
||||||
{
|
|
||||||
fn terminate_process_group() {
|
|
||||||
let pgid = getpgrp();
|
|
||||||
kill(Pid::from_raw(-pgid.as_raw()), Signal::SIGTERM)
|
|
||||||
.expect("Failed to send SIGTERM to process group");
|
|
||||||
}
|
|
||||||
terminate_process_group();
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,6 @@ pub mod acp;
|
|||||||
pub mod bench;
|
pub mod bench;
|
||||||
pub mod configure;
|
pub mod configure;
|
||||||
pub mod info;
|
pub mod info;
|
||||||
pub mod mcp;
|
|
||||||
pub mod project;
|
pub mod project;
|
||||||
pub mod recipe;
|
pub mod recipe;
|
||||||
pub mod schedule;
|
pub mod schedule;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -10,11 +10,12 @@ pub static APP_STRATEGY: Lazy<AppStrategyArgs> = Lazy::new(|| AppStrategyArgs {
|
|||||||
pub mod autovisualiser;
|
pub mod autovisualiser;
|
||||||
pub mod computercontroller;
|
pub mod computercontroller;
|
||||||
pub mod developer;
|
pub mod developer;
|
||||||
|
pub mod mcp_server_runner;
|
||||||
mod memory;
|
mod memory;
|
||||||
pub mod tutorial;
|
pub mod tutorial;
|
||||||
|
|
||||||
pub use autovisualiser::AutoVisualiserRouter;
|
pub use autovisualiser::AutoVisualiserRouter;
|
||||||
pub use computercontroller::ComputerControllerRouter;
|
pub use computercontroller::ComputerControllerServer;
|
||||||
pub use developer::rmcp_developer::DeveloperServer;
|
pub use developer::rmcp_developer::DeveloperServer;
|
||||||
pub use memory::MemoryServer;
|
pub use memory::MemoryServer;
|
||||||
pub use tutorial::TutorialServer;
|
pub use tutorial::TutorialServer;
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
use crate::{
|
||||||
|
AutoVisualiserRouter, ComputerControllerServer, DeveloperServer, MemoryServer, TutorialServer,
|
||||||
|
};
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use rmcp::{transport::stdio, ServiceExt};
|
||||||
|
|
||||||
|
/// Run an MCP server by name
|
||||||
|
///
|
||||||
|
/// This function handles the common logic for starting MCP servers.
|
||||||
|
/// The caller is responsible for setting up logging before calling this function.
|
||||||
|
pub async fn run_mcp_server(name: &str) -> Result<()> {
|
||||||
|
if name == "googledrive" || name == "google_drive" {
|
||||||
|
return Err(anyhow!(
|
||||||
|
"the built-in Google Drive extension has been removed"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
tracing::info!("Starting MCP server");
|
||||||
|
|
||||||
|
match name {
|
||||||
|
"autovisualiser" => serve_and_wait(AutoVisualiserRouter::new()).await,
|
||||||
|
"computercontroller" => serve_and_wait(ComputerControllerServer::new()).await,
|
||||||
|
"developer" => serve_and_wait(DeveloperServer::new()).await,
|
||||||
|
"memory" => serve_and_wait(MemoryServer::new()).await,
|
||||||
|
"tutorial" => serve_and_wait(TutorialServer::new()).await,
|
||||||
|
_ => {
|
||||||
|
tracing::warn!("Unknown MCP server name: {}", name);
|
||||||
|
Err(anyhow!("Unknown MCP server name: {}", name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function to run any MCP server with common error handling
|
||||||
|
async fn serve_and_wait<S>(server: S) -> Result<()>
|
||||||
|
where
|
||||||
|
S: rmcp::ServerHandler,
|
||||||
|
{
|
||||||
|
let service = server.serve(stdio()).await.inspect_err(|e| {
|
||||||
|
tracing::error!("serving error: {:?}", e);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
service.waiting().await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
use anyhow::{anyhow, Result};
|
|
||||||
use goose_mcp::{
|
|
||||||
AutoVisualiserRouter, ComputerControllerRouter, DeveloperServer, MemoryServer, TutorialServer,
|
|
||||||
};
|
|
||||||
use mcp_server::router::RouterService;
|
|
||||||
use mcp_server::{BoundedService, ByteTransport, Server};
|
|
||||||
use rmcp::{transport::stdio, ServiceExt};
|
|
||||||
use tokio::io::{stdin, stdout};
|
|
||||||
|
|
||||||
pub async fn run(name: &str) -> Result<()> {
|
|
||||||
crate::logging::setup_logging(Some(&format!("mcp-{name}")))?;
|
|
||||||
|
|
||||||
if name == "googledrive" || name == "google_drive" {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"the built-in Google Drive extension has been removed"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
tracing::info!("Starting MCP server");
|
|
||||||
|
|
||||||
// Handle RMCP-based servers
|
|
||||||
if name == "developer" {
|
|
||||||
let service = DeveloperServer::new()
|
|
||||||
.serve(stdio())
|
|
||||||
.await
|
|
||||||
.inspect_err(|e| {
|
|
||||||
tracing::error!("serving error: {:?}", e);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
service.waiting().await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if name == "autovisualiser" {
|
|
||||||
let service = AutoVisualiserRouter::new()
|
|
||||||
.serve(stdio())
|
|
||||||
.await
|
|
||||||
.inspect_err(|e| {
|
|
||||||
tracing::error!("serving error: {:?}", e);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
service.waiting().await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if name == "tutorial" {
|
|
||||||
let service = TutorialServer::new()
|
|
||||||
.serve(stdio())
|
|
||||||
.await
|
|
||||||
.inspect_err(|e| {
|
|
||||||
tracing::error!("serving error: {:?}", e);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
service.waiting().await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if name == "memory" {
|
|
||||||
let service = MemoryServer::new().serve(stdio()).await.inspect_err(|e| {
|
|
||||||
tracing::error!("serving error: {:?}", e);
|
|
||||||
})?;
|
|
||||||
service.waiting().await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle old MCP-based servers
|
|
||||||
let router: Option<Box<dyn BoundedService>> = match name {
|
|
||||||
"computercontroller" => Some(Box::new(RouterService(ComputerControllerRouter::new()))),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let server = Server::new(router.unwrap_or_else(|| panic!("Unknown server requested {}", name)));
|
|
||||||
let transport = ByteTransport::new(stdin(), stdout());
|
|
||||||
|
|
||||||
tracing::info!("Server initialized and ready to handle requests");
|
|
||||||
Ok(server.run(transport).await?)
|
|
||||||
}
|
|
||||||
@@ -1,2 +1 @@
|
|||||||
pub mod agent;
|
pub mod agent;
|
||||||
pub mod mcp;
|
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
commands::agent::run().await?;
|
commands::agent::run().await?;
|
||||||
}
|
}
|
||||||
Commands::Mcp { name } => {
|
Commands::Mcp { name } => {
|
||||||
commands::mcp::run(name).await?;
|
logging::setup_logging(Some(&format!("mcp-{name}")))?;
|
||||||
|
goose_mcp::mcp_server_runner::run_mcp_server(name).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user