Skip to main content
Glama

Convex MCP server

Official
by get-convex
config.rs6.39 kB
use std::collections::BTreeMap; use url::Url; use crate::fivetran_sdk::{ form_field::Type, FormField, TextField, }; const CONFIG_KEY_DEPLOYMENT_URL: &str = "url"; const CONFIG_KEY_DEPLOYMENT_KEY: &str = "key"; /// The configuration parameters used by the connector, requested to users by /// the Fivetran UI. Users can obtain these values from the Convex dashboard in /// the deployment’s settings page. pub struct Config { /// The domain where the deployment is hosted (e.g. "https://aware-llama-900.convex.cloud"). pub deploy_url: Url, /// The key giving admin permissions to the deployment /// (e.g. "prod:aware-llama-900|016b26d3900d5e482f1780969c2fa608a773140fb221db21785a9b2775b50263da6a258301b6374ef72b4c120e237c20ac50") pub deploy_key: String, } impl Config { /// Layout of the fields visible in the Fivetran UI pub fn fivetran_fields() -> Vec<FormField> { vec![ FormField { name: CONFIG_KEY_DEPLOYMENT_URL.to_string(), label: "Deployment URL".to_string(), required: Some(true), description: Some( "The domain where the deployment is hosted. You can find it in the deployment \ settings page of the Convex dashboard." .to_string(), ), r#type: Some(Type::TextField(TextField::PlainText as i32)), default_value: None, placeholder: Some("https://aware-llama-900.convex.cloud".to_string()), }, FormField { name: CONFIG_KEY_DEPLOYMENT_KEY.to_string(), label: "Deploy Key".to_string(), required: Some(true), description: Some( "The key giving access to your deployment. You can find it in the deployment \ settings page of the Convex dashboard." .to_string(), ), r#type: Some(Type::TextField(TextField::Password as i32)), default_value: None, placeholder: None, }, ] } /// Validates user-supplied configuration parameters /// and creates a [`Config`] instance if they are valid. pub fn from_parameters(configuration: BTreeMap<String, String>) -> anyhow::Result<Self> { let Some(deploy_url) = configuration.get(CONFIG_KEY_DEPLOYMENT_URL) else { anyhow::bail!("Missing {CONFIG_KEY_DEPLOYMENT_URL}"); }; let Ok(deploy_url) = Url::parse(deploy_url) else { anyhow::bail!("Invalid {CONFIG_KEY_DEPLOYMENT_URL} (must be an URL)"); }; if deploy_url.host_str().is_none() { anyhow::bail!("Invalid deploy URL: must contain a host."); } if deploy_url.path() != "/" || deploy_url.query().is_some() || deploy_url.username() != "" || deploy_url.password().is_some() || deploy_url.fragment().is_some() || (deploy_url.scheme() != "http" && deploy_url.scheme() != "https") { anyhow::bail!("Invalid deploy URL: must be a root URL."); } let Some(deploy_key) = configuration.get(CONFIG_KEY_DEPLOYMENT_KEY) else { anyhow::bail!("Missing {CONFIG_KEY_DEPLOYMENT_KEY}"); }; Ok(Config { deploy_url, deploy_key: deploy_key.to_owned(), }) } } #[cfg(test)] mod tests { use maplit::btreemap; use super::*; const VALID_DEPLOY_KEY: &str = "prod:aware-llama-900|016b26d3900d5e482f1780969c2fa608a773140fb221db21785a9b2775b50263da6a258301b6374ef72b4c120e237c20ac50"; #[test] fn accepts_valid_parameters() { let api = Config::from_parameters(btreemap! { "url".to_string() => "https://aware-llama-900.convex.cloud".to_string(), "key".to_string() => VALID_DEPLOY_KEY.to_string(), }) .unwrap(); assert_eq!( api.deploy_url.to_string(), "https://aware-llama-900.convex.cloud/" ); assert_eq!(api.deploy_key, "prod:aware-llama-900|016b26d3900d5e482f1780969c2fa608a773140fb221db21785a9b2775b50263da6a258301b6374ef72b4c120e237c20ac50"); } #[test] fn accepts_valid_parameters_with_trailing_slash() { let api = Config::from_parameters(btreemap! { "url".to_string() => "https://aware-llama-900.convex.cloud/".to_string(), "key".to_string() => VALID_DEPLOY_KEY.to_string(), }) .unwrap(); assert_eq!( api.deploy_url.to_string(), "https://aware-llama-900.convex.cloud/" ); assert_eq!(api.deploy_key, "prod:aware-llama-900|016b26d3900d5e482f1780969c2fa608a773140fb221db21785a9b2775b50263da6a258301b6374ef72b4c120e237c20ac50"); } #[test] fn refuses_missing_deploy_url() { assert!(Config::from_parameters(btreemap! { "key".to_string() => VALID_DEPLOY_KEY.to_string(), },) .is_err()); } #[test] fn refuses_missing_deploy_key() { assert!(Config::from_parameters(btreemap! { "url".to_string() => "https://aware-llama-900.convex.cloud".to_string(), },) .is_err()); } #[test] fn refuses_invalid_urls() { for url in [ "aware lalama convex", "https://aware-llama-900.convex.cloud/api/", "https://aware-llama-900.convex.cloud?abc", "https://aware-llama-900.convex.cloud?abc=def", "https://root:hunter2@aware-llama-900.convex.cloud", "https://aware-llama-900.convex.cloud/#abc", "ftp://aware-llama-900.convex.cloud/", "/", ] { assert!( Config::from_parameters(btreemap! { "url".to_string() => url.to_string(), "key".to_string() => VALID_DEPLOY_KEY.to_string(), }) .is_err(), "{url} is not a valid deploy URL" ); } } #[test] fn accepts_non_convex_hosts() { assert!(Config::from_parameters(btreemap! { "url".to_string() => "http://localhost".to_string(), "key".to_string() => VALID_DEPLOY_KEY.to_string(), }) .is_ok()); } }

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