64 lines
1.5 KiB
Rust
64 lines
1.5 KiB
Rust
|
|
use std::sync::Arc;
|
||
|
|
|
||
|
|
use axum::{
|
||
|
|
extract::State,
|
||
|
|
http::StatusCode,
|
||
|
|
routing::{get, post},
|
||
|
|
Json, Router,
|
||
|
|
};
|
||
|
|
use tokio::net::TcpListener;
|
||
|
|
|
||
|
|
use crate::handlers::RequestHandler;
|
||
|
|
use crate::protocol::JsonRpcRequest;
|
||
|
|
use crate::Result;
|
||
|
|
|
||
|
|
pub struct SseTransport {
|
||
|
|
host: String,
|
||
|
|
port: u16,
|
||
|
|
request_handler: Arc<RequestHandler>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl SseTransport {
|
||
|
|
pub fn new(host: String, port: u16, request_handler: Arc<RequestHandler>) -> Self {
|
||
|
|
Self {
|
||
|
|
host,
|
||
|
|
port,
|
||
|
|
request_handler,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fn router(&self) -> Router {
|
||
|
|
Router::new()
|
||
|
|
.route("/health", get(health_handler))
|
||
|
|
.route("/mcp", post(mcp_handler))
|
||
|
|
.with_state(self.request_handler.clone())
|
||
|
|
}
|
||
|
|
|
||
|
|
pub async fn bind(&self) -> Result<()> {
|
||
|
|
let addr_str = format!("{}:{}", self.host, self.port);
|
||
|
|
let listener = TcpListener::bind(&addr_str).await?;
|
||
|
|
|
||
|
|
tracing::info!("SSE transport listening on http://{}", addr_str);
|
||
|
|
|
||
|
|
let router = self.router();
|
||
|
|
axum::serve(listener, router).await?;
|
||
|
|
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn health_handler() -> impl axum::response::IntoResponse {
|
||
|
|
Json(serde_json::json!({
|
||
|
|
"status": "healthy",
|
||
|
|
"version": env!("CARGO_PKG_VERSION"),
|
||
|
|
}))
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn mcp_handler(
|
||
|
|
State(handler): State<Arc<RequestHandler>>,
|
||
|
|
Json(request): Json<JsonRpcRequest>,
|
||
|
|
) -> impl axum::response::IntoResponse {
|
||
|
|
let response = handler.handle(&request).await;
|
||
|
|
(StatusCode::OK, Json(response))
|
||
|
|
}
|