Skip to content

ListToolsResult contains URL to non-reachable schema #179

@denniskawurek

Description

@denniskawurek

Describe the bug
Hi,

I'm aiming to use this SDK to implement a small server.
I checked the examples for having an idea of how it works and can connect successfully from a client to a server.

But when I try to call the tools/list endpoint from a client like VSCode I get the following error message within VSCode:

MCP server `my-toolbox` has tools with invalid parameters which will be omitted.

The details show:

Tool `say_hello` has invalid JSON parameters:
	- Unable to load schema from 'https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema': Not Found. The requested location could not be found.
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-in. (at /$schema)
	- Schema: {"$schema":"https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema","title":"EmptyObject","type":"object"}

In the debug logs of my server I see the response which is sent to the server:

2025-05-15T19:32:05.705088Z DEBUG rmcp::service: response message id=1 result=ListToolsResult(ListToolsResult { next_cursor: None, tools: [Tool { name: "say_hello", description: Some("Say hello to the client"), input_schema: {"$schema": String("https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema"), "title": String("EmptyObject"), "type": String("object")}, annotations: None }] })

Looks like VSCode tries to lookup the schema and follow the URL, which leads to a 404: https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema

The same is logged when using the MCP inspector and when using either SseServer or StreamableHttpServer.
But the MCP inspector seems to not follow the schema link. And can call the tools/list successfully.

To Reproduce
I've created the following small example to reproduce it:

use rmcp::{
    Error as McpError, ServerHandler,
    model::{CallToolResult, Content, ServerCapabilities, ServerInfo},
    tool,
    transport::{SseServer, StreamableHttpServer},
};
use tracing_subscriber::{
    layer::SubscriberExt,
    util::SubscriberInitExt,
    {self},
};

const BIND_ADDRESS: &str = "127.0.0.1:8000";

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    /*
    // Streamable
    tracing_subscriber::registry()
        .with(
            tracing_subscriber::EnvFilter::try_from_default_env()
                .unwrap_or_else(|_| "debug".to_string().into()),
        )
        .with(tracing_subscriber::fmt::layer())
        .init();

    let ct = StreamableHttpServer::serve(BIND_ADDRESS.parse()?)
        .await?
        .with_service(MyToolBox::new);

    tokio::signal::ctrl_c().await?;
    ct.cancel();
    Ok(())*/
    // SSE
    tracing_subscriber::registry()
        .with(
            tracing_subscriber::EnvFilter::try_from_default_env()
                .unwrap_or_else(|_| "debug".to_string().into()),
        )
        .with(tracing_subscriber::fmt::layer())
        .init();

    let ct = SseServer::serve(BIND_ADDRESS.parse()?)
        .await?
        .with_service(MyToolBox::new);

    tokio::signal::ctrl_c().await?;
    ct.cancel();
    Ok(())
}

#[derive(Debug, Clone)]
pub struct MyToolBox;

#[tool(tool_box)]
impl MyToolBox {
    pub fn new() -> Self {
        MyToolBox
    }

    #[tool(description = "Say hello to the client")]
    fn say_hello(&self) -> Result<CallToolResult, McpError> {
        Ok(CallToolResult::success(vec![Content::text(
            "hello".to_string(),
        )]))
    }
}

#[tool(tool_box)]
impl ServerHandler for MyToolBox {
    fn get_info(&self) -> ServerInfo {
        ServerInfo {
            instructions: Some("My toolbox".into()),
            capabilities: ServerCapabilities::builder().enable_tools().build(),
            ..Default::default()
        }
    }
}

Cargo.toml:

[package]
name = "cargo-fails-vscode"
version = "0.1.0"
edition = "2024"

[dependencies]
rmcp = { git = "https://github.com/modelcontextprotocol/rust-sdk", branch = "main", features = ["server", "transport-sse-server", "transport-io", "transport-streamable-http-server", "auth"] }
serde_yaml = "0.9.34"
tokio = {version = "1.45.0", features = ["full"]}
anyhow = "1.0"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = [
    "env-filter",
    "std",
    "fmt",
] }

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-bugBug fixes and error corrections

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions