test(mcp): schema/batch missing-argument INVALID_INPUT arms (COV-12 review-002)
schema tool with None arguments and batch tool without a calls array both return INVALID_INPUT naming the required field, without dispatching.
This commit is contained in:
@@ -1106,6 +1106,73 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn schema_tool_without_arguments_is_invalid_input() {
|
||||||
|
let registry = full_registry_with_ops(vec![(
|
||||||
|
"fs/readFile".to_string(),
|
||||||
|
OperationType::Query,
|
||||||
|
AccessControl::default(),
|
||||||
|
)]);
|
||||||
|
let gateway = ToMcpGateway::new(dispatch(registry));
|
||||||
|
|
||||||
|
let result = invoke_tool(&gateway, "schema", None, None).await;
|
||||||
|
assert_eq!(result.is_error, Some(true));
|
||||||
|
let structured = result.structured_content.expect("structured error present");
|
||||||
|
assert_eq!(
|
||||||
|
structured.get("code"),
|
||||||
|
Some(&Value::String("INVALID_INPUT".to_string()))
|
||||||
|
);
|
||||||
|
let message = structured
|
||||||
|
.get("message")
|
||||||
|
.and_then(Value::as_str)
|
||||||
|
.expect("message");
|
||||||
|
assert!(
|
||||||
|
message.contains("`name` is required"),
|
||||||
|
"missing tool arguments must name the required field: {message}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn batch_tool_without_calls_argument_is_invalid_input_without_dispatching() {
|
||||||
|
let registry = full_registry_with_ops(vec![(
|
||||||
|
"echo/run".to_string(),
|
||||||
|
OperationType::Query,
|
||||||
|
AccessControl::default(),
|
||||||
|
)]);
|
||||||
|
let gateway = ToMcpGateway::new(dispatch(registry));
|
||||||
|
|
||||||
|
let none_args = invoke_tool(&gateway, "batch", None, None).await;
|
||||||
|
assert_eq!(none_args.is_error, Some(true));
|
||||||
|
let structured = none_args
|
||||||
|
.structured_content
|
||||||
|
.expect("structured error present");
|
||||||
|
assert_eq!(
|
||||||
|
structured.get("code"),
|
||||||
|
Some(&Value::String("INVALID_INPUT".to_string()))
|
||||||
|
);
|
||||||
|
assert_eq!(structured.get("retryable"), Some(&Value::Bool(false)));
|
||||||
|
let message = structured
|
||||||
|
.get("message")
|
||||||
|
.and_then(Value::as_str)
|
||||||
|
.expect("message");
|
||||||
|
assert!(
|
||||||
|
message.contains("`calls` is required"),
|
||||||
|
"missing batch arguments must name the required field: {message}"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut args = Map::new();
|
||||||
|
args.insert("calls".to_string(), Value::String("nope".to_string()));
|
||||||
|
let non_array = invoke_tool(&gateway, "batch", Some(args), None).await;
|
||||||
|
assert_eq!(non_array.is_error, Some(true));
|
||||||
|
let structured = non_array
|
||||||
|
.structured_content
|
||||||
|
.expect("structured error present");
|
||||||
|
assert_eq!(
|
||||||
|
structured.get("code"),
|
||||||
|
Some(&Value::String("INVALID_INPUT".to_string()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn call_returns_structured_error_for_call_error() {
|
async fn call_returns_structured_error_for_call_error() {
|
||||||
let registry = full_registry_with_ops(vec![]);
|
let registry = full_registry_with_ops(vec![]);
|
||||||
|
|||||||
Reference in New Issue
Block a user