feat(rmcp): add optional _meta to CallToolResult, EmbeddedResource, and ResourceContents (#386)

* feat(rmcp): support optional _meta on EmbeddedResource and ResourceContents

- Add optional _meta to RawEmbeddedResource and ResourceContents (text/blob)
- Update constructors/usages to set meta: None by default
- Add tests to lock behavior (embedded text/blob + CallToolResult)
- Update JSON Schemas to include optional _meta fields

* style(rmcp): rustfmt after _meta changes and tests
This commit is contained in:
Andrew Harvard 2025-09-02 13:47:09 -04:00 • committed by GitHub
commit 7d46b39b49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1267,6 +1267,9 @@ pub struct CallToolResult {
/// Whether this result represents an error condition
#[serde(skip_serializing_if = "Option::is_none")]
pub is_error: Option<bool>,
/// Optional protocol-level metadata for this result
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
pub meta: Option<Meta>,
}
impl CallToolResult {
@ -1276,6 +1279,7 @@ impl CallToolResult {
content,
structured_content: None,
is_error: Some(false),
meta: None,
}
}
/// Create an error tool result with unstructured content
@ -1284,6 +1288,7 @@ impl CallToolResult {
content,
structured_content: None,
is_error: Some(true),
meta: None,
}
}
/// Create a successful tool result with structured content
@ -1305,6 +1310,7 @@ impl CallToolResult {
content: vec![Content::text(value.to_string())],
structured_content: Some(value),
is_error: Some(false),
meta: None,
}
}
/// Create an error tool result with structured content
@ -1330,6 +1336,7 @@ impl CallToolResult {
content: vec![Content::text(value.to_string())],
structured_content: Some(value),
is_error: Some(true),
meta: None,
}
}
@ -1377,6 +1384,9 @@ impl<'de> Deserialize<'de> for CallToolResult {
structured_content: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
is_error: Option<bool>,
/// Accept `_meta` during deserialization
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
meta: Option<Meta>,
}
let helper = CallToolResultHelper::deserialize(deserializer)?;
@ -1384,6 +1394,7 @@ impl<'de> Deserialize<'de> for CallToolResult {
content: helper.content.unwrap_or_default(),
structured_content: helper.structured_content,
is_error: helper.is_error,
meta: helper.meta,
};
// Validate mutual exclusivity