Skip to main content
Glama

Convex MCP server

Official
by get-convex
decoding.rs3.42 kB
//! Decoding configuration files into Rust types use std::{ collections::HashMap, marker::PhantomData, str::FromStr, }; use prost_reflect::{ prost::Message, DynamicMessage, MessageDescriptor, }; /// Trait representing the decoding of a config file's contents to a generic /// output type. pub trait ConfigDecoder: Clone { type Output: PartialEq + Clone + Send + Sync + 'static; fn decode(&self, contents: Vec<u8>) -> anyhow::Result<Self::Output>; } /// Simple decoder for getting the value of the config file as a UTF-8 string. #[derive(Copy, Clone)] pub struct TextDecoder; impl ConfigDecoder for TextDecoder { type Output = String; fn decode(&self, contents: Vec<u8>) -> anyhow::Result<String> { Ok(String::from_utf8(contents)?) } } #[derive(Copy, Clone)] pub struct DelimitedKeyValueDecoder<K, V> { delimiter: char, _marker: PhantomData<(K, V)>, } impl<K: FromStr, V: FromStr> DelimitedKeyValueDecoder<K, V> { pub fn new(delimiter: char) -> Self { Self { delimiter, _marker: PhantomData, } } } impl<K, V> ConfigDecoder for DelimitedKeyValueDecoder<K, V> where K: FromStr + Eq + std::hash::Hash + Clone + Send + Sync + 'static, V: FromStr + Eq + Clone + Send + Sync + 'static, <K as FromStr>::Err: std::error::Error + Send + Sync + 'static, <V as FromStr>::Err: std::error::Error + Send + Sync + 'static, { type Output = HashMap<K, V>; fn decode(&self, contents: Vec<u8>) -> anyhow::Result<Self::Output> { let contents = std::str::from_utf8(&contents)?; let mut map = HashMap::new(); for line in contents.lines() { let trimmed = line.trim(); if trimmed.is_empty() { continue; } let (key, value) = trimmed.split_once(self.delimiter).ok_or_else(|| { anyhow::anyhow!( "failed to find delimiter `{}` in line: `{}`", self.delimiter, line ) })?; map.insert(key.parse()?, value.parse()?); } Ok(map) } } /// No-op decoder for getting the raw bytes of the config file. #[derive(Copy, Clone)] pub struct BytesDecoder; impl ConfigDecoder for BytesDecoder { type Output = Vec<u8>; fn decode(&self, contents: Vec<u8>) -> anyhow::Result<Self::Output> { Ok(contents) } } pub trait ProstMessage = Message + Clone + Default + PartialEq + 'static; /// Decodes textproto format to a Prost message. You need the /// [`MessageDescriptor`] for the proto you intend to decode; this can be /// obtained from the `FILE_DESCRIPTOR_BYTES` constant in every generated /// protobuf crate. #[derive(Clone)] pub struct TextProtoDecoder<T: ProstMessage> { descriptor: MessageDescriptor, _type: PhantomData<T>, } impl<T: ProstMessage> TextProtoDecoder<T> { pub const fn new(descriptor: MessageDescriptor) -> Self { Self { descriptor, _type: PhantomData, } } } impl<T: ProstMessage> ConfigDecoder for TextProtoDecoder<T> { type Output = T; fn decode(&self, contents: Vec<u8>) -> anyhow::Result<T> { let contents = std::str::from_utf8(&contents)?; let message = DynamicMessage::parse_text_format(self.descriptor.clone(), contents)?; Ok(message.transcode_to()?) } }

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