Skip to content

Commit 4dcb918

Browse files
committed
feat!: relax tool result structuredContent type
1 parent 7793214 commit 4dcb918

6 files changed

Lines changed: 38 additions & 30 deletions

File tree

crates/rmcp/src/model/content.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
//! variants for sampling messages (SEP-1577).
99
1010
use serde::{Deserialize, Serialize};
11-
use serde_json::json;
11+
use serde_json::{Value, json};
1212

1313
use super::{Annotations, Meta, resource::ResourceContents};
1414

@@ -197,7 +197,7 @@ pub struct ToolResultContent {
197197
pub tool_use_id: String,
198198
pub content: Vec<ContentBlock>,
199199
#[serde(skip_serializing_if = "Option::is_none")]
200-
pub structured_content: Option<super::JsonObject>,
200+
pub structured_content: Option<Value>,
201201
#[serde(skip_serializing_if = "Option::is_none")]
202202
pub is_error: Option<bool>,
203203
}

crates/rmcp/tests/test_message_schema/client_json_rpc_message_schema.json

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,13 +2346,7 @@
23462346
"null"
23472347
]
23482348
},
2349-
"structuredContent": {
2350-
"type": [
2351-
"object",
2352-
"null"
2353-
],
2354-
"additionalProperties": true
2355-
},
2349+
"structuredContent": true,
23562350
"toolUseId": {
23572351
"type": "string"
23582352
}

crates/rmcp/tests/test_message_schema/client_json_rpc_message_schema_current.json

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,13 +2346,7 @@
23462346
"null"
23472347
]
23482348
},
2349-
"structuredContent": {
2350-
"type": [
2351-
"object",
2352-
"null"
2353-
],
2354-
"additionalProperties": true
2355-
},
2349+
"structuredContent": true,
23562350
"toolUseId": {
23572351
"type": "string"
23582352
}

crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema.json

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3446,13 +3446,7 @@
34463446
"null"
34473447
]
34483448
},
3449-
"structuredContent": {
3450-
"type": [
3451-
"object",
3452-
"null"
3453-
],
3454-
"additionalProperties": true
3455-
},
3449+
"structuredContent": true,
34563450
"toolUseId": {
34573451
"type": "string"
34583452
}

crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema_current.json

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3446,13 +3446,7 @@
34463446
"null"
34473447
]
34483448
},
3449-
"structuredContent": {
3450-
"type": [
3451-
"object",
3452-
"null"
3453-
],
3454-
"additionalProperties": true
3455-
},
3449+
"structuredContent": true,
34563450
"toolUseId": {
34573451
"type": "string"
34583452
}

crates/rmcp/tests/test_sampling.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,38 @@ fn test_tool_result_content_requires_content() {
370370
assert!(err.to_string().contains("missing field `content`"));
371371
}
372372

373+
#[tokio::test]
374+
async fn test_tool_result_content_with_array_structured_content() -> Result<()> {
375+
let structured =
376+
serde_json::json!([{ "city": "SF", "temp": 72 }, { "city": "NY", "temp": 65 }]);
377+
let mut tool_result = ToolResultContent::new("call_123", vec![ContentBlock::text("forecast")]);
378+
tool_result.structured_content = Some(structured);
379+
380+
let json = serde_json::to_string(&tool_result)?;
381+
let deserialized: ToolResultContent = serde_json::from_str(&json)?;
382+
assert_eq!(tool_result, deserialized);
383+
assert!(deserialized.structured_content.unwrap().is_array());
384+
385+
Ok(())
386+
}
387+
388+
#[tokio::test]
389+
async fn test_tool_result_content_with_primitive_structured_content() -> Result<()> {
390+
let structured = serde_json::json!(42);
391+
let mut tool_result = ToolResultContent::new("call_123", vec![ContentBlock::text("count")]);
392+
tool_result.structured_content = Some(structured);
393+
394+
let json = serde_json::to_string(&tool_result)?;
395+
let deserialized: ToolResultContent = serde_json::from_str(&json)?;
396+
assert_eq!(tool_result, deserialized);
397+
assert!(matches!(
398+
deserialized.structured_content,
399+
Some(serde_json::Value::Number(_))
400+
));
401+
402+
Ok(())
403+
}
404+
373405
#[tokio::test]
374406
async fn test_sampling_message_with_tool_use() -> Result<()> {
375407
let message = SamplingMessage::assistant_tool_use(

0 commit comments

Comments
 (0)