use std::collections::BTreeMap;
use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use super::config::{McpAgentTarget, McpRegistrationScope, McpServerTransport};
use super::error::McpRegisterError;
pub mod claude_code;
pub mod cline;
pub mod codex;
pub mod continue_dev;
pub mod cursor;
pub mod windsurf;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ResolvedServer {
pub name: String,
pub transport: McpServerTransport,
pub command: Option<String>,
pub args: Vec<String>,
pub url: Option<String>,
pub env: BTreeMap<String, String>,
pub is_jarvy: bool,
}
#[derive(Debug, Clone)]
pub struct ApplyOutcome {
pub agent: &'static str,
pub path: PathBuf,
pub applied: usize,
pub warnings: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct RemoveOutcome {
pub agent: &'static str,
pub path: PathBuf,
pub removed: usize,
#[allow(dead_code)]
pub warnings: Vec<String>,
}
#[derive(Debug, Clone, Default)]
pub struct CheckOutcome {
pub agent: &'static str,
pub path: PathBuf,
pub missing: Vec<String>,
pub extra_jarvy: Vec<String>,
}
impl CheckOutcome {
pub fn is_clean(&self) -> bool {
self.missing.is_empty() && self.extra_jarvy.is_empty()
}
}
pub trait AgentRegistrar: Sync {
#[allow(dead_code)]
fn slug(&self) -> &'static str;
fn settings_path(&self, scope: McpRegistrationScope) -> Result<PathBuf, McpRegisterError>;
fn apply(
&self,
servers: &[ResolvedServer],
scope: McpRegistrationScope,
) -> Result<ApplyOutcome, McpRegisterError>;
fn check(
&self,
servers: &[ResolvedServer],
scope: McpRegistrationScope,
) -> Result<CheckOutcome, McpRegisterError>;
fn remove(&self, scope: McpRegistrationScope) -> Result<RemoveOutcome, McpRegisterError>;
}
static CLAUDE_CODE: claude_code::ClaudeCodeRegistrar = claude_code::ClaudeCodeRegistrar;
static CURSOR: cursor::CursorRegistrar = cursor::CursorRegistrar;
static CODEX: codex::CodexRegistrar = codex::CodexRegistrar;
static WINDSURF: windsurf::WindsurfRegistrar = windsurf::WindsurfRegistrar;
static CLINE: cline::ClineRegistrar = cline::ClineRegistrar;
static CONTINUE: continue_dev::ContinueRegistrar = continue_dev::ContinueRegistrar;
pub fn registrar_for(target: McpAgentTarget) -> &'static dyn AgentRegistrar {
match target {
McpAgentTarget::ClaudeCode => &CLAUDE_CODE,
McpAgentTarget::Cursor => &CURSOR,
McpAgentTarget::Codex => &CODEX,
McpAgentTarget::Windsurf => &WINDSURF,
McpAgentTarget::Cline => &CLINE,
McpAgentTarget::Continue => &CONTINUE,
}
}