From 8f0a9e2a7fde1bf89a04cc693774b39701c9b185 Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+DaleSeo@users.noreply.github.com> Date: Fri, 26 Jun 2026 15:06:47 -0400 Subject: [PATCH] Revert "feat!: relax tool result structuredContent type (#919)" This reverts commit b8a936c4f529d0ce4a8680a41a213792c7786b70. --- crates/rmcp/src/model/content.rs | 4 +-- .../client_json_rpc_message_schema.json | 8 ++++- ...lient_json_rpc_message_schema_current.json | 8 ++++- .../server_json_rpc_message_schema.json | 8 ++++- ...erver_json_rpc_message_schema_current.json | 8 ++++- crates/rmcp/tests/test_sampling.rs | 32 ------------------- 6 files changed, 30 insertions(+), 38 deletions(-) diff --git a/crates/rmcp/src/model/content.rs b/crates/rmcp/src/model/content.rs index cd98f96c..680136f8 100644 --- a/crates/rmcp/src/model/content.rs +++ b/crates/rmcp/src/model/content.rs @@ -10,7 +10,7 @@ // ToolUseContent/ToolResultContent are SEP-2577-deprecated; internal references are expected. #![expect(deprecated)] use serde::{Deserialize, Serialize}; -use serde_json::{Value, json}; +use serde_json::json; use super::{Annotations, Meta, resource::ResourceContents}; @@ -207,7 +207,7 @@ pub struct ToolResultContent { pub tool_use_id: String, pub content: Vec, #[serde(skip_serializing_if = "Option::is_none")] - pub structured_content: Option, + pub structured_content: Option, #[serde(skip_serializing_if = "Option::is_none")] pub is_error: Option, } diff --git a/crates/rmcp/tests/test_message_schema/client_json_rpc_message_schema.json b/crates/rmcp/tests/test_message_schema/client_json_rpc_message_schema.json index 1108254b..3bfdb7c4 100644 --- a/crates/rmcp/tests/test_message_schema/client_json_rpc_message_schema.json +++ b/crates/rmcp/tests/test_message_schema/client_json_rpc_message_schema.json @@ -2352,7 +2352,13 @@ "null" ] }, - "structuredContent": true, + "structuredContent": { + "type": [ + "object", + "null" + ], + "additionalProperties": true + }, "toolUseId": { "type": "string" } diff --git a/crates/rmcp/tests/test_message_schema/client_json_rpc_message_schema_current.json b/crates/rmcp/tests/test_message_schema/client_json_rpc_message_schema_current.json index 1108254b..3bfdb7c4 100644 --- a/crates/rmcp/tests/test_message_schema/client_json_rpc_message_schema_current.json +++ b/crates/rmcp/tests/test_message_schema/client_json_rpc_message_schema_current.json @@ -2352,7 +2352,13 @@ "null" ] }, - "structuredContent": true, + "structuredContent": { + "type": [ + "object", + "null" + ], + "additionalProperties": true + }, "toolUseId": { "type": "string" } diff --git a/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema.json b/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema.json index c002b180..fcf821f5 100644 --- a/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema.json +++ b/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema.json @@ -3454,7 +3454,13 @@ "null" ] }, - "structuredContent": true, + "structuredContent": { + "type": [ + "object", + "null" + ], + "additionalProperties": true + }, "toolUseId": { "type": "string" } diff --git a/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema_current.json b/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema_current.json index c002b180..fcf821f5 100644 --- a/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema_current.json +++ b/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema_current.json @@ -3454,7 +3454,13 @@ "null" ] }, - "structuredContent": true, + "structuredContent": { + "type": [ + "object", + "null" + ], + "additionalProperties": true + }, "toolUseId": { "type": "string" } diff --git a/crates/rmcp/tests/test_sampling.rs b/crates/rmcp/tests/test_sampling.rs index b1c1710b..83d3f6fb 100644 --- a/crates/rmcp/tests/test_sampling.rs +++ b/crates/rmcp/tests/test_sampling.rs @@ -370,38 +370,6 @@ fn test_tool_result_content_requires_content() { assert!(err.to_string().contains("missing field `content`")); } -#[tokio::test] -async fn test_tool_result_content_with_array_structured_content() -> Result<()> { - let structured = - serde_json::json!([{ "city": "SF", "temp": 72 }, { "city": "NY", "temp": 65 }]); - let mut tool_result = ToolResultContent::new("call_123", vec![ContentBlock::text("forecast")]); - tool_result.structured_content = Some(structured); - - let json = serde_json::to_string(&tool_result)?; - let deserialized: ToolResultContent = serde_json::from_str(&json)?; - assert_eq!(tool_result, deserialized); - assert!(deserialized.structured_content.unwrap().is_array()); - - Ok(()) -} - -#[tokio::test] -async fn test_tool_result_content_with_primitive_structured_content() -> Result<()> { - let structured = serde_json::json!(42); - let mut tool_result = ToolResultContent::new("call_123", vec![ContentBlock::text("count")]); - tool_result.structured_content = Some(structured); - - let json = serde_json::to_string(&tool_result)?; - let deserialized: ToolResultContent = serde_json::from_str(&json)?; - assert_eq!(tool_result, deserialized); - assert!(matches!( - deserialized.structured_content, - Some(serde_json::Value::Number(_)) - )); - - Ok(()) -} - #[tokio::test] async fn test_sampling_message_with_tool_use() -> Result<()> { let message = SamplingMessage::assistant_tool_use(