fix: report pre-init metadata errors (#1160)
This commit is contained in:
parent
018ab24fac
commit
38428f66bc
2 changed files with 44 additions and 5 deletions
|
|
@ -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),
|
||||||
)));
|
)));
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue