codex-memory 3.0.15

A simple memory storage service with MCP interface for Claude Desktop
Documentation
use crate::error::{Error, Result};
use serde::{Deserialize, Serialize};

/// Minimal configuration for the storage service
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    /// PostgreSQL database connection URL
    pub database_url: String,

    /// MCP server port
    pub mcp_port: u16,

    /// Log level (debug, info, warn, error)
    pub log_level: String,
}

impl Config {
    /// Load configuration from environment variables
    pub fn from_env() -> Result<Self> {
        // Only load .env file if not in test mode
        #[cfg(not(test))]
        dotenvy::dotenv().ok(); // Ignore if .env doesn't exist

        let database_url = std::env::var("DATABASE_URL")
            .map_err(|_| Error::Config("DATABASE_URL not set".to_string()))?;

        // Ensure DATABASE_URL is not empty
        if database_url.is_empty() {
            return Err(Error::Config("DATABASE_URL not set or empty".to_string()));
        }

        let mcp_port = std::env::var("MCP_PORT")
            .unwrap_or_else(|_| "3333".to_string())
            .parse::<u16>()
            .map_err(|e| Error::Config(format!("Invalid MCP_PORT: {e}")))?;

        let log_level = std::env::var("LOG_LEVEL").unwrap_or_else(|_| "info".to_string());

        Ok(Self {
            database_url,
            mcp_port,
            log_level,
        })
    }

    /// Create test configuration with custom database URL
    #[cfg(test)]
    pub fn for_test(database_url: String) -> Self {
        Self {
            database_url,
            mcp_port: 3333,
            log_level: "info".to_string(),
        }
    }
}

impl Default for Config {
    fn default() -> Self {
        // Default should not provide database URL - must come from environment
        Self {
            database_url: std::env::var("DATABASE_URL").unwrap_or_else(|_| String::new()), // Empty string if not set - will fail on use
            mcp_port: 3333,
            log_level: "info".to_string(),
        }
    }
}