pub(crate) const MAX_STRING_ARG: usize = 1024;
pub(crate) fn parse_bounded_string(
arguments: &serde_json::Value,
field: &'static str,
) -> Result<String, crate::commands::mcp::error::McpError> {
use crate::commands::mcp::error::McpError;
let map = match arguments {
serde_json::Value::Object(m) => m,
serde_json::Value::Null => {
return Err(McpError::InvalidArgument {
message: "missing argument",
});
}
_ => {
return Err(McpError::InvalidArgument {
message: "arguments must be an object",
});
}
};
let value = map.get(field).ok_or(McpError::InvalidArgument {
message: "missing argument",
})?;
let s = match value {
serde_json::Value::String(s) => s.clone(),
_ => {
return Err(McpError::InvalidArgument {
message: "argument must be a string",
});
}
};
if s.len() > MAX_STRING_ARG {
return Err(McpError::ArgumentTooLarge {
field,
limit: MAX_STRING_ARG,
observed: s.len(),
});
}
Ok(s)
}
pub(crate) fn parse_optional_bounded_string(
arguments: &serde_json::Value,
field: &'static str,
) -> Result<Option<String>, crate::commands::mcp::error::McpError> {
use crate::commands::mcp::error::McpError;
let map = match arguments {
serde_json::Value::Object(m) => m,
serde_json::Value::Null => return Ok(None),
_ => {
return Err(McpError::InvalidArgument {
message: "arguments must be an object",
});
}
};
match map.get(field) {
None => Ok(None),
Some(serde_json::Value::String(s)) => {
if s.len() > MAX_STRING_ARG {
return Err(McpError::ArgumentTooLarge {
field,
limit: MAX_STRING_ARG,
observed: s.len(),
});
}
Ok(Some(s.clone()))
}
Some(_) => Err(McpError::InvalidArgument {
message: "argument must be a string",
}),
}
}