use rmcp::model::ErrorData as McpError;
pub(super) fn default_strict_true() -> bool {
true
}
pub(super) const MAX_CONTENT_BYTES: usize = 10 * 1024 * 1024;
pub(super) const MAX_PARAM_BYTES: usize = 1024 * 1024;
pub(super) const MAX_BATCH_FILES: usize = 1000;
pub(super) const MAX_JSON_DEPTH: usize = 64;
pub(super) fn validate_size(field: &str, value: &str, max_bytes: usize) -> Result<(), McpError> {
if value.len() > max_bytes {
return Err(McpError::invalid_params(
format!(
"{field} exceeds maximum size ({} bytes, limit {max_bytes})",
value.len(),
),
None,
));
}
Ok(())
}
pub(super) fn validate_content_size(field: &str, value: &str) -> Result<(), McpError> {
validate_size(field, value, MAX_CONTENT_BYTES)
}
pub(super) fn validate_param_size(field: &str, value: &str) -> Result<(), McpError> {
validate_size(field, value, MAX_PARAM_BYTES)
}
pub(super) fn validate_json_depth(field: &str, value: &serde_json::Value) -> Result<(), McpError> {
fn measure(v: &serde_json::Value) -> usize {
match v {
serde_json::Value::Array(arr) => 1 + arr.iter().map(measure).max().unwrap_or(0),
serde_json::Value::Object(obj) => 1 + obj.values().map(measure).max().unwrap_or(0),
_ => 0,
}
}
let depth = measure(value);
if depth > MAX_JSON_DEPTH {
return Err(McpError::invalid_params(
format!("{field} exceeds maximum nesting depth ({depth}, limit {MAX_JSON_DEPTH})"),
None,
));
}
Ok(())
}
pub(super) fn validate_batch_size(field: &str, count: usize) -> Result<(), McpError> {
if count > MAX_BATCH_FILES {
return Err(McpError::invalid_params(
format!("{field} exceeds maximum batch size ({count}, limit {MAX_BATCH_FILES})"),
None,
));
}
Ok(())
}