Skip to main content
Glama

Convex MCP server

Official
by get-convex
component_definition_path.rs4.28 kB
use std::{ ops::Deref, path::{ Component as PathComponent, PathBuf, }, str::FromStr, }; use anyhow::Context; // Path relative to a project's `convex/` directory for each component // definition's folder. This path is project-level and originates from // a developer's source code. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct ComponentDefinitionPath { path: PathBuf, } impl ComponentDefinitionPath { pub fn min() -> Self { ComponentDefinitionPath { path: PathBuf::new(), } } pub fn root() -> Self { ComponentDefinitionPath { path: PathBuf::new(), } } pub fn is_root(&self) -> bool { self.path.as_os_str().is_empty() } } // Windows has a maximum path limit of 260 (UTF-16) codepoints, which then is at // most 260 * 4 = 1040 bytes, which is then at most 1387 bytes encoded as // base64. Since we encode component definition paths as base64 within our // esbuild plugin, permit up to 2048 bytes here to be safe. const MAX_DEFINITION_PATH_COMPONENT_LEN: usize = 2048; fn check_valid_definition_path_component(s: &str) -> anyhow::Result<()> { if s.len() > MAX_DEFINITION_PATH_COMPONENT_LEN { anyhow::bail!( "Path component is too long ({} > maximum {}): {}...", s.len(), MAX_DEFINITION_PATH_COMPONENT_LEN, &s[..s.len().min(32)] ); } if s.is_empty() { anyhow::bail!("Path component is empty"); } if !s .chars() .all(|c| c.is_ascii() && !c.is_ascii_control() && c != '/' && c != '\\') { anyhow::bail!("Path component {s} can only include non-control ASCII characters."); } Ok(()) } impl FromStr for ComponentDefinitionPath { type Err = anyhow::Error; fn from_str(s: &str) -> Result<Self, Self::Err> { let path = PathBuf::from(s); for component in path.components() { match component { PathComponent::Normal(c) => { let s = c .to_str() .with_context(|| format!("Path {s} has an invalid Unicode character"))?; check_valid_definition_path_component(s)?; }, // Component paths are allowed to have `..` (since they're relative from the root // component's source directory). PathComponent::ParentDir => (), PathComponent::RootDir => { anyhow::bail!("Component paths must be relative ({s} is absolute).") }, c => anyhow::bail!("Invalid path component {c:?} in {s}."), } } path.as_os_str() .to_str() .with_context(|| format!("Path {s} has an invalid Unicode character"))?; Ok(ComponentDefinitionPath { path }) } } impl Deref for ComponentDefinitionPath { type Target = str; fn deref(&self) -> &Self::Target { self.path .as_os_str() .to_str() .expect("Invalid Unicode in ComponentDefinitionPath") } } impl From<ComponentDefinitionPath> for String { fn from(value: ComponentDefinitionPath) -> Self { value .path .into_os_string() .into_string() .expect("Invalid Unicode in ComponentDefinitionPath?") } } #[cfg(any(test, feature = "testing"))] impl proptest::arbitrary::Arbitrary for ComponentDefinitionPath { type Parameters = (); type Strategy = impl proptest::strategy::Strategy<Value = ComponentDefinitionPath>; fn arbitrary_with((): Self::Parameters) -> Self::Strategy { use proptest::prelude::*; ( 0..=4, prop::collection::vec(any::<super::ComponentName>(), 0..=4), ) .prop_map(|(depth, components)| { let mut path = String::new(); for _ in 0..depth { path.push_str("../"); } for component in components { path.push_str(&component); path.push('/'); } path.parse().unwrap() }) .boxed() } }

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