Describe the bug
According to the MCP schema (version 2025-06-18), a tool’s outputSchema must have a root schema of type "object".
The Rust SDK currently serializes any structured output into a JSON schema without ensuring that the root type is "object". This behavior is non-compliant with the specification.
To Reproduce
- Implement a tool handler whose return type is
Json<non-object> or Result<Json<non-object>, E>.
An example of this exists in this very repository calculator.rs#L47.
Here is a minimal file with that tool:
use rmcp::{Json,ServerHandler,ServiceExt,
handler::server::{tool::ToolRouter, wrapper::Parameters},
model::{ServerCapabilities,ServerInfo},
schemars, tool, tool_handler, tool_router,
transport::stdio,};#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]pubstructSubRequest{#[schemars(description = "the left hand side number")]puba:i32,#[schemars(description = "the right hand side number")]pubb:i32,}#[derive(Debug,Clone)]pubstructCalculator{tool_router:ToolRouter<Self>,}#[tool_router]implCalculator{pubfnnew() -> Self{Self{tool_router:Self::tool_router(),}}#[tool(description = "Calculate the difference of two numbers")]fnsub(&self,Parameters(SubRequest{ a, b }):Parameters<SubRequest>) -> Json<i32>{Json(a - b)}}#[tool_handler]implServerHandlerforCalculator{fnget_info(&self) -> ServerInfo{ServerInfo{instructions:Some("A simple calculator".into()),capabilities:ServerCapabilities::builder().enable_tools().build(),
..Default::default()}}}#[tokio::main]asyncfnmain() -> anyhow::Result<()>{let service: rmcp::service::RunningService<rmcp::RoleServer,Calculator> =
Calculator::new().serve(stdio()).await.inspect_err(|e| {
tracing::error!("serving error: {:?}", e);})?;
service.waiting().await?;Ok(())}- Query the available tools.
{"jsonrpc": "2.0","id": 1,"method": "initialize","params": {"protocolVersion": "2025-06-18","capabilities": {"elicitation": {}},"clientInfo": {"name": "example-client","version": "1.0.0"}}}{"jsonrpc": "2.0", "id": 2, "method": "notifications/initialized"}{"jsonrpc": "2.0", "id": 3, "method": "tools/list"}
- Observe the schema in the response - the root of
outputSchema is of type "integer", when it should be "object"
{"outputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","format":"int32","title":"int32","type":"integer"}}Expected behavior
The generated outputSchema should comply with the specification by having a root type of "object", and all serialized outputs should match this schema.
Logs
Here are the full logs from running my example program.
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-03-26","capabilities":{"tools":{}},"serverInfo":{"name":"rmcp","version":"0.8.5"},"instructions":"A simple calculator"}}
{"jsonrpc":"2.0","id":3,"result":{"tools":[{"name":"sub","description":"Calculate the difference of two numbers","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","properties":{"a":{"description":"the left hand side number","format":"int32","type":"integer"},"b":{"description":"the right hand side number","format":"int32","type":"integer"}},"required":["a","b"],"title":"SubRequest","type":"object"},"outputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","format":"int32","title":"int32","type":"integer"}}]}}Additional context
The team behind this SDK has previously acknowledged incomplete compatibility with the 2025-06-18 schema version (#496 (comment)). This report highlights a specific instance which I have noticed.
This issue also appears to underlie #491, as the MCP schema expects outputSchema definitions with root type "object", rather than an empty definition {} or one where the root is of a primitive type.
As a temporary workaround for anyone interested, wrapping non-object outputs resolves the issue:
use serde::{Serialize,Deserialize};use rmcp::{schemars, schemars::JsonSchema};#[derive(Debug,Clone,Serialize,Deserialize,JsonSchema)]// Useful in situations where the result is not of type object by itselfpubstructWrapper<T>{pubresult:T,}impl<T>Wrapper<T>{pubfnnew(result:T) -> Self{Self{ result }}}
Describe the bug
According to the MCP schema (version 2025-06-18), a tool’s outputSchema must have a root schema of type "object".
The Rust SDK currently serializes any structured output into a JSON schema without ensuring that the root type is "object". This behavior is non-compliant with the specification.
To Reproduce
Json<non-object>orResult<Json<non-object>, E>.An example of this exists in this very repository calculator.rs#L47.
Here is a minimal file with that tool:
{"jsonrpc": "2.0","id": 1,"method": "initialize","params": {"protocolVersion": "2025-06-18","capabilities": {"elicitation": {}},"clientInfo": {"name": "example-client","version": "1.0.0"}}}{"jsonrpc": "2.0", "id": 2, "method": "notifications/initialized"}{"jsonrpc": "2.0", "id": 3, "method": "tools/list"}outputSchemais of type"integer", when it should be"object"{"outputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","format":"int32","title":"int32","type":"integer"}}Expected behavior
The generated
outputSchemashould comply with the specification by having a root type of"object", and all serialized outputs should match this schema.Logs
Here are the full logs from running my example program.
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-03-26","capabilities":{"tools":{}},"serverInfo":{"name":"rmcp","version":"0.8.5"},"instructions":"A simple calculator"}} {"jsonrpc":"2.0","id":3,"result":{"tools":[{"name":"sub","description":"Calculate the difference of two numbers","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","properties":{"a":{"description":"the left hand side number","format":"int32","type":"integer"},"b":{"description":"the right hand side number","format":"int32","type":"integer"}},"required":["a","b"],"title":"SubRequest","type":"object"},"outputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","format":"int32","title":"int32","type":"integer"}}]}}Additional context
The team behind this SDK has previously acknowledged incomplete compatibility with the 2025-06-18 schema version (#496 (comment)). This report highlights a specific instance which I have noticed.
This issue also appears to underlie #491, as the MCP schema expects
outputSchemadefinitions with root type"object", rather than an empty definition{}or one where the root is of a primitive type.As a temporary workaround for anyone interested, wrapping non-object outputs resolves the issue: