Skip to main content

stygian_plugin/
config.rs

1//! Runtime configuration for the standalone MCP server.
2
3use clap::{Parser, ValueEnum};
4use std::path::PathBuf;
5
6/// Transport mode for the MCP server.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Default)]
8pub enum TransportMode {
9    /// JSON-RPC 2.0 over stdin/stdout (default; for LLM tool integrations).
10    #[default]
11    Stdio,
12    /// JSON-RPC 2.0 over HTTP (for Chrome extension and browser clients).
13    Http,
14}
15
16/// Command-line configuration for stygian-plugin MCP server.
17#[derive(Debug, Clone, Parser)]
18#[command(name = "stygian-plugin-mcp")]
19#[command(about = "Standalone MCP server for stygian-plugin extraction", long_about = None)]
20pub struct Config {
21    /// Directory where extraction templates are stored (JSON files)
22    #[arg(long, value_name = "PATH", default_value = "./plugin-templates")]
23    pub templates_dir: PathBuf,
24
25    /// Logging level (off, error, warn, info, debug, trace)
26    #[arg(long, value_name = "LEVEL", default_value = "info")]
27    pub log_level: String,
28
29    /// Server name advertised in MCP initialize response
30    #[arg(long, value_name = "NAME", default_value = "stygian-plugin")]
31    pub server_name: String,
32
33    /// Transport mode: stdio (default) or http
34    ///
35    /// Use `http` to expose JSON-RPC 2.0 over HTTP so the Chrome browser
36    /// extension can connect directly via `http://localhost:<port>/mcp/tools/call`.
37    #[arg(long, value_name = "MODE", default_value = "stdio")]
38    pub transport: TransportMode,
39
40    /// Port for the HTTP transport (only used when --transport=http)
41    #[arg(long, value_name = "PORT", default_value = "3000")]
42    pub http_port: u16,
43}
44
45impl Config {
46    /// Parse configuration from command-line arguments and environment variables.
47    #[must_use]
48    pub fn from_args() -> Self {
49        Self::parse()
50    }
51
52    /// Create a test configuration with sensible defaults.
53    #[must_use]
54    pub fn testing() -> Self {
55        Self {
56            templates_dir: PathBuf::from("./test-templates"),
57            log_level: "debug".to_string(),
58            server_name: "stygian-plugin-test".to_string(),
59            transport: TransportMode::Stdio,
60            http_port: 3000,
61        }
62    }
63
64    /// Create a test configuration pointing to an HTTP transport on a given port.
65    #[must_use]
66    pub fn testing_http(port: u16) -> Self {
67        Self {
68            templates_dir: PathBuf::from("./test-templates"),
69            log_level: "debug".to_string(),
70            server_name: "stygian-plugin-test".to_string(),
71            transport: TransportMode::Http,
72            http_port: port,
73        }
74    }
75}
76
77/// Supported MCP protocol versions, in preferred order.
78pub const SUPPORTED_PROTOCOL_VERSIONS: &[&str] = &["2025-11-25", "2025-06-18", "2024-11-05"];
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn test_config_defaults() {
86        let cfg = Config::testing();
87        assert_eq!(cfg.server_name, "stygian-plugin-test");
88        assert_eq!(cfg.log_level, "debug");
89        assert_eq!(cfg.transport, TransportMode::Stdio);
90        assert_eq!(cfg.http_port, 3000);
91    }
92
93    #[test]
94    fn test_config_http() {
95        let cfg = Config::testing_http(8080);
96        assert_eq!(cfg.transport, TransportMode::Http);
97        assert_eq!(cfg.http_port, 8080);
98    }
99}