Skip to main content
Glama

Convex MCP server

Official
by get-convex
mod.rs3.81 kB
pub mod module_loader; pub mod permit; mod promise; pub mod syscall_error; mod version; use std::ops::Deref; use anyhow::Context; use deno_core::{ serde_v8, v8, }; use errors::{ ErrorCode, ErrorMetadata, }; use serde_json::Value as JsonValue; use value::TableName; pub use self::{ promise::{ resolve_promise, resolve_promise_allow_all_errors, }, version::parse_version, }; pub const MAX_LOG_LINE_LENGTH: usize = 32768; pub const MAX_LOG_LINES: usize = 256; #[derive(Debug, derive_more::Display)] pub struct ArgName(pub &'static str); pub fn with_argument_error<T>( name: &str, f: impl FnOnce() -> anyhow::Result<T>, ) -> anyhow::Result<T> { f().map_err(|e| { anyhow::anyhow!(ErrorMetadata::bad_request( "InvalidArgument", if let Some(ArgName(arg_name)) = e.downcast_ref() { if let Some(cause) = e.chain().nth(1) { format!("Invalid argument `{arg_name}` for `{name}`: {cause}") } else { format!("Invalid argument `{arg_name}` for `{name}`: {e}") } } else { format!("Invalid arguments for `{name}`: {e}") } )) }) } #[derive(Eq, PartialEq, Debug)] pub enum Phase { Importing, Executing, } pub fn json_to_v8<'a>( scope: &mut v8::HandleScope<'a>, json: JsonValue, ) -> anyhow::Result<v8::Local<'a, v8::Value>> { let value_v8 = serde_v8::to_v8(scope, json)?; Ok(value_v8) } /// Convert `RejectedBeforeExecution` error codes into `Overloaded`. /// This is useful when calling nested UDFs as the code would otherwise leak out /// of the _parent_ UDF, causing its caller to mistakenly believe the parent /// call to be retriable. pub fn remove_rejected_before_execution(mut e: anyhow::Error) -> anyhow::Error { if let Some(em) = e.downcast_mut::<ErrorMetadata>() && em.code == ErrorCode::RejectedBeforeExecution { em.code = ErrorCode::Overloaded; } e } /// For DB syscalls that take an explicit table name, checks that the /// explicit table name that the user used (`requested_table_name`) /// matches the name of the ID’s table (`actual_name_name`). pub fn check_table_name( requested_table_name: &Option<String>, actual_table_name: &TableName, ) -> anyhow::Result<()> { if let Some(requested_table_name) = requested_table_name { if requested_table_name != actual_table_name.deref() { return Err(ErrorMetadata::bad_request( "InvalidTable", format!( "expected to be an Id<\"{}\">, got Id<\"{}\"> instead.", requested_table_name, actual_table_name.deref() ), )) .context(ArgName("id")); } } Ok(()) } #[cfg(test)] mod tests { use super::*; #[test] fn test_check_table_name_accepts_the_correct_name() { let requested_table_name = Some("documents".to_string()); let actual_table_name: TableName = "documents".parse().unwrap(); assert!(check_table_name(&requested_table_name, &actual_table_name).is_ok()); } #[test] fn test_check_table_name_rejects_oher_names() { let requested_table_name = Some("documents".to_string()); let actual_table_name: TableName = "users".parse().unwrap(); assert!(check_table_name(&requested_table_name, &actual_table_name).is_err()); } #[test] fn test_check_table_name_does_nothing_if_the_requested_table_name_is_none() { let requested_table_name = None; let actual_table_name: TableName = "documents".parse().unwrap(); assert!(check_table_name(&requested_table_name, &actual_table_name).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