test(mcp): from_mcp wraps non-object tool arguments as {"value": …} (COV-12 review-002)
Wire-level round trip through the real rmcp server: a scalar input
reaches the remote tool as {"value": <input>}, matching the
value_to_json_object wrap.
This commit is contained in:
@@ -420,6 +420,37 @@ async fn import_refuses_tool_name_containing_slash() {
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn forwarding_handler_wraps_non_object_input_as_value_field() {
|
||||
// A scalar/array tool argument cannot be a JSON object on the MCP
|
||||
// wire; the adapter wraps it as {"value": <input>} (review-002
|
||||
// from_mcp :460-468 arm). Proven over the real rmcp round trip: the
|
||||
// echo server reflects the arguments object back.
|
||||
let (endpoint, _handle) = spawn_server().await;
|
||||
let adapter = FromMCP::new(endpoint, "echo");
|
||||
let bundles = adapter.import().await.expect("import succeeds");
|
||||
let echo = bundles
|
||||
.into_iter()
|
||||
.find(|b| b.spec.name == "echo/echo")
|
||||
.expect("echo tool present");
|
||||
|
||||
let ctx = test_context("req-wrap", Capabilities::new());
|
||||
let response = match &echo.handler {
|
||||
HandlerKind::Once(h) => h(serde_json::json!("bare-scalar"), ctx).await,
|
||||
HandlerKind::Stream(_) | HandlerKind::Sink(_) => panic!("expected Once handler"),
|
||||
};
|
||||
match response.result {
|
||||
Ok(Value::Object(obj)) => {
|
||||
assert_eq!(
|
||||
obj.get("echoed"),
|
||||
Some(&serde_json::json!({ "value": "bare-scalar" })),
|
||||
"non-object input must reach the wire as {{\"value\": …}}: got {obj:?}"
|
||||
);
|
||||
}
|
||||
other => panic!("expected object structured content, got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn forwarding_handler_maps_json_rpc_tool_error_with_code_fidelity() {
|
||||
// A server whose `call_tool` returns a JSON-RPC error (rmcp
|
||||
|
||||
Reference in New Issue
Block a user