lsp-mcp 0.1.0

MCP server providing unified access to Language Server Protocol features
Documentation
use std::path::PathBuf;
use thiserror::Error;

/// Language identifier for LSP servers
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Language {
    Rust,
    TypeScript,
    JavaScript,
    Python,
    Go,
    Cpp,
    C,
}

impl std::fmt::Display for Language {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Language::Rust => write!(f, "rust"),
            Language::TypeScript => write!(f, "typescript"),
            Language::JavaScript => write!(f, "javascript"),
            Language::Python => write!(f, "python"),
            Language::Go => write!(f, "go"),
            Language::Cpp => write!(f, "cpp"),
            Language::C => write!(f, "c"),
        }
    }
}

impl Language {
    /// Get the LSP language identifier string
    pub fn language_id(&self) -> &'static str {
        match self {
            Language::Rust => "rust",
            Language::TypeScript => "typescript",
            Language::JavaScript => "javascript",
            Language::Python => "python",
            Language::Go => "go",
            Language::Cpp => "cpp",
            Language::C => "c",
        }
    }

    /// Detect language from file extension
    pub fn from_extension(ext: &str) -> Option<Self> {
        match ext.to_lowercase().as_str() {
            "rs" => Some(Language::Rust),
            "ts" | "tsx" => Some(Language::TypeScript),
            "js" | "jsx" | "mjs" | "cjs" => Some(Language::JavaScript),
            "py" | "pyi" => Some(Language::Python),
            "go" => Some(Language::Go),
            "cpp" | "cc" | "cxx" | "hpp" | "hxx" => Some(Language::Cpp),
            "c" | "h" => Some(Language::C),
            _ => None,
        }
    }

    /// Try to parse from string
    pub fn from_str(s: &str) -> Option<Self> {
        match s.to_lowercase().as_str() {
            "rust" | "rs" => Some(Language::Rust),
            "typescript" | "ts" => Some(Language::TypeScript),
            "javascript" | "js" => Some(Language::JavaScript),
            "python" | "py" => Some(Language::Python),
            "go" | "golang" => Some(Language::Go),
            "cpp" | "c++" => Some(Language::Cpp),
            "c" => Some(Language::C),
            _ => None,
        }
    }
}

/// Errors that can occur in the LSP MCP server
#[derive(Error, Debug)]
pub enum LspMcpError {
    #[error("No active workspace. Call lsp_activate_workspace first.")]
    NoActiveWorkspace,

    #[error("Workspace not found: {0}")]
    WorkspaceNotFound(PathBuf),

    #[error("Language server not running for {language} in {workspace}")]
    ServerNotRunning {
        language: Language,
        workspace: PathBuf,
    },

    #[error("Language server failed to start: {0}")]
    ServerStartFailed(String),

    #[error("Language server initialization failed: {0}")]
    InitializationFailed(String),

    #[error("LSP request timed out after {0} seconds")]
    RequestTimeout(u64),

    #[error("LSP protocol error: {0}")]
    ProtocolError(String),

    #[error("File not found: {0}")]
    FileNotFound(PathBuf),

    #[error("Unsupported language: {0}")]
    UnsupportedLanguage(String),

    #[error("Invalid position: line {line}, character {character}")]
    InvalidPosition { line: u32, character: u32 },

    #[error("Language server not available: {0}")]
    ServerNotAvailable(String),

    #[error("IO error: {0}")]
    Io(#[from] std::io::Error),

    #[error("JSON error: {0}")]
    Json(#[from] serde_json::Error),

    #[error("Channel send error")]
    ChannelSend,

    #[error("Channel receive error")]
    ChannelRecv,
}

pub type Result<T> = std::result::Result<T, LspMcpError>;