Skip to main content
Glama

Convex MCP server

Official
by get-convex
config.rs8.3 kB
use std::fmt; use clap::Parser; use clusters::DbDriverTag; use common::types::{ ConvexOrigin, ConvexSite, }; use keybroker::{ InstanceSecret, KeyBroker, DEV_INSTANCE_NAME, DEV_SECRET, }; use metrics::SERVER_VERSION_STR; use model::database_globals::types::StorageTagInitializer; use serde_json::Value as JsonValue; use url::Url; #[derive(Parser, Clone)] #[clap(version = &**SERVER_VERSION_STR, author = "Convex, Inc. <no-reply@convex.dev>", group(clap::ArgGroup::new("storage").multiple(false)))] pub struct LocalConfig { /// File path for SQLite, the file path; for postgres, a server URL. #[clap(default_value = "convex_local_backend.sqlite3")] pub db_spec: String, /// Database driver type. #[clap(short, long, value_enum, default_value_t = DbDriverTag::Sqlite)] pub db: DbDriverTag, /// Host interface to bind to #[clap(short, long, default_value = "0.0.0.0")] pub interface: ::std::net::Ipv4Addr, /// Host port daemon should bind to #[clap(short, long, default_value = "3210")] pub port: u16, /// Host port to bind for Convex HTTP Actions #[clap(long, default_value = "3211")] site_proxy_port: u16, /// Origin of the Convex server, as accessible from the client. /// e.g. if the client is running on localhost, you can use the default of /// http://127.0.0.1:${port}. /// Otherwise, if the client is accessing the backend from the public /// internet, this would be the public URL of the backend, like /// https://api.my-app.com . /// Note the port in this url (usually 443, the https default) need not /// match the bind port `--port`. #[clap(long, requires = "convex_site")] convex_origin: Option<ConvexOrigin>, /// Origin of the Convex HTTP Actions, as accessible from the client. /// e.g. if the client is running on localhost, you can use the default of /// http://127.0.0.1:${site_proxy_port}. /// Otherwise, if the client is accessing the backend from the public /// internet, this would be the public URL of the backend, like /// https://my-app.com . /// Note the port in this url (usually 443, the https default) need not /// match the bind port `--site-proxy-port`. /// If you don't have a separate URL for HTTP Actions, you can use /// value from `--convex-origin` with a "/http" suffix, like /// https://api.my-app.com/http . #[clap(long, requires = "convex_origin")] convex_site: Option<ConvexSite>, /// Optional proxy for Actions fetches /// /// i.e. if doing `await fetch(request)` within an action, you can /// send the request through this proxy to screen it for SSRF attacks. #[clap(long)] pub convex_http_proxy: Option<Url>, /// Instance name for this backend. #[clap(long, requires = "instance_secret")] pub instance_name: Option<String>, /// Instance secret for this backend. #[clap(long, requires = "instance_name")] pub instance_secret: Option<String>, /// Identifier (like a user ID) to attach to any sentry /// events generated by this backend. Sentry is disabled /// by default. #[clap(long, hide = true)] pub sentry_identifier: Option<String>, /// Which directory should file storage use #[clap(long, group = "storage", default_value = "convex_local_storage")] local_storage: String, /// Use S3 storage instead of local storage. #[clap(long, group = "storage")] pub s3_storage: bool, /// If set, the persistence won't require SSL when talking to the database. /// It would still prefer SSL if available. This should only be set in /// tests. #[clap(long)] pub do_not_require_ssl: bool, /// self-hosted Convex will periodically communicate with a remote beacon /// server. This is to help Convex understand and improve the product. /// If set, the self-host beacon will not be sent. #[clap(long, env = "DISABLE_BEACON", value_parser = clap::builder::BoolishValueParser::new())] pub disable_beacon: bool, /// A tag to identify the self-hosted instance. #[clap(long, hide = true, default_value = "self-host")] pub beacon_tag: String, /// Extra fields to send to the beacon. #[clap(long, hide = true)] pub beacon_fields: Option<JsonValue>, /// If set, logs will be redacted from clients. Set this on production /// deployments, to prevent information like stacktraces of serverside /// code from being leaked to clients. /// /// On development deployments, it can be helpful to have this information /// reach the client for debugging purposes. #[clap(long, default_value = "false")] pub redact_logs_to_client: bool, /// Path of local file for logs to be routed to. For local testing /// of log integrations (eg axiom/datadog). #[clap(long)] pub local_log_sink: Option<String>, } impl fmt::Debug for LocalConfig { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Config") .field("convex_origin", &self.convex_origin) .field("convex_site", &self.convex_site) .field("instance_name", &self.instance_name) .finish() } } impl LocalConfig { pub fn http_bind_address(&self) -> ([u8; 4], u16) { (self.interface.octets(), self.port) } pub fn site_forward_prefix(&self) -> String { format!("http://127.0.0.1:{}/http", self.port) } pub fn site_bind_address(&self) -> Option<([u8; 4], u16)> { Some((self.interface.octets(), self.site_proxy_port)) } pub fn convex_origin_url(&self) -> anyhow::Result<ConvexOrigin> { let origin = self .convex_origin .clone() .unwrap_or(format!("http://127.0.0.1:{}", self.port).into()); // Allow empty origin so you can start up a self-hosted backend without // knowing its url yet. if !origin.is_empty() && !origin.starts_with("https://") && !origin.starts_with("http://") { anyhow::bail!( "Origin url should start with https:// or http:// but got '{}'", origin ); } Ok(origin) } pub fn convex_site_url(&self) -> anyhow::Result<ConvexSite> { let site = self .convex_site .clone() .unwrap_or(format!("http://127.0.0.1:{}", self.site_proxy_port).into()); // Allow empty site so you can start up a self-hosted backend without // knowing its url yet. if !site.is_empty() && !site.starts_with("https://") && !site.starts_with("http://") { anyhow::bail!( "Site url should start with https:// or http:// but got '{}'", site ); } Ok(site) } pub fn name(&self) -> String { self.instance_name .clone() .unwrap_or(DEV_INSTANCE_NAME.to_owned()) } pub fn key_broker(&self) -> anyhow::Result<KeyBroker> { let name = self.name(); KeyBroker::new(&name, self.secret()?) } pub fn secret(&self) -> anyhow::Result<InstanceSecret> { InstanceSecret::try_from( self.instance_secret .clone() .unwrap_or(DEV_SECRET.to_owned()) .as_str(), ) } pub fn storage_tag_initializer(&self) -> StorageTagInitializer { if self.s3_storage { StorageTagInitializer::S3 } else { StorageTagInitializer::Local { dir: self.local_storage.clone().into(), } } } #[cfg(test)] pub fn new_for_test() -> anyhow::Result<Self> { use anyhow::Context; let tempdir_handle = tempfile::tempdir()?; let db_path = tempdir_handle.path().join("convex_local_backend.sqlite3"); // Easiest way to get a config object with defaults is to parse from cmd line let config = Self::try_parse_from([ "convex-local-backend", db_path.to_str().context("invalid db path")?, "--local-storage", tempdir_handle .path() .to_str() .context("invalid local storage path")?, ])?; Ok(config) } }

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