turul_http_mcp_server/
json_rpc_responses.rs1use bytes::Bytes;
7use http_body_util::Full;
8use hyper::{Response, StatusCode, header};
9use serde_json::Value;
10use tracing::error;
11
12use turul_mcp_json_rpc_server::{
13 JsonRpcError, JsonRpcResponse, error::JsonRpcErrorObject, types::RequestId,
14};
15
16type JsonRpcBody = Full<Bytes>;
18
19pub fn jsonrpc_error_response(
22 id: RequestId,
23 code: i64,
24 message: &str,
25 data: Option<Value>,
26) -> Result<Response<JsonRpcBody>, hyper::Error> {
27 let error_obj = JsonRpcErrorObject {
28 code,
29 message: message.to_string(),
30 data,
31 };
32
33 let err = JsonRpcError::new(Some(id), error_obj);
34
35 let body_bytes = serde_json::to_vec(&err).unwrap_or_else(|e| {
36 error!("Failed to serialize JSON-RPC error: {}", e);
37 b"{}".to_vec()
38 });
39
40 Ok(Response::builder()
41 .status(StatusCode::OK)
42 .header(header::CONTENT_TYPE, "application/json")
43 .body(Full::new(Bytes::from(body_bytes)))
44 .unwrap())
45}
46
47pub fn jsonrpc_notification_response() -> Result<Response<JsonRpcBody>, hyper::Error> {
49 Ok(Response::builder()
50 .status(StatusCode::ACCEPTED) .header(header::CONTENT_TYPE, "application/json")
52 .body(Full::new(Bytes::new()))
53 .unwrap())
54}
55
56pub fn jsonrpc_success_response(
58 id: RequestId,
59 result: Value,
60) -> Result<Response<JsonRpcBody>, hyper::Error> {
61 let response = JsonRpcResponse::success(id, result);
62
63 let body_bytes = serde_json::to_vec(&response).unwrap_or_else(|e| {
64 error!("Failed to serialize JSON-RPC response: {}", e);
65 b"{}".to_vec()
66 });
67
68 Ok(Response::builder()
69 .status(StatusCode::OK)
70 .header(header::CONTENT_TYPE, "application/json")
71 .body(Full::new(Bytes::from(body_bytes)))
72 .unwrap())
73}
74
75pub fn jsonrpc_response_with_session(
77 response: JsonRpcResponse,
78 session_id: Option<String>,
79) -> Result<Response<JsonRpcBody>, hyper::Error> {
80 let body_bytes = serde_json::to_vec(&response).unwrap_or_else(|e| {
81 error!("Failed to serialize JSON-RPC response: {}", e);
82 b"{}".to_vec()
83 });
84
85 let mut builder = Response::builder()
86 .status(StatusCode::OK)
87 .header(header::CONTENT_TYPE, "application/json");
88
89 if let Some(session_id) = session_id {
90 builder = builder.header("Mcp-Session-Id", session_id);
91 }
92
93 Ok(builder.body(Full::new(Bytes::from(body_bytes))).unwrap())
94}
95
96pub fn method_not_allowed_response() -> Response<JsonRpcBody> {
98 Response::builder()
99 .status(StatusCode::METHOD_NOT_ALLOWED)
100 .header("Allow", "GET, POST, DELETE, OPTIONS")
101 .body(Full::new(Bytes::from("Method not allowed")))
102 .unwrap()
103}
104
105pub fn not_found_response() -> Response<JsonRpcBody> {
107 Response::builder()
108 .status(StatusCode::NOT_FOUND)
109 .body(Full::new(Bytes::from("Not Found")))
110 .unwrap()
111}
112
113pub fn bad_request_response(message: &str) -> Response<JsonRpcBody> {
115 let error_obj = JsonRpcErrorObject {
116 code: -32700, message: message.to_string(),
118 data: None,
119 };
120
121 let err = JsonRpcError::new(None, error_obj);
122
123 let body_bytes = serde_json::to_vec(&err).unwrap_or_else(|_| b"{}".to_vec());
124
125 Response::builder()
126 .status(StatusCode::BAD_REQUEST)
127 .header(header::CONTENT_TYPE, "application/json")
128 .body(Full::new(Bytes::from(body_bytes)))
129 .unwrap()
130}
131
132pub fn options_response() -> Response<JsonRpcBody> {
134 Response::builder()
135 .status(StatusCode::OK)
136 .header("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS")
137 .header(
138 "Access-Control-Allow-Headers",
139 "Content-Type, Accept, MCP-Protocol-Version, Mcp-Session-Id, Last-Event-ID",
140 )
141 .header("Access-Control-Max-Age", "86400")
142 .body(Full::new(Bytes::new()))
143 .unwrap()
144}
145
146pub fn sse_response_headers() -> http::response::Builder {
148 Response::builder()
149 .status(StatusCode::OK)
150 .header(header::CONTENT_TYPE, "text/event-stream")
151 .header(header::CACHE_CONTROL, "no-cache")
152 .header("Connection", "keep-alive")
153 .header("Access-Control-Allow-Origin", "*")
154}