fix: resolve clippy warnings across workspace (#1195)

* fix: resolve clippy warnings across workspace

* ci: also run clippy on rmcp with all features except local

--all-features enables the local feature, which cfg-gates out
tower.rs and most of the test suite, so the existing clippy step
never actually lints them.
This commit is contained in:
Dale Seo 2026-09-08 19:05:29 -04:00 • committed by GitHub
commit 6fa40536de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 277 additions and 289 deletions

View file

@ -55,6 +55,24 @@ use crate::{
pub(crate) const DEFAULT_MAX_REQUEST_BODY_BYTES: usize = 4 * 1024 * 1024;
const STATELESS_STREAM_CHANNEL_CAPACITY: usize = 16;
struct ErrorResponse(Box<BoxResponse>);
impl ErrorResponse {
fn into_response(self) -> BoxResponse {
*self.0
}
}
impl From<BoxResponse> for ErrorResponse {
fn from(response: BoxResponse) -> Self {
Self(Box::new(response))
}
}
type HttpResult<T> = Result<T, ErrorResponse>;
type RestoreResultSender = tokio::sync::watch::Sender<Option<bool>>;
type PendingRestores = Arc<tokio::sync::RwLock<HashMap<SessionId, RestoreResultSender>>>;
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct StreamableHttpServerConfig {
@ -247,10 +265,6 @@ impl StreamableHttpServerConfig {
}
}
#[expect(
clippy::result_large_err,
reason = "BoxResponse is intentionally large; matches other handlers in this file"
)]
/// Validates the `MCP-Protocol-Version` header on incoming HTTP requests.
///
/// Per the MCP 2025-06-18 spec:
@ -259,7 +273,7 @@ impl StreamableHttpServerConfig {
fn validate_protocol_version_header(
headers: &http::HeaderMap,
allow_unknown: bool,
) -> Result<(), BoxResponse> {
) -> HttpResult<()> {
if let Some(value) = headers.get(HEADER_MCP_PROTOCOL_VERSION) {
let version_str = value.to_str().map_err(|_| {
Response::builder()
@ -284,7 +298,8 @@ fn validate_protocol_version_header(
)))
.boxed(),
)
.expect("valid response"));
.expect("valid response")
.into());
}
}
Ok(())
@ -349,28 +364,24 @@ impl<S: Service<RoleServer>> Service<RoleServer> for NegotiatingStatelessHttpSer
}
}
#[expect(
clippy::result_large_err,
reason = "BoxResponse is intentionally large; matches other handlers in this file"
)]
// SEP-2567: sessions are removed from the discover lifecycle. Validate
// protocol-version consistency, then classify the request with the shared
// lifecycle helper.
fn is_legacy_request(
message: Option<&ClientJsonRpcMessage>,
headers: &HeaderMap,
) -> Result<bool, BoxResponse> {
) -> HttpResult<bool> {
let has_per_request_version = message.is_some_and(message_has_per_request_protocol_version);
validate_protocol_version_header(headers, has_per_request_version)?;
if let Some(message) = message {
if let ClientJsonRpcMessage::Request(req) = message {
if let ClientRequest::InitializeRequest(init) = &req.request {
validate_header_matches_init_body(
headers,
init.params.protocol_version.as_str(),
Some(req.id.clone()),
)?;
}
if let ClientJsonRpcMessage::Request(req) = message
&& let ClientRequest::InitializeRequest(init) = &req.request
{
validate_header_matches_init_body(
headers,
init.params.protocol_version.as_str(),
Some(req.id.clone()),
)?;
}
validate_request_protocol_version_meta(headers, message)?;
}
@ -430,10 +441,10 @@ async fn persist_and_forward_event(
output: &mut Option<tokio::sync::mpsc::Sender<ServerSseMessage>>,
) -> Result<(), EventStoreError> {
event.event_id = Some(event_store.store_event(stream_id, &event).await?);
if let Some(sender) = output {
if sender.send(event).await.is_err() {
*output = None;
}
if let Some(sender) = output
&& sender.send(event).await.is_err()
{
*output = None;
}
Ok(())
}
@ -464,16 +475,12 @@ fn invalid_params_jsonrpc_response(
.expect("valid response")
}
#[expect(
clippy::result_large_err,
reason = "BoxResponse is intentionally large; matches other handlers in this file"
)]
/// Absent header is allowed; the first initialize round-trip may legitimately omit it.
fn validate_header_matches_init_body(
headers: &http::HeaderMap,
body_version: &str,
request_id: Option<RequestId>,
) -> Result<(), BoxResponse> {
) -> HttpResult<()> {
let Some(header_value) = headers.get(HEADER_MCP_PROTOCOL_VERSION) else {
return Ok(());
};
@ -494,19 +501,16 @@ fn validate_header_matches_init_body(
format!(
"Invalid Request: MCP-Protocol-Version header ({header_str}) does not match initialize params.protocolVersion ({body_version})"
),
));
)
.into());
}
Ok(())
}
#[expect(
clippy::result_large_err,
reason = "BoxResponse is intentionally large; matches other handlers in this file"
)]
fn validate_request_protocol_version_meta(
headers: &HeaderMap,
message: &ClientJsonRpcMessage,
) -> Result<(), BoxResponse> {
) -> HttpResult<()> {
let ClientJsonRpcMessage::Request(request) = message else {
return Ok(());
};
@ -530,7 +534,8 @@ fn validate_request_protocol_version_meta(
"Invalid params: request _meta is missing or has malformed required fields: {}",
missing.join(", ")
),
));
)
.into());
}
return Ok(());
};
@ -538,7 +543,8 @@ fn validate_request_protocol_version_meta(
return Err(header_mismatch_jsonrpc_response(
Some(request.id.clone()),
"request _meta protocolVersion requires MCP-Protocol-Version header",
));
)
.into());
};
if header_version != meta_version.as_str() {
return Err(header_mismatch_jsonrpc_response(
@ -546,7 +552,8 @@ fn validate_request_protocol_version_meta(
format!(
"MCP-Protocol-Version header ({header_version}) does not match request _meta protocolVersion ({meta_version})"
),
));
)
.into());
}
Ok(())
}
@ -557,15 +564,11 @@ fn validate_request_protocol_version_meta(
/// HTTP 400 / JSON-RPC `-32020` before handler dispatch. `server/discover`
/// is included so the seam aligns with the per-POST header contract; its
/// body-metadata rule is preserved unchanged.
#[expect(
clippy::result_large_err,
reason = "BoxResponse is intentionally large; matches other handlers in this file"
)]
fn validate_required_protocol_header(
config: &StreamableHttpServerConfig,
headers: &HeaderMap,
message: &ClientJsonRpcMessage,
) -> Result<(), BoxResponse> {
) -> HttpResult<()> {
if !config.stateless_protocol_metadata_required {
return Ok(());
}
@ -583,7 +586,8 @@ fn validate_required_protocol_header(
Err(header_mismatch_jsonrpc_response(
Some(request.id.clone()),
"Missing MCP-Protocol-Version header for request requiring per-request protocol metadata",
))
)
.into())
}
/// When `stateless_protocol_metadata_required` is enabled in stateless mode,
@ -593,14 +597,10 @@ fn validate_required_protocol_header(
/// `server/discover` (whose body-metadata rule is already enforced by
/// `validate_request_protocol_version_meta`), notifications, and other message
/// kinds are exempt.
#[expect(
clippy::result_large_err,
reason = "BoxResponse is intentionally large; matches other handlers in this file"
)]
fn validate_required_protocol_meta(
config: &StreamableHttpServerConfig,
message: &ClientJsonRpcMessage,
) -> Result<(), BoxResponse> {
) -> HttpResult<()> {
if !config.stateless_protocol_metadata_required {
return Ok(());
}
@ -619,7 +619,8 @@ fn validate_required_protocol_meta(
Err(invalid_params_jsonrpc_response(
Some(request.id.clone()),
"Invalid params: request requires protocolVersion in request _meta",
))
)
.into())
}
fn jsonrpc_http_status(message: &ServerJsonRpcMessage) -> http::StatusCode {
@ -640,7 +641,7 @@ fn jsonrpc_http_status(message: &ServerJsonRpcMessage) -> http::StatusCode {
fn jsonrpc_message_response(
message: ServerJsonRpcMessage,
map_protocol_status: bool,
) -> Result<BoxResponse, BoxResponse> {
) -> HttpResult<BoxResponse> {
let status = if map_protocol_status {
jsonrpc_http_status(&message)
} else {
@ -674,15 +675,11 @@ fn header_mismatch_jsonrpc_response(
/// The `initialize` handshake is exempt: clients emit these headers only after the
/// version has been negotiated. `tool_schema` supplies the called tool's input schema
/// so annotated `Mcp-Param-*` headers can be checked (no schema => those are skipped).
#[expect(
clippy::result_large_err,
reason = "BoxResponse is intentionally large; matches other handlers in this file"
)]
fn validate_standard_headers(
headers: &HeaderMap,
message: &ClientJsonRpcMessage,
tool_schema: impl Fn(&str) -> Option<Arc<JsonObject>>,
) -> Result<(), BoxResponse> {
) -> HttpResult<()> {
let version_requires_headers = headers
.get(HEADER_MCP_PROTOCOL_VERSION)
.and_then(|value| value.to_str().ok())
@ -715,7 +712,7 @@ fn validate_standard_headers(
.and_then(|name| name.as_str())
.and_then(tool_schema);
if let Err(reason) = mcp_headers::validate_request_headers(headers, &value, schema.as_deref()) {
return Err(header_mismatch_jsonrpc_response(request_id, reason));
return Err(header_mismatch_jsonrpc_response(request_id, reason).into());
}
Ok(())
}
@ -839,10 +836,7 @@ fn bad_request_response(message: &str) -> BoxResponse {
.expect("failed to build bad request response")
}
fn parse_host_header(
uri: &http::Uri,
headers: &HeaderMap,
) -> Result<NormalizedAuthority, BoxResponse> {
fn parse_host_header(uri: &http::Uri, headers: &HeaderMap) -> HttpResult<NormalizedAuthority> {
if let Some(host) = headers.get(http::header::HOST) {
let host_str = host
.to_str()
@ -873,23 +867,20 @@ fn validate_dns_rebinding_headers(
uri: &http::Uri,
headers: &HeaderMap,
config: &StreamableHttpServerConfig,
) -> Result<(), BoxResponse> {
) -> HttpResult<()> {
let host = parse_host_header(uri, headers)?;
if !host_is_allowed(&host, &config.allowed_hosts) {
tracing::warn!(
host = ?host,
"rejected request with disallowed Host header (possible DNS rebinding attempt)",
);
return Err(forbidden_response("Forbidden: Host header is not allowed"));
return Err(forbidden_response("Forbidden: Host header is not allowed").into());
}
validate_origin_header(headers, &config.allowed_origins)?;
Ok(())
}
fn validate_origin_header(
headers: &HeaderMap,
allowed_origins: &[String],
) -> Result<(), BoxResponse> {
fn validate_origin_header(headers: &HeaderMap, allowed_origins: &[String]) -> HttpResult<()> {
if allowed_origins.is_empty() {
return Ok(());
}
@ -914,9 +905,7 @@ fn validate_origin_header(
origin = ?origin,
"rejected request with disallowed Origin header (possible cross-origin attack)",
);
return Err(forbidden_response(
"Forbidden: Origin header is not allowed",
));
return Err(forbidden_response("Forbidden: Origin header is not allowed").into());
}
Ok(())
}
@ -1012,9 +1001,7 @@ pub struct StreamableHttpService<S, M> {
/// same unknown session ID wait for the first restore to complete rather
/// than racing to replay the initialize handshake. `None` when no external
/// session store is configured (avoids allocating the map).
pending_restores: Option<
Arc<tokio::sync::RwLock<HashMap<SessionId, tokio::sync::watch::Sender<Option<bool>>>>>,
>,
pending_restores: Option<PendingRestores>,
/// Caches tool input schemas by name for SEP-2243 `Mcp-Param-*` validation.
/// Populated lazily via `get_tool` so the service factory runs at most once
/// per tool name. `None` value means the tool exposes no schema.
@ -1067,10 +1054,9 @@ where
/// `result` defaults to `false` (failure / cancellation). Only the success path
/// needs to set it to `true` before returning.
struct PendingRestoreGuard {
pending_restores:
Arc<tokio::sync::RwLock<HashMap<SessionId, tokio::sync::watch::Sender<Option<bool>>>>>,
pending_restores: PendingRestores,
session_id: SessionId,
watch_tx: tokio::sync::watch::Sender<Option<bool>>,
watch_tx: RestoreResultSender,
/// The value that will be broadcast to waiting tasks on drop.
result: bool,
}
@ -1098,12 +1084,10 @@ where
session_manager: Arc<M>,
config: StreamableHttpServerConfig,
) -> Self {
let pending_restores = config.session_store.is_some().then(|| {
Arc::new(tokio::sync::RwLock::new(HashMap::<
SessionId,
tokio::sync::watch::Sender<Option<bool>>,
>::new()))
});
let pending_restores = config
.session_store
.is_some()
.then(|| Arc::new(tokio::sync::RwLock::new(HashMap::new())));
Self {
config,
session_manager,
@ -1130,19 +1114,18 @@ where
tokio::spawn(async move {
let mut sender = Some(sender);
if let Some(retry) = retry {
if let Err(error) = persist_and_forward_event(
if let Some(retry) = retry
&& let Err(error) = persist_and_forward_event(
event_store.as_ref(),
&stream_id,
ServerSseMessage::retry(retry),
&mut sender,
)
.await
{
tracing::error!(%stream_id, %error, "failed to persist SSE priming event");
request_ct.cancel();
return;
}
{
tracing::error!(%stream_id, %error, "failed to persist SSE priming event");
request_ct.cancel();
return;
}
let mut first = first;
@ -1214,7 +1197,7 @@ where
service: S,
mut request: crate::model::JsonRpcRequest<ClientRequest>,
parts: http::request::Parts,
) -> Result<BoxResponse, BoxResponse> {
) -> HttpResult<BoxResponse> {
let peer_info = Self::peer_info_for_stateless_request(&request, &parts.headers);
request.request.extensions_mut().insert(parts);
let (transport, mut receiver) =
@ -1279,10 +1262,10 @@ where
/// per name to read its `ServerHandler::get_tool` definition. Used to
/// validate SEP-2243 `Mcp-Param-*` headers against the request body.
fn tool_schema(&self, name: &str) -> Option<Arc<JsonObject>> {
if let Ok(cache) = self.tool_schemas.read() {
if let Some(schema) = cache.get(name) {
return schema.clone();
}
if let Ok(cache) = self.tool_schemas.read()
&& let Some(schema) = cache.get(name)
{
return schema.clone();
}
let schema = self
.get_service()
@ -1472,23 +1455,15 @@ where
Some(init_done_tx),
);
if let Err(e) = self
.session_manager
self.session_manager
.initialize_session(session_id, restore_init)
.await
.map_err(|e| std::io::Error::other(e.to_string()))
{
return Err(e);
}
.map_err(|e| std::io::Error::other(e.to_string()))?;
if let Err(e) = self
.session_manager
self.session_manager
.accept_message(session_id, restore_initialized)
.await
.map_err(|e| std::io::Error::other(e.to_string()))
{
return Err(e);
}
.map_err(|e| std::io::Error::other(e.to_string()))?;
if init_done_rx.await.is_err() {
return Err(std::io::Error::other(
@ -1513,7 +1488,7 @@ where
if let Err(response) =
validate_dns_rebinding_headers(request.uri(), request.headers(), &self.config)
{
return response;
return response.into_response();
}
let method = request.method().clone();
let supports_stateless_replay = self.session_manager.event_store().is_some();
@ -1540,10 +1515,10 @@ where
};
match result {
Ok(response) => response,
Err(response) => response,
Err(response) => response.into_response(),
}
}
async fn handle_get<B>(&self, request: Request<B>) -> Result<BoxResponse, BoxResponse>
async fn handle_get<B>(&self, request: Request<B>) -> HttpResult<BoxResponse>
where
B: Body + Send + 'static,
B::Error: Display,
@ -1686,7 +1661,7 @@ where
))
}
async fn handle_post<B>(&self, request: Request<B>) -> Result<BoxResponse, BoxResponse>
async fn handle_post<B>(&self, request: Request<B>) -> HttpResult<BoxResponse>
where
B: Body + Send + 'static,
B::Error: Display,
@ -1838,7 +1813,7 @@ where
let stored_init_params = match &mut message {
ClientJsonRpcMessage::Request(req) => {
let ClientRequest::InitializeRequest(init_req) = &req.request else {
return Err(unexpected_message_response("initialize request"));
return Err(unexpected_message_response("initialize request").into());
};
// Reject mismatched MCP-Protocol-Version header before binding the session to anything.
validate_header_matches_init_body(
@ -1856,7 +1831,7 @@ where
stored_init_params
}
_ => {
return Err(unexpected_message_response("initialize request"));
return Err(unexpected_message_response("initialize request").into());
}
};
let service = self
@ -2013,7 +1988,8 @@ where
std::io::ErrorKind::UnexpectedEof,
"no response message received from handler",
),
));
)
.into());
};
tracing::trace!(?message);
if matches!(
@ -2045,7 +2021,7 @@ where
}
}
async fn handle_delete<B>(&self, request: Request<B>) -> Result<BoxResponse, BoxResponse>
async fn handle_delete<B>(&self, request: Request<B>) -> HttpResult<BoxResponse>
where
B: Body + Send + 'static,
B::Error: Display,

View file

@ -380,10 +380,10 @@ async fn test_mcp_custom_headers_sent_to_server() -> anyhow::Result<()> {
let mut headers_map = HashMap::new();
for (name, value) in headers.iter() {
let name_str = name.as_str();
if name_str.starts_with("x-") {
if let Ok(v) = value.to_str() {
headers_map.insert(name_str.to_string(), v.to_string());
}
if name_str.starts_with("x-")
&& let Ok(v) = value.to_str()
{
headers_map.insert(name_str.to_string(), v.to_string());
}
}
@ -392,48 +392,48 @@ async fn test_mcp_custom_headers_sent_to_server() -> anyhow::Result<()> {
stored.extend(headers_map);
// Parse the MCP request
if let Ok(json_body) = serde_json::from_slice::<serde_json::Value>(&body) {
if let Some(method) = json_body.get("method").and_then(|m| m.as_str()) {
if method == "initialize" {
state.initialize_called.notify_one();
// Return a valid MCP initialize response with session header
let response = json!({
"jsonrpc": "2.0",
"id": json_body.get("id"),
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"serverInfo": {
"name": "test-server",
"version": "1.0.0"
}
if let Ok(json_body) = serde_json::from_slice::<serde_json::Value>(&body)
&& let Some(method) = json_body.get("method").and_then(|m| m.as_str())
{
if method == "initialize" {
state.initialize_called.notify_one();
// Return a valid MCP initialize response with session header
let response = json!({
"jsonrpc": "2.0",
"id": json_body.get("id"),
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"serverInfo": {
"name": "test-server",
"version": "1.0.0"
}
});
return (
StatusCode::OK,
[
(http::header::CONTENT_TYPE, "application/json"),
(
http::HeaderName::from_static("mcp-session-id"),
"test-session-123",
),
],
response.to_string(),
);
} else if method == "notifications/initialized" {
// For initialized notification, return 202 Accepted
return (
StatusCode::ACCEPTED,
[
(http::header::CONTENT_TYPE, "application/json"),
(
http::HeaderName::from_static("mcp-session-id"),
"test-session-123",
),
],
String::new(),
);
}
}
});
return (
StatusCode::OK,
[
(http::header::CONTENT_TYPE, "application/json"),
(
http::HeaderName::from_static("mcp-session-id"),
"test-session-123",
),
],
response.to_string(),
);
} else if method == "notifications/initialized" {
// For initialized notification, return 202 Accepted
return (
StatusCode::ACCEPTED,
[
(http::header::CONTENT_TYPE, "application/json"),
(
http::HeaderName::from_static("mcp-session-id"),
"test-session-123",
),
],
String::new(),
);
}
}

View file

@ -4,14 +4,12 @@
use std::sync::Arc;
use rmcp::{
ClientHandler, RoleServer, ServerHandler, ServiceExt,
ClientHandler, ServerHandler, ServiceExt,
handler::server::{router::prompt::PromptRouter, wrapper::Parameters},
model::{
ClientInfo, ContentBlock, GetPromptRequestParams, GetPromptResult, ListPromptsResult,
PaginatedRequestParams, PromptMessage, Role,
ClientInfo, ContentBlock, GetPromptRequestParams, GetPromptResult, PromptMessage, Role,
},
prompt, prompt_handler, prompt_router,
service::RequestContext,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

View file

@ -20,12 +20,6 @@ struct Request {
fields: HashMap<String, String>,
}
#[derive(Debug, schemars::JsonSchema, serde::Deserialize, serde::Serialize)]
struct Sum {
a: i32,
b: i32,
}
#[rmcp::prompt_router(router = "test_router")]
impl<T> TestHandler<T> {
#[rmcp::prompt]

View file

@ -375,7 +375,7 @@ fn test_tool_result_content_requires_content() {
#[case::array(serde_json::json!([{ "city": "SF", "temp": 72 }, { "city": "NY", "temp": 65 }]))]
#[case::string(serde_json::json!("sunny"))]
#[case::integer(serde_json::json!(42))]
#[case::float(serde_json::json!(3.14))]
#[case::float(serde_json::json!(3.5))]
#[case::boolean(serde_json::json!(true))]
fn tool_result_content_round_trips_non_object_structured_content(
#[case] structured: serde_json::Value,

View file

@ -1,5 +1,8 @@
#![cfg(all(feature = "server", feature = "client", not(feature = "local")))]
#![allow(deprecated)]
#![expect(
deprecated,
reason = "This test verifies request association for the deprecated sampling API"
)]
use std::sync::{Arc, Mutex};
@ -18,9 +21,11 @@ use tokio::{
sync::oneshot,
};
type RequestResultSender = oneshot::Sender<Result<(), ServiceError>>;
#[derive(Clone)]
struct SamplingServer {
outside: Arc<Mutex<Option<oneshot::Sender<Result<(), ServiceError>>>>>,
outside: Arc<Mutex<Option<RequestResultSender>>>,
}
impl ServerHandler for SamplingServer {

View file

@ -13,9 +13,9 @@ use rmcp::{
use serde_json::json;
#[derive(Debug, serde::Deserialize, rmcp::schemars::JsonSchema)]
pub struct SumArgs {
pub a: i32,
pub b: i32,
struct SumArgs {
a: i32,
b: i32,
}
#[derive(Clone)]

View file

@ -21,12 +21,6 @@ struct Request {
fields: HashMap<String, String>,
}
#[derive(Debug, schemars::JsonSchema, serde::Deserialize, serde::Serialize)]
struct Sum {
a: i32,
b: i32,
}
#[rmcp::tool_router(router = test_router_1)]
impl<T> TestHandler<T> {
#[rmcp::tool]

View file

@ -35,10 +35,10 @@ async fn mcp_handler(
let mut headers_map = HashMap::new();
for (name, value) in headers.iter() {
let name_str = name.as_str();
if name_str.starts_with("x-") || name_str == "host" {
if let Ok(v) = value.to_str() {
headers_map.insert(name_str.to_string(), v.to_string());
}
if (name_str.starts_with("x-") || name_str == "host")
&& let Ok(v) = value.to_str()
{
headers_map.insert(name_str.to_string(), v.to_string());
}
}
@ -46,46 +46,46 @@ async fn mcp_handler(
stored.extend(headers_map);
drop(stored);
if let Ok(json_body) = serde_json::from_slice::<serde_json::Value>(&body) {
if let Some(method) = json_body.get("method").and_then(|m| m.as_str()) {
if method == "initialize" {
state.initialize_called.notify_one();
let response = json!({
"jsonrpc": "2.0",
"id": json_body.get("id"),
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"serverInfo": {
"name": "test-unix-server",
"version": "1.0.0"
}
if let Ok(json_body) = serde_json::from_slice::<serde_json::Value>(&body)
&& let Some(method) = json_body.get("method").and_then(|m| m.as_str())
{
if method == "initialize" {
state.initialize_called.notify_one();
let response = json!({
"jsonrpc": "2.0",
"id": json_body.get("id"),
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"serverInfo": {
"name": "test-unix-server",
"version": "1.0.0"
}
});
return (
StatusCode::OK,
[
(http::header::CONTENT_TYPE, "application/json"),
(
http::HeaderName::from_static("mcp-session-id"),
"unix-test-session",
),
],
response.to_string(),
);
} else if method == "notifications/initialized" {
return (
StatusCode::ACCEPTED,
[
(http::header::CONTENT_TYPE, "application/json"),
(
http::HeaderName::from_static("mcp-session-id"),
"unix-test-session",
),
],
String::new(),
);
}
}
});
return (
StatusCode::OK,
[
(http::header::CONTENT_TYPE, "application/json"),
(
http::HeaderName::from_static("mcp-session-id"),
"unix-test-session",
),
],
response.to_string(),
);
} else if method == "notifications/initialized" {
return (
StatusCode::ACCEPTED,
[
(http::header::CONTENT_TYPE, "application/json"),
(
http::HeaderName::from_static("mcp-session-id"),
"unix-test-session",
),
],
String::new(),
);
}
}