use crate::application::mcp::initialize::read_offer;
use crate::application::server::builder::DispatchError;
use crate::application::server::context::RequestContext;
use crate::domain::feature::FeatureProfile;
use crate::domain::ir::JsonObject;
use crate::domain::{
CapabilitySet, Negotiation, ProtocolVersion, SupportedVersions, TransportKind,
negotiate_server, resolve, transport_allowed,
};
pub(super) fn negotiate(
ctx: &RequestContext,
params: &JsonObject,
) -> Result<(ProtocolVersion, FeatureProfile), DispatchError> {
let transport = ctx.peer().transport();
let supported = supported_on(transport)?;
let offer = read_offer(params).map_err(|_| DispatchError::MalformedInitialize)?;
let version = negotiate_server(offer.version, &supported).version();
let profile = resolve(Negotiation {
version,
client_caps: offer.capabilities,
server_caps: CapabilitySet::all_for(version),
transport,
});
Ok((version, profile))
}
pub(super) fn supported_on(transport: TransportKind) -> Result<SupportedVersions, DispatchError> {
let all = SupportedVersions::all().map_err(|_| DispatchError::UnnegotiableVersion)?;
if transport != TransportKind::LegacySse {
return Ok(all);
}
let defining: Vec<ProtocolVersion> = all
.as_slice()
.iter()
.copied()
.filter(|version| transport_allowed(*version, transport))
.collect();
SupportedVersions::from_slice(&defining).map_err(|_| DispatchError::UnnegotiableVersion)
}