feat!: add server discovery and negotiation (SEP-2575) (#973)
* feat!: add server discovery and negotiation * feat!: make protocol unions extensible * ci: add discovery conformance coverage
This commit is contained in:
parent
b93220d4a7
commit
3549e86d28
1 changed files with 1325 additions and 98 deletions
77
crates/rmcp/tests/test_server_discover_client.rs
Normal file
77
crates/rmcp/tests/test_server_discover_client.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
#![cfg(all(feature = "client", not(feature = "local")))]
|
||||
|
||||
use rmcp::{
|
||||
ClientHandler, ServerHandler, ServiceExt,
|
||||
model::{
|
||||
ClientCapabilities, Implementation, ProtocolVersion, RequestMetaObject, ServerCapabilities,
|
||||
ServerInfo,
|
||||
},
|
||||
select_protocol_version,
|
||||
};
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct DiscoveryServer;
|
||||
|
||||
impl ServerHandler for DiscoveryServer {
|
||||
fn get_info(&self) -> ServerInfo {
|
||||
ServerInfo::new(ServerCapabilities::builder().enable_tools().build())
|
||||
.with_server_info(Implementation::new("discovery-server", "1.0.0"))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct DiscoveryClient;
|
||||
|
||||
impl ClientHandler for DiscoveryClient {}
|
||||
|
||||
#[test]
|
||||
fn select_protocol_version_uses_client_preference_order() {
|
||||
let selected = select_protocol_version(
|
||||
&[ProtocolVersion::V_2026_07_28, ProtocolVersion::V_2025_11_25],
|
||||
&[ProtocolVersion::V_2025_11_25, ProtocolVersion::V_2026_07_28],
|
||||
);
|
||||
|
||||
assert_eq!(selected, Some(ProtocolVersion::V_2026_07_28));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn select_protocol_version_returns_none_without_overlap() {
|
||||
let selected = select_protocol_version(
|
||||
&[ProtocolVersion::V_2026_07_28],
|
||||
&[ProtocolVersion::V_2025_11_25],
|
||||
);
|
||||
|
||||
assert_eq!(selected, None);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn client_discover_helper_returns_typed_result() {
|
||||
let (server_transport, client_transport) = tokio::io::duplex(4096);
|
||||
tokio::spawn(async move {
|
||||
let _ = DiscoveryServer
|
||||
.serve(server_transport)
|
||||
.await
|
||||
.expect("server should start")
|
||||
.waiting()
|
||||
.await;
|
||||
});
|
||||
let client = DiscoveryClient
|
||||
.serve(client_transport)
|
||||
.await
|
||||
.expect("client should connect");
|
||||
let mut meta = RequestMetaObject::new();
|
||||
meta.set_protocol_version(ProtocolVersion::V_2026_07_28);
|
||||
meta.set_client_info(Implementation::new("discovery-client", "1.0.0"));
|
||||
meta.set_client_capabilities(ClientCapabilities::default());
|
||||
|
||||
let result = client
|
||||
.discover(meta)
|
||||
.await
|
||||
.expect("discover should succeed");
|
||||
|
||||
assert_eq!(
|
||||
result.server_info,
|
||||
Implementation::new("discovery-server", "1.0.0")
|
||||
);
|
||||
client.cancel().await.expect("client should cancel");
|
||||
}
|
||||
Loading…
Reference in a new issue