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>( async fn serve_server_with_ct_inner<S, T>(
service: S, service: S,
transport: T, transport: T,
@ -528,11 +538,22 @@ where
let initialize_request = match request { let initialize_request = match request {
ClientRequest::InitializeRequest(request) => request, ClientRequest::InitializeRequest(request) => request,
mut request => { mut request => {
if !request let missing_metadata = request
.get_meta() .get_meta()
.missing_required_keys(&ProtocolVersion::V_2026_07_28) .missing_required_keys(&ProtocolVersion::V_2026_07_28);
.is_empty() 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( return Err(ServerInitializeError::ExpectedInitializeRequest(Some(
ClientJsonRpcMessage::request(request, id), ClientJsonRpcMessage::request(request, id),
))); )));

View file

@ -162,7 +162,7 @@ async fn stateless_server_uses_each_requests_client_context() {
} }
#[tokio::test] #[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_transport, client_transport) = tokio::io::duplex(4096);
let server_task = tokio::spawn(async move { StatelessServer.serve(server_transport).await }); let server_task = tokio::spawn(async move { StatelessServer.serve(server_transport).await });
let mut client = IntoTransport::<rmcp::RoleClient, _, _>::into_transport(client_transport); let mut client = IntoTransport::<rmcp::RoleClient, _, _>::into_transport(client_transport);
@ -186,6 +186,24 @@ async fn stateless_server_rejects_malformed_metadata_opener() {
)) ))
.await .await
.expect("send list tools"); .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 { let Err(error) = server_task.await.expect("server task") else {
panic!("malformed opener should not start a session"); panic!("malformed opener should not start a session");
}; };