feat!: align model types with MCP 2025-11-25 spec (#927)

* feat!: align model types with MCP 2025-11-25 spec

* fix: complete 2025-11-25 model spec conformance
This commit is contained in:
Dale Seo 2026-06-24 20:41:13 -04:00 • committed by GitHub
commit 77932141e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 4321 additions and 3886 deletions

View file

@ -94,14 +94,14 @@ impl Counter {
}
fn _create_resource_text(&self, uri: &str, name: &str) -> Resource {
RawResource::new(uri, name.to_string()).no_annotation()
Resource::new(uri, name.to_string())
}
#[tool(description = "Increment the counter by 1")]
async fn increment(&self) -> Result<CallToolResult, McpError> {
let mut counter = self.counter.lock().await;
*counter += 1;
Ok(CallToolResult::success(vec![Content::text(
Ok(CallToolResult::success(vec![ContentBlock::text(
counter.to_string(),
)]))
}
@ -110,7 +110,7 @@ impl Counter {
async fn decrement(&self) -> Result<CallToolResult, McpError> {
let mut counter = self.counter.lock().await;
*counter -= 1;
Ok(CallToolResult::success(vec![Content::text(
Ok(CallToolResult::success(vec![ContentBlock::text(
counter.to_string(),
)]))
}
@ -118,7 +118,7 @@ impl Counter {
#[tool(description = "Get the current counter value")]
async fn get_value(&self) -> Result<CallToolResult, McpError> {
let counter = self.counter.lock().await;
Ok(CallToolResult::success(vec![Content::text(
Ok(CallToolResult::success(vec![ContentBlock::text(
counter.to_string(),
)]))
}
@ -129,19 +129,19 @@ impl Counter {
)]
async fn long_task(&self) -> Result<CallToolResult, McpError> {
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
Ok(CallToolResult::success(vec![Content::text(
Ok(CallToolResult::success(vec![ContentBlock::text(
"Long task completed",
)]))
}
#[tool(description = "Say hello to the client")]
fn say_hello(&self) -> Result<CallToolResult, McpError> {
Ok(CallToolResult::success(vec![Content::text("hello")]))
Ok(CallToolResult::success(vec![ContentBlock::text("hello")]))
}
#[tool(description = "Repeat what you say")]
fn echo(&self, Parameters(object): Parameters<JsonObject>) -> Result<CallToolResult, McpError> {
Ok(CallToolResult::success(vec![Content::text(
Ok(CallToolResult::success(vec![ContentBlock::text(
serde_json::Value::Object(object).to_string(),
)]))
}
@ -151,7 +151,7 @@ impl Counter {
&self,
Parameters(StructRequest { a, b }): Parameters<StructRequest>,
) -> Result<CallToolResult, McpError> {
Ok(CallToolResult::success(vec![Content::text(
Ok(CallToolResult::success(vec![ContentBlock::text(
(a + b).to_string(),
)]))
}
@ -166,8 +166,8 @@ impl Counter {
.map(|v| v.to_str().unwrap_or("(non-ascii)").to_owned());
match session_id {
Some(id) => Ok(CallToolResult::success(vec![Content::text(id)])),
None => Ok(CallToolResult::success(vec![Content::text(
Some(id) => Ok(CallToolResult::success(vec![ContentBlock::text(id)])),
None => Ok(CallToolResult::success(vec![ContentBlock::text(
"no session (not running over streamable HTTP?)",
)])),
}
@ -190,10 +190,7 @@ impl Counter {
"This is an example prompt with your message here: '{}'",
args.message
);
Ok(vec![PromptMessage::new_text(
PromptMessageRole::User,
prompt,
)])
Ok(vec![PromptMessage::new_text(Role::User, prompt)])
}
/// Analyze the current counter value and suggest next steps
@ -209,11 +206,11 @@ impl Counter {
let messages = vec![
PromptMessage::new_text(
PromptMessageRole::Assistant,
Role::Assistant,
"I'll analyze the counter situation and suggest the best approach.",
),
PromptMessage::new_text(
PromptMessageRole::User,
Role::User,
format!(
"Current counter value: {}\nGoal value: {}\nDifference: {}\nStrategy preference: {}\n\nPlease analyze the situation and suggest the best approach to reach the goal.",
current_value, args.goal, difference, strategy
@ -406,12 +403,7 @@ mod tests {
});
let client_service = client.serve(client_transport).await?;
let mut task_meta = serde_json::Map::new();
task_meta.insert(
"source".into(),
serde_json::Value::String("integration-test".into()),
);
let params = CallToolRequestParams::new("long_task").with_task(task_meta);
let params = CallToolRequestParams::new("long_task").with_task(TaskMetadata::new());
let response = client_service
.send_request(ClientRequest::CallToolRequest(Request::new(params.clone())))
.await?;

View file

@ -97,12 +97,12 @@ impl ProgressDemo {
let chunk_str = String::from_utf8_lossy(&chunk);
counter += 1;
// create progress notification param
let progress_param = ProgressNotificationParam {
progress_token: ProgressToken(progress_token.clone()),
progress: counter as f64,
total: Some(5.0),
message: Some(chunk_str.to_string()),
};
let progress_param = ProgressNotificationParam::new(
ProgressToken(progress_token.clone()),
counter as f64,
)
.with_total(5.0)
.with_message(chunk_str.to_string());
match ctx.peer.notify_progress(progress_param).await {
Ok(_) => {
@ -122,7 +122,7 @@ impl ProgressDemo {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
Ok(CallToolResult::success(vec![Content::text(format!(
Ok(CallToolResult::success(vec![ContentBlock::text(format!(
"Processed {} records successfully",
counter
))]))

View file

@ -16,7 +16,7 @@ use std::sync::Arc;
use rmcp::{
ErrorData as McpError, ServerHandler,
handler::server::{router::tool::ToolRouter, wrapper::Parameters},
model::{CallToolResult, Content},
model::{CallToolResult, ContentBlock},
schemars, task_handler,
task_manager::OperationProcessor,
tool, tool_handler, tool_router,
@ -70,7 +70,7 @@ impl TaskDemo {
Parameters(SumArgs { a, b }): Parameters<SumArgs>,
) -> Result<CallToolResult, McpError> {
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
Ok(CallToolResult::success(vec![Content::text(
Ok(CallToolResult::success(vec![ContentBlock::text(
(a + b).to_string(),
)]))
}
@ -81,7 +81,7 @@ impl TaskDemo {
&self,
Parameters(EchoArgs { message }): Parameters<EchoArgs>,
) -> Result<CallToolResult, McpError> {
Ok(CallToolResult::success(vec![Content::text(message)]))
Ok(CallToolResult::success(vec![ContentBlock::text(message)]))
}
}