use serde_json::Value;
use turbomcp_core::context::{RequestContext, TransportType};
use turbomcp_core::error::{McpError, McpResult};
use turbomcp_core::handler::McpHandler;
use turbomcp_core::jsonrpc::{JsonRpcIncoming, JsonRpcOutgoing};
use turbomcp_core::router::{RouteConfig, route_request};
use worker::{Request, Response};
pub trait WasmHandlerExt: McpHandler {
fn handle_worker_request(
&self,
req: Request,
) -> impl std::future::Future<Output = worker::Result<Response>>;
fn handle_json_rpc_request(
&self,
request: Value,
) -> impl std::future::Future<Output = McpResult<Value>>;
}
impl<T: McpHandler> WasmHandlerExt for T {
fn handle_worker_request(
&self,
mut req: Request,
) -> impl std::future::Future<Output = worker::Result<Response>> {
let handler = self.clone();
async move {
let body = req.text().await?;
let request: JsonRpcIncoming = match serde_json::from_str(&body) {
Ok(r) => r,
Err(e) => {
let response = JsonRpcOutgoing::error(
None,
McpError::parse_error(format!("Invalid JSON: {}", e)),
);
return Response::from_json(&response);
}
};
let request_id = request
.id
.as_ref()
.map(|v| v.to_string())
.unwrap_or_else(|| "wasm-request".to_string());
let ctx = RequestContext::new(request_id, TransportType::Wasm);
let config = RouteConfig::default();
let response = route_request(&handler, request, &ctx, &config).await;
if response.should_send() {
Response::from_json(&response)
} else {
Response::empty()
}
}
}
fn handle_json_rpc_request(
&self,
request: Value,
) -> impl std::future::Future<Output = McpResult<Value>> {
let handler = self.clone();
async move {
let request: JsonRpcIncoming = serde_json::from_value(request)
.map_err(|e| McpError::parse_error(format!("Invalid request: {}", e)))?;
let request_id = request
.id
.as_ref()
.map(|v| v.to_string())
.unwrap_or_else(|| "wasm-request".to_string());
let ctx = RequestContext::new(request_id, TransportType::Wasm);
let config = RouteConfig::default();
let response = route_request(&handler, request, &ctx, &config).await;
serde_json::to_value(&response)
.map_err(|e| McpError::internal(format!("Serialization error: {}", e)))
}
}
}