#[cfg(feature = "mcp-server")]
use a2a_mcp::bridge::agent_to_mcp::AgentToMcpBridge;
#[cfg(feature = "mcp-server")]
use a2a_rs::{domain::AgentCard, port::AsyncMessageHandler};
#[cfg(feature = "mcp-server")]
use rmcp::{RoleServer, transport::stdio};
#[cfg(feature = "mcp-server")]
use tracing::info;
#[cfg(feature = "mcp-server")]
use crate::core::config::McpServerConfig;
#[cfg(feature = "mcp-server")]
pub async fn run_mcp_server<H>(
config: &McpServerConfig,
agent_card: AgentCard,
handler: H,
) -> Result<(), Box<dyn std::error::Error>>
where
H: AsyncMessageHandler + Send + Sync + 'static,
{
if !config.enabled {
return Ok(());
}
info!("Starting MCP server for agent: {}", agent_card.name);
let bridge = AgentToMcpBridge::with_handler(handler, agent_card.clone())
.with_mcp_metadata(config.name.clone(), config.version.clone());
if config.stdio {
info!("Starting stdio transport for MCP server");
let (read, write) = stdio();
let _running =
rmcp::service::serve_directly::<RoleServer, _, _, _, _>(bridge, (read, write), None);
tokio::select! {
_ = tokio::signal::ctrl_c() => {
info!("Received Ctrl+C, shutting down");
}
_ = tokio::time::sleep(tokio::time::Duration::MAX) => {
}
}
info!("MCP server shutdown gracefully");
Ok(())
} else {
info!("Only stdio transport is currently supported for MCP server");
Ok(())
}
}
#[cfg(feature = "mcp-server")]
pub fn is_mcp_server_enabled(config: &McpServerConfig) -> bool {
config.enabled
}
#[cfg(not(feature = "mcp-server"))]
pub async fn run_mcp_server<H>(
_config: &crate::core::config::McpServerConfig,
_agent_card: a2a_rs::domain::AgentCard,
_handler: H,
) -> Result<(), Box<dyn std::error::Error>>
where
H: a2a_rs::port::AsyncMessageHandler + Send + Sync + 'static,
{
tracing::warn!("MCP server feature not enabled. Compile with --features mcp-server");
Ok(())
}
#[cfg(not(feature = "mcp-server"))]
pub fn is_mcp_server_enabled(_config: &crate::core::config::McpServerConfig) -> bool {
false
}