Skip to content

Commit 7ba1ac4

Browse files
authored
fix: use mimeType instead of mime_type for MCP specification compliance (#339)
- Fix ResourceContents enum to properly serialize with camelCase field names - Add comprehensive tests to verify JSON serialization compliance - Ensure all resource-related structs use mimeType as per MCP spec - Add tests for RawResource, ResourceContents, RawImageContent, RawAudioContent - Add test for prompt message image content serialization - Update message schema files to reflect mimeType changes - Fix import ordering to match project formatting standards This change ensures the Rust SDK is fully compliant with the MCP specification which requires mimeType (camelCase) for all resource content types.
1 parent cdea86f commit 7ba1ac4

File tree

5 files changed

+107
-5
lines changed

5 files changed

+107
-5
lines changed

crates/rmcp/src/model/content.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,40 @@ impl IntoContents for () {
171171
vec![]
172172
}
173173
}
174+
175+
#[cfg(test)]
176+
mod tests {
177+
use serde_json;
178+
179+
use super::*;
180+
181+
#[test]
182+
fn test_image_content_serialization() {
183+
let image_content = RawImageContent {
184+
data: "base64data".to_string(),
185+
mime_type: "image/png".to_string(),
186+
};
187+
188+
let json = serde_json::to_string(&image_content).unwrap();
189+
println!("ImageContent JSON: {}", json);
190+
191+
// Verify it contains mimeType (camelCase) not mime_type (snake_case)
192+
assert!(json.contains("mimeType"));
193+
assert!(!json.contains("mime_type"));
194+
}
195+
196+
#[test]
197+
fn test_audio_content_serialization() {
198+
let audio_content = RawAudioContent {
199+
data: "base64audiodata".to_string(),
200+
mime_type: "audio/wav".to_string(),
201+
};
202+
203+
let json = serde_json::to_string(&audio_content).unwrap();
204+
println!("AudioContent JSON: {}", json);
205+
206+
// Verify it contains mimeType (camelCase) not mime_type (snake_case)
207+
assert!(json.contains("mimeType"));
208+
assert!(!json.contains("mime_type"));
209+
}
210+
}

crates/rmcp/src/model/prompt.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,25 @@ pub struct PromptArgumentTemplate {
168168
pub description: Option<String>,
169169
pub required: Option<bool>,
170170
}
171+
172+
#[cfg(test)]
173+
mod tests {
174+
use serde_json;
175+
176+
use super::*;
177+
178+
#[test]
179+
fn test_prompt_message_image_serialization() {
180+
let image_content = RawImageContent {
181+
data: "base64data".to_string(),
182+
mime_type: "image/png".to_string(),
183+
};
184+
185+
let json = serde_json::to_string(&image_content).unwrap();
186+
println!("PromptMessage ImageContent JSON: {}", json);
187+
188+
// Verify it contains mimeType (camelCase) not mime_type (snake_case)
189+
assert!(json.contains("mimeType"));
190+
assert!(!json.contains("mime_type"));
191+
}
192+
}

crates/rmcp/src/model/resource.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,17 @@ pub struct RawResourceTemplate {
4242
pub type ResourceTemplate = Annotated<RawResourceTemplate>;
4343

4444
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
45-
#[serde(rename_all = "camelCase", untagged)]
45+
#[serde(untagged)]
4646
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4747
pub enum ResourceContents {
48+
#[serde(rename_all = "camelCase")]
4849
TextResourceContents {
4950
uri: String,
5051
#[serde(skip_serializing_if = "Option::is_none")]
5152
mime_type: Option<String>,
5253
text: String,
5354
},
55+
#[serde(rename_all = "camelCase")]
5456
BlobResourceContents {
5557
uri: String,
5658
#[serde(skip_serializing_if = "Option::is_none")]
@@ -81,3 +83,44 @@ impl RawResource {
8183
}
8284
}
8385
}
86+
87+
#[cfg(test)]
88+
mod tests {
89+
use serde_json;
90+
91+
use super::*;
92+
93+
#[test]
94+
fn test_resource_serialization() {
95+
let resource = RawResource {
96+
uri: "file:///test.txt".to_string(),
97+
name: "test".to_string(),
98+
description: Some("Test resource".to_string()),
99+
mime_type: Some("text/plain".to_string()),
100+
size: Some(100),
101+
};
102+
103+
let json = serde_json::to_string(&resource).unwrap();
104+
println!("Serialized JSON: {}", json);
105+
106+
// Verify it contains mimeType (camelCase) not mime_type (snake_case)
107+
assert!(json.contains("mimeType"));
108+
assert!(!json.contains("mime_type"));
109+
}
110+
111+
#[test]
112+
fn test_resource_contents_serialization() {
113+
let text_contents = ResourceContents::TextResourceContents {
114+
uri: "file:///test.txt".to_string(),
115+
mime_type: Some("text/plain".to_string()),
116+
text: "Hello world".to_string(),
117+
};
118+
119+
let json = serde_json::to_string(&text_contents).unwrap();
120+
println!("ResourceContents JSON: {}", json);
121+
122+
// Verify it contains mimeType (camelCase) not mime_type (snake_case)
123+
assert!(json.contains("mimeType"));
124+
assert!(!json.contains("mime_type"));
125+
}
126+
}

crates/rmcp/tests/test_message_schema/client_json_rpc_message_schema.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,7 @@
11291129
{
11301130
"type": "object",
11311131
"properties": {
1132-
"mime_type": {
1132+
"mimeType": {
11331133
"type": [
11341134
"string",
11351135
"null"
@@ -1153,7 +1153,7 @@
11531153
"blob": {
11541154
"type": "string"
11551155
},
1156-
"mime_type": {
1156+
"mimeType": {
11571157
"type": [
11581158
"string",
11591159
"null"

crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,7 @@
13331333
{
13341334
"type": "object",
13351335
"properties": {
1336-
"mime_type": {
1336+
"mimeType": {
13371337
"type": [
13381338
"string",
13391339
"null"
@@ -1357,7 +1357,7 @@
13571357
"blob": {
13581358
"type": "string"
13591359
},
1360-
"mime_type": {
1360+
"mimeType": {
13611361
"type": [
13621362
"string",
13631363
"null"

0 commit comments

Comments
 (0)