Skip to main content
Glama

Convex MCP server

Official
by get-convex
env.rs4.59 kB
use std::{ env, fmt::Debug, fs::File, io, str::FromStr, sync::LazyLock, }; use sentry_tracing::EventFilter; use tracing::Level; use tracing_subscriber::{ fmt::{ format::format, MakeWriter, }, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, }; pub fn env_config<T>(name: &str, default: T) -> T where T: Debug + FromStr + PartialEq, <T as FromStr>::Err: Debug, { let var_s = match env::var(name) { Ok(s) => s, Err(env::VarError::NotPresent) => return default, Err(env::VarError::NotUnicode(..)) => { tracing::warn!("Invalid value for {name}, falling back to {default:?}."); return default; }, }; match T::from_str(&var_s) { Ok(v) => { if v != default { tracing::info!("Overriding {name} to {v:?} from environment"); } v }, Err(e) => { tracing::warn!("Invalid value {var_s} for {name}, falling back to {default:?}: {e:?}"); default }, } } pub static CONVEX_TRACE_FILE: LazyLock<Option<File>> = LazyLock::new(|| { if env::var("CONVEX_TRACE_FILE").is_err() { return None; } let exe_path = std::env::current_exe().expect("Couldn't find exe name"); let exe_name = exe_path .file_name() .expect("Path was empty") .to_str() .expect("Not valid unicode"); // e.g. `backend.log` let filename = format!("{exe_name}.log"); let file = File::create(&filename).unwrap_or_else(|_| panic!("Could not create file {filename}")); Some(file) }); /// Guard object. Hold onto it for as long as you'd like to keep tracing to a /// file specified by `CONVEX_TRACE_FILE` pub struct TracingGuard { _guard: Option<tracing_appender::non_blocking::WorkerGuard>, } /// Call this from scripts at startup. pub fn config_tool() -> TracingGuard { config_tracing(io::stderr, Level::ERROR) } /// Call this from services at startup. pub fn config_service() -> TracingGuard { config_tracing(io::stdout, Level::INFO) } fn config_tracing<W>(writer: W, level: Level) -> TracingGuard where W: Send + Sync + for<'writer> MakeWriter<'writer> + 'static, { let mut layers = Vec::new(); let color_disabled = std::env::var("NO_COLOR").is_ok(); let format_layer = tracing_subscriber::fmt::layer() .with_ansi(!color_disabled) .with_writer(writer); let format_layer = match std::env::var("LOG_FORMAT") { Ok(s) if s == "json" => format_layer.event_format(format().json()).boxed(), Ok(s) if s == "compact" => format_layer.event_format(format().compact()).boxed(), Ok(s) if s == "pretty" => format_layer.event_format(format().pretty()).boxed(), _ => format_layer.event_format(format().compact()).boxed(), }; let format_layer = format_layer .with_filter( tracing_subscriber::EnvFilter::try_from_default_env() .unwrap_or(EnvFilter::new(level.as_str())), ) .boxed(); layers.push(format_layer); let sentry_layer = sentry_tracing::layer() .event_filter(|md| match md.level() { &tracing::Level::DEBUG | &tracing::Level::TRACE => EventFilter::Ignore, _ => EventFilter::Breadcrumb, }) .span_filter(|_md| false); layers.push(sentry_layer.boxed()); let guard = if let Some(ref file) = *CONVEX_TRACE_FILE { let (file_writer, guard) = tracing_appender::non_blocking(file); let file_writer_layer = tracing_subscriber::fmt::layer() .with_writer(file_writer) .with_filter( EnvFilter::from_default_env() .add_directive(Level::INFO.into()) .add_directive("common::errors=debug".parse().unwrap()), ) .boxed(); layers.push(file_writer_layer); Some(guard) } else { None }; tracing_subscriber::registry().with(layers).init(); TracingGuard { _guard: guard } } pub fn config_test() { // Try to initialize tracing_subcriber. Ok if it fails - probably // means it was initialized already. Ok to be non-rigorous here, because // it's very hard to run initialization of logging in tests, so we tend to // toss it in common helper methods all over. let _ = tracing_subscriber::fmt() .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) .with_test_writer() .compact() .try_init(); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/get-convex/convex-backend'

If you have feedback or need assistance with the MCP directory API, please join our Discord server