Skip to main content
Glama

Convex MCP server

Official
by get-convex
mod.rs4.14 kB
pub mod definition; pub mod handles; use std::collections::BTreeMap; use serde::{ Deserialize, Serialize, }; use value::{ codegen_convex_serialization, identifier::Identifier, DeveloperDocumentId, }; use crate::components::{ ComponentName, Resource, SerializedResource, }; #[derive(Debug, Clone, Eq, PartialEq)] #[cfg_attr(any(test, feature = "testing"), derive(proptest_derive::Arbitrary))] pub struct ComponentMetadata { pub definition_id: DeveloperDocumentId, pub component_type: ComponentType, pub state: ComponentState, } #[derive(Debug, Clone, Eq, PartialEq)] #[cfg_attr(any(test, feature = "testing"), derive(proptest_derive::Arbitrary))] pub enum ComponentState { /// The component is mounted and can be used. Active, /// The component is unmounted. Component functions are not available, and /// tables in the component are read-only. Unmounted, } impl ComponentMetadata { pub fn parent_and_name(&self) -> Option<(DeveloperDocumentId, ComponentName)> { match &self.component_type { ComponentType::App => None, ComponentType::ChildComponent { parent, name, .. } => Some((*parent, name.clone())), } } } #[derive(Debug, Clone, Eq, PartialEq)] #[cfg_attr(any(test, feature = "testing"), derive(proptest_derive::Arbitrary))] pub enum ComponentType { App, ChildComponent { parent: DeveloperDocumentId, name: ComponentName, args: BTreeMap<Identifier, Resource>, }, } impl ComponentType { pub fn is_root(&self) -> bool { matches!(self, ComponentType::App) } } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SerializedComponentMetadata { pub definition_id: String, pub parent: Option<String>, pub name: Option<String>, pub args: Option<Vec<(String, SerializedResource)>>, pub state: Option<String>, } impl TryFrom<ComponentMetadata> for SerializedComponentMetadata { type Error = anyhow::Error; fn try_from(m: ComponentMetadata) -> anyhow::Result<Self> { let (parent, name, args) = match m.component_type { ComponentType::App => (None, None, None), ComponentType::ChildComponent { parent, name, args } => ( Some(parent.to_string()), Some(name.to_string()), Some( args.into_iter() .map(|(k, v)| anyhow::Ok((k.to_string(), v.try_into()?))) .try_collect()?, ), ), }; let state = match m.state { ComponentState::Active => "active", ComponentState::Unmounted => "unmounted", }; Ok(Self { definition_id: m.definition_id.to_string(), parent, name, args, state: Some(state.to_string()), }) } } impl TryFrom<SerializedComponentMetadata> for ComponentMetadata { type Error = anyhow::Error; fn try_from(m: SerializedComponentMetadata) -> anyhow::Result<Self> { let component_type = match (m.parent, m.name, m.args) { (None, None, None) => ComponentType::App, (Some(parent), Some(name), Some(args)) => ComponentType::ChildComponent { parent: parent.parse()?, name: name.parse()?, args: args .into_iter() .map(|(k, v)| Ok((k.parse()?, v.try_into()?))) .collect::<anyhow::Result<_>>()?, }, _ => anyhow::bail!("Invalid component type"), }; let state = match m.state.as_deref() { None | Some("active") => ComponentState::Active, Some("unmounted") => ComponentState::Unmounted, Some(invalid_state) => anyhow::bail!("Invalid component state: {invalid_state}"), }; Ok(Self { definition_id: m.definition_id.parse()?, component_type, state, }) } } codegen_convex_serialization!(ComponentMetadata, SerializedComponentMetadata);

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