Skip to main content

mcp_servers/
setup.rs

1use crate::coding::tools::bash::BashEnvironment;
2use crate::{CodingMcp, ReviewMcp, SkillsMcp, SubAgentsMcp, TasksMcp};
3use aether_core::core::AgentDeps;
4use aether_core::mcp::{AETHER_MCP_IPC_SOCKET, McpBuilder, RuntimeServices, ToolFilter, mcp};
5use clap::{Parser, ValueEnum};
6use mcp_utils::server::McpServer;
7use std::path::Path;
8
9#[doc = include_str!("docs/mcp_builder_ext.md")]
10pub trait McpBuilderExt {
11    fn with_builtin_servers(self) -> Self;
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
15pub enum Builtin {
16    Coding,
17    Skills,
18    Tasks,
19    Subagents,
20    Review,
21}
22
23pub fn agent_mcp(root: impl AsRef<Path>, deps: AgentDeps, tools: ToolFilter) -> McpBuilder {
24    mcp(root).with_agent_deps(deps).with_tool_filter(tools).with_builtin_servers()
25}
26
27impl McpBuilderExt for McpBuilder {
28    fn with_builtin_servers(self) -> Self {
29        Builtin::value_variants().iter().fold(self, |builder, &builtin| {
30            builder.register_in_memory_server(builtin.name(), move |args, services| Ok(builtin.build(args, services)?))
31        })
32    }
33}
34
35impl Builtin {
36    pub fn name(self) -> &'static str {
37        match self {
38            Self::Coding => "coding",
39            Self::Skills => "skills",
40            Self::Tasks => "tasks",
41            Self::Subagents => "subagents",
42            Self::Review => "review",
43        }
44    }
45
46    pub fn build(self, args: Vec<String>, services: &RuntimeServices) -> Result<McpServer, clap::Error> {
47        let root = services.root_dir.as_path();
48        Ok(match self {
49            Self::Coding => {
50                CodingMcp::from_args(parse(args)?, root).with_bash_environment(bash_environment(services)).into()
51            }
52            Self::Skills => SkillsMcp::from_args(parse(args)?, root).into(),
53            Self::Tasks => TasksMcp::from_args(parse(args)?, root).into(),
54            Self::Review => ReviewMcp::from_args(parse(args)?, root).into(),
55            Self::Subagents => SubAgentsMcp::from_args(parse(args)?, root, services.agent_deps.clone()).into(),
56        })
57    }
58}
59
60fn parse<T: Parser>(args: Vec<String>) -> Result<T, clap::Error> {
61    T::try_parse_from(args)
62}
63
64fn bash_environment(services: &RuntimeServices) -> BashEnvironment {
65    let environment = BashEnvironment::new().with_current_exe_dir_on_path();
66    match &services.deferred_tools_socket {
67        Some(socket) => environment.with_var(AETHER_MCP_IPC_SOCKET, socket.to_string_lossy()),
68        None => environment,
69    }
70}