fix: report pre-init metadata errors (#1160)

This commit is contained in:
Dale Seo 2026-08-18 09:34:54 +09:00 • committed by GitHub
commit 38428f66bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 44 additions and 5 deletions

View file

@ -483,6 +483,16 @@ pub(crate) fn negotiate_protocol_version(
}
}
fn missing_request_metadata_error(missing: &[&str]) -> ErrorData {
ErrorData::invalid_params(
format!(
"request _meta is missing or has malformed required fields: {}",
missing.join(", ")
),
None,
)
}
async fn serve_server_with_ct_inner<S, T>(
service: S,
transport: T,
@ -528,11 +538,22 @@ where
let initialize_request = match request {
ClientRequest::InitializeRequest(request) => request,
mut request => {
if !request
let missing_metadata = request
.get_meta()
.missing_required_keys(&ProtocolVersion::V_2026_07_28)
.is_empty()
{
.missing_required_keys(&ProtocolVersion::V_2026_07_28);
if !missing_metadata.is_empty() {
transport
.send(ServerJsonRpcMessage::error(
missing_request_metadata_error(&missing_metadata),
Some(id.clone()),
))
.await
.map_err(|error| {
ServerInitializeError::transport::<T>(
error,
"sending pre-init metadata error response",
)
})?;
return Err(ServerInitializeError::ExpectedInitializeRequest(Some(
ClientJsonRpcMessage::request(request, id),
)));

View file

@ -162,7 +162,7 @@ async fn stateless_server_uses_each_requests_client_context() {
}
#[tokio::test]
async fn stateless_server_rejects_malformed_metadata_opener() {
async fn stateless_server_rejects_malformed_metadata_opener_with_error_response() {
let (server_transport, client_transport) = tokio::io::duplex(4096);
let server_task = tokio::spawn(async move { StatelessServer.serve(server_transport).await });
let mut client = IntoTransport::<rmcp::RoleClient, _, _>::into_transport(client_transport);
@ -186,6 +186,24 @@ async fn stateless_server_rejects_malformed_metadata_opener() {
))
.await
.expect("send list tools");
let Some(ServerJsonRpcMessage::Error(error)) = client.receive().await else {
panic!("expected invalid params");
};
assert_eq!(error.id, Some(RequestId::Number(1)));
assert_eq!(error.error.code, ErrorCode::INVALID_PARAMS);
assert!(
error
.error
.message
.contains("request _meta is missing or has malformed required fields")
);
assert!(
error
.error
.message
.contains("io.modelcontextprotocol/clientCapabilities")
);
let Err(error) = server_task.await.expect("server task") else {
panic!("malformed opener should not start a session");
};