From 98c056c3d948e73dde5745909fbd1d0c88497242 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 11 Aug 2025 14:59:05 +0800 Subject: [PATCH] CLI: add `fonts download` subcommand to fetch assets Expose a `docx-mcp fonts download` subcommand that runs the existing `download_fonts.sh` helper, so users can fetch the embedded fonts via the binary. Keeps existing flags intact and avoids build-time network coupling. --- src/main.rs | 30 +++++++++++++++++++++++++++++- src/security.rs | 23 ++++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8d68b06..e786161 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use anyhow::Result; use mcp_server::{Server, ServerBuilder, ServerOptions}; use mcp_core::ToolManager; -use tracing::info; +use tracing::{info, warn}; use tracing_subscriber::{EnvFilter, fmt, prelude::*}; use clap::Parser; @@ -16,6 +16,7 @@ mod security; mod fonts; use docx_tools::DocxToolsProvider; +use std::process::Command; #[tokio::main] async fn main() -> Result<()> { @@ -26,6 +27,33 @@ async fn main() -> Result<()> { // Parse command line arguments (which also includes environment variables) let args = security::Args::parse(); + + // Handle top-level subcommands that should run and exit + if let Some(cmd) = &args.command { + match cmd { + security::CliCommand::Fonts { action } => { + match action { + security::FontsAction::Download => { + info!("Downloading fonts via embedded helper..."); + // Prefer the script if available; otherwise, fetch directly in the future + let script_path = "./download_fonts.sh"; + if !std::path::Path::new(script_path).exists() { + warn!("download_fonts.sh not found; please run it manually or pull latest"); + anyhow::bail!("download_fonts.sh not found"); + } + + let status = Command::new(script_path).status()?; + if !status.success() { + anyhow::bail!("Font download helper failed"); + } + info!("Fonts downloaded successfully"); + return Ok(()); + } + } + } + } + } + let security_config = security::SecurityConfig::from_args(args); info!("Starting DOCX MCP Server - Security: {}", security_config.get_summary()); diff --git a/src/security.rs b/src/security.rs index 231c59b..12ab415 100644 --- a/src/security.rs +++ b/src/security.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use std::collections::HashSet; use std::env; use tracing::{debug, info, warn}; -use clap::Parser; +use clap::{Parser, Subcommand}; /// Command line arguments for the DOCX MCP server #[derive(Parser, Debug)] @@ -41,6 +41,10 @@ pub struct Args { /// Maximum number of open documents #[arg(long, env = "DOCX_MCP_MAX_DOCS")] pub max_docs: Option, + + /// Optional top-level subcommand (e.g., fonts download) + #[command(subcommand)] + pub command: Option, } /// Security configuration for the MCP server @@ -71,6 +75,23 @@ pub struct SecurityConfig { pub sandbox_mode: bool, } +/// Top-level CLI subcommands +#[derive(Subcommand, Debug, Clone, Serialize, Deserialize)] +pub enum CliCommand { + /// Font utilities + Fonts { + #[command(subcommand)] + action: FontsAction, + }, +} + +/// Font-related actions +#[derive(Subcommand, Debug, Clone, Serialize, Deserialize)] +pub enum FontsAction { + /// Download open-source fonts into assets/fonts + Download, +} + impl Default for SecurityConfig { fn default() -> Self { Self {