proto_cli 0.57.3

A multi-language version manager, a unified toolchain.
use crate::mcp::ProtoMcp;
use crate::session::ProtoSession;
use clap::Args;
use iocraft::prelude::element;
use miette::IntoDiagnostic;
use rmcp::{ServerHandler, ServiceExt, transport::stdio};
use starbase::AppResult;
use starbase_console::ui::*;

#[derive(Args, Clone, Debug)]
pub struct McpArgs {
    #[arg(
        long,
        help = "Display server information and list available tools and resources"
    )]
    info: bool,
}

#[tracing::instrument(skip_all)]
pub async fn mcp(session: ProtoSession, args: McpArgs) -> AppResult {
    let console = session.console.clone();
    let server = ProtoMcp::new(session);

    if !args.info {
        server
            .serve(stdio())
            .await
            .into_diagnostic()?
            .waiting()
            .await
            .into_diagnostic()?;

        return Ok(None);
    }

    let info = server.get_info();

    let mut tools = server.tool_router.list_all();
    tools.sort_by(|a, d| a.name.cmp(&d.name));

    let mut resources = server.list_all_resources().resources;
    resources.sort_by(|a, d| a.name.cmp(&d.name));

    console.render(element! {
        Container {
            Section(title: "Server") {
                #(info.instructions.as_ref().map(|desc| {
                    element! {
                        View(margin_bottom: 1) {
                            StyledText(
                                content: desc,
                            )
                        }
                    }
                }))

                Entry(
                    name: "CLI version",
                    value: element! {
                        StyledText(
                            content: info.server_info.version.to_string(),
                            style: Style::Symbol
                        )
                    }.into_any()
                )
                Entry(
                    name: "Protocol version",
                    value: element! {
                        StyledText(
                            content: info.protocol_version.to_string(),
                            style: Style::Hash
                        )
                    }.into_any()
                )
            }

            Section(title: "Tools") {
                #(tools.into_iter().map(|tool| {
                    element! {
                        Entry(
                            name: tool.name.to_string(),
                            content: tool.description.unwrap_or_default().to_string(),
                        )
                    }
                }))
            }

            Section(title: "Resources") {
                #(resources.into_iter().map(|resource| {
                    element! {
                        Entry(
                            name: resource.uri.to_string(),
                            content: resource.name.to_string(),
                        )
                    }
                }))
            }
        }
    })?;

    Ok(None)
}