Skip to main content
Glama

Convex MCP server

Official
by get-convex
virtual_table.rs3.96 kB
use std::{ collections::BTreeMap, sync::LazyLock, }; use common::{ document::{ DeveloperDocument, ParseDocument, ParsedDocument, ResolvedDocument, CREATION_TIME_FIELD, ID_FIELD, }, virtual_system_mapping::{ VirtualSystemDocMapper, VirtualSystemMapping, }, }; use semver::Version; use value::{ val, ConvexObject, ConvexValue, FieldName, TableMapping, }; use super::{ types::FileStorageEntry, FILE_STORAGE_TABLE, }; // First release of virtual tables static MIN_NPM_VERSION_FILE_STORAGE_V1: LazyLock<Version> = LazyLock::new(|| Version::parse("1.6.1").unwrap()); // sha256 of the file now uses base64 instead of hex for consistency static MIN_NPM_VERSION_FILE_STORAGE_V2: LazyLock<Version> = LazyLock::new(|| Version::parse("1.9.0").unwrap()); pub struct FileStorageDocMapper; impl VirtualSystemDocMapper for FileStorageDocMapper { fn system_to_virtual_doc( &self, virtual_system_mapping: &VirtualSystemMapping, doc: ResolvedDocument, table_mapping: &TableMapping, version: Version, ) -> anyhow::Result<DeveloperDocument> { // Note: in the future we may support different versions of our virtual table // APIs, which we determine based on the NPM client version let system_table_name = table_mapping.tablet_name(doc.id().tablet_id)?; if system_table_name == FILE_STORAGE_TABLE.clone() && version < *MIN_NPM_VERSION_FILE_STORAGE_V1 { anyhow::bail!("System document cannot be converted to a virtual document") } let metadata: ParsedDocument<FileStorageEntry> = doc.clone().parse()?; let metadata: FileStorageEntry = metadata.into_value(); let sha256 = if version >= *MIN_NPM_VERSION_FILE_STORAGE_V2 { metadata.sha256.as_base64() } else { metadata.sha256.as_hex() }; let public_metadata = PublicFileMetadata { sha256, size: metadata.size as f64, content_type: metadata.content_type, }; let mut public_metadata_resolved: ConvexObject = public_metadata.try_into()?; let virtual_developer_id = virtual_system_mapping.system_resolved_id_to_virtual_developer_id(doc.id())?; let mut fields: BTreeMap<_, _> = public_metadata_resolved.into(); fields.insert(ID_FIELD.to_owned().into(), virtual_developer_id.into()); fields.insert( CREATION_TIME_FIELD.to_owned().into(), ConvexValue::from(f64::from(doc.creation_time())), ); public_metadata_resolved = fields.try_into()?; let public_doc = DeveloperDocument::new( virtual_developer_id, doc.creation_time(), public_metadata_resolved, ); Ok(public_doc) } } #[derive(Clone, Debug, PartialEq)] #[cfg_attr(any(test, feature = "testing"), derive(proptest_derive::Arbitrary))] struct PublicFileMetadata { sha256: String, // Hex-encoded Sha256 of contents size: f64, // Size of file in storage content_type: Option<String>, // Optional ContentType header saved with file } impl TryFrom<PublicFileMetadata> for ConvexObject { type Error = anyhow::Error; fn try_from( PublicFileMetadata { sha256, size, content_type, }: PublicFileMetadata, ) -> Result<Self, Self::Error> { let mut obj: BTreeMap<FieldName, ConvexValue> = BTreeMap::new(); obj.insert("sha256".parse()?, sha256.try_into()?); obj.insert("size".parse()?, ConvexValue::Float64(size)); obj.insert( "contentType".parse()?, match content_type { None => val!(null), Some(ct) => val!(ct), }, ); ConvexObject::try_from(obj) } }

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