1use crate::middleware::Middleware;
4use crate::registry::*;
5use axum::extract::ws::WebSocket;
6use mocopr_core::monitoring::MonitoringSystem;
7use mocopr_core::prelude::*;
8use serde_json::json;
9use std::sync::Arc;
10use tracing::{debug, error, info, warn};
11
12pub struct McpServer {
14 info: Implementation,
15 capabilities: ServerCapabilities,
16 handler: Arc<ServerMessageHandler>,
17 middleware_stack: Vec<Box<dyn Middleware>>,
18 monitoring_system: Option<MonitoringSystem>,
19 bind_address: String,
20 port: u16,
21 enable_http: bool,
22 enable_websocket: bool,
23}
24
25impl McpServer {
26 pub fn builder() -> crate::builder::McpServerBuilder {
28 crate::builder::McpServerBuilder::new()
29 }
30
31 pub fn new(
33 info: Implementation,
34 capabilities: ServerCapabilities,
35 resource_registry: ResourceRegistry,
36 tool_registry: ToolRegistry,
37 prompt_registry: PromptRegistry,
38 middleware_stack: Vec<Box<dyn Middleware>>,
39 monitoring_system: Option<MonitoringSystem>,
40 bind_address: String,
41 port: u16,
42 enable_http: bool,
43 enable_websocket: bool,
44 ) -> Self {
45 let handler = Arc::new(ServerMessageHandler::new(
46 info.clone(),
47 capabilities.clone(),
48 resource_registry,
49 tool_registry,
50 prompt_registry,
51 ));
52
53 Self {
54 info,
55 capabilities,
56 handler,
57 middleware_stack,
58 monitoring_system,
59 bind_address,
60 port,
61 enable_http,
62 enable_websocket,
63 }
64 }
65
66 pub fn info(&self) -> &Implementation {
68 &self.info
69 }
70
71 pub fn capabilities(&self) -> &ServerCapabilities {
73 &self.capabilities
74 }
75
76 pub fn middleware(&self) -> &Vec<Box<dyn Middleware>> {
78 &self.middleware_stack
79 }
80
81 pub fn monitoring(&self) -> Option<&MonitoringSystem> {
83 self.monitoring_system.as_ref()
84 }
85
86 pub fn bind_address(&self) -> &str {
88 &self.bind_address
89 }
90
91 pub fn port(&self) -> u16 {
93 self.port
94 }
95
96 pub fn http_enabled(&self) -> bool {
98 self.enable_http
99 }
100
101 pub fn websocket_enabled(&self) -> bool {
103 self.enable_websocket
104 }
105
106 pub async fn run_stdio(&self) -> Result<()> {
108 info!("Starting MCP server with stdio transport");
109
110 let transport = mocopr_core::transport::stdio::StdioTransport::current_process();
111 let (session, mut events) =
112 mocopr_core::protocol::Session::new(Box::new(transport), self.handler.clone());
113
114 let session_events = tokio::spawn(async move {
116 while let Some(event) = events.recv().await {
117 match event {
118 mocopr_core::protocol::SessionEvent::Connected => {
119 info!("Client connected");
120 }
121 mocopr_core::protocol::SessionEvent::Disconnected => {
122 info!("Client disconnected");
123 break;
124 }
125 mocopr_core::protocol::SessionEvent::Initialized { client_info } => {
126 info!("Session initialized with client: {}", client_info.name);
127 }
128 mocopr_core::protocol::SessionEvent::Error { error } => {
129 error!("Session error: {}", error);
130 }
131 _ => {}
132 }
133 }
134 });
135
136 let session_result = session.run().await;
138
139 let _ = session_events.await;
141
142 session_result
143 }
144
145 pub async fn run(&self) -> Result<()> {
150 if self.enable_http && self.enable_websocket {
151 let addr = format!("{}:{}", self.bind_address, self.port);
153 info!("Starting server with HTTP and WebSocket on {}", addr);
154 self.run_http_with_websocket(&addr).await
155 } else if self.enable_websocket {
156 let addr = format!("{}:{}", self.bind_address, self.port);
158 self.run_websocket(&addr).await
159 } else if self.enable_http {
160 let addr = format!("{}:{}", self.bind_address, self.port);
162 self.run_http(&addr).await
163 } else {
164 self.run_stdio().await
166 }
167 }
168
169 pub async fn run_http(&self, addr: &str) -> Result<()> {
171 info!("Starting MCP server with HTTP transport on {}", addr);
172
173 use axum::{Router, routing::post};
174 use tower_http::cors::CorsLayer;
175
176 let handler = self.handler.clone();
177
178 let app = Router::new()
179 .route("/mcp", post(handle_http_request))
180 .layer(CorsLayer::permissive())
181 .with_state(handler);
182
183 let listener = tokio::net::TcpListener::bind(addr).await?;
184 info!("HTTP server listening on {}", addr);
185
186 axum::serve(listener, app).await?;
187 Ok(())
188 }
189
190 pub async fn run_http_with_websocket(&self, addr: &str) -> Result<()> {
192 info!(
193 "Starting MCP server with HTTP and WebSocket transport on {}",
194 addr
195 );
196
197 use axum::{
198 Router,
199 extract::ws::WebSocketUpgrade,
200 routing::{get, post},
201 };
202 use tower_http::cors::CorsLayer;
203
204 let handler = self.handler.clone();
205 let ws_handler = handler.clone();
206
207 let app = Router::new()
208 .route("/mcp", post(handle_http_request))
209 .route(
210 "/mcp/ws",
211 get(move |ws: WebSocketUpgrade| async move {
212 ws.on_upgrade(move |socket| handle_websocket(socket, ws_handler))
213 }),
214 )
215 .layer(CorsLayer::permissive())
216 .with_state(handler);
217
218 let listener = tokio::net::TcpListener::bind(addr).await?;
219 info!("HTTP+WebSocket server listening on {}", addr);
220
221 axum::serve(listener, app).await?;
222 Ok(())
223 }
224
225 pub async fn run_websocket(&self, addr: &str) -> Result<()> {
227 info!("Starting MCP server with WebSocket transport on {}", addr);
228
229 use axum::{Router, extract::ws::WebSocketUpgrade, routing::get};
230 use tower_http::cors::CorsLayer;
231
232 let handler = self.handler.clone();
233
234 let app = Router::new()
235 .route(
236 "/mcp",
237 get(move |ws: WebSocketUpgrade| async move {
238 ws.on_upgrade(move |socket| handle_websocket(socket, handler))
239 }),
240 )
241 .layer(CorsLayer::permissive());
242
243 let listener = tokio::net::TcpListener::bind(addr).await?;
244 info!("WebSocket server listening on {}", addr);
245
246 axum::serve(listener, app).await?;
247 Ok(())
248 }
249
250 pub fn resources(&self) -> &ResourceRegistry {
252 &self.handler.resources
253 }
254
255 pub fn tools(&self) -> &ToolRegistry {
257 &self.handler.tools
258 }
259
260 pub fn prompts(&self) -> &PromptRegistry {
262 &self.handler.prompts
263 }
264}
265
266async fn handle_mcp_method(
268 handler: &Arc<ServerMessageHandler>,
269 json_msg: &serde_json::Value,
270) -> Option<serde_json::Value> {
271 let method = match json_msg.get("method").and_then(|m| m.as_str()) {
272 Some(method) => method,
273 None => {
274 return Some(json!({
275 "jsonrpc": "2.0",
276 "error": {
277 "code": -32600,
278 "message": "Invalid Request"
279 },
280 "id": json_msg.get("id")
281 }));
282 }
283 };
284
285 let id = json_msg.get("id");
286 let params = json_msg.get("params");
287
288 let result = match method {
290 "ping" => {
291 let request = match params {
292 Some(p) => match serde_json::from_value::<PingRequest>(p.clone()) {
293 Ok(req) => req,
294 Err(_) => PingRequest { message: None },
295 },
296 None => PingRequest { message: None },
297 };
298 handler
299 .handle_ping(request)
300 .await
301 .map(|r| serde_json::to_value(r).unwrap())
302 }
303
304 "resources/list" => {
305 let request = match params {
306 Some(p) => serde_json::from_value::<ResourcesListRequest>(p.clone()),
307 None => Ok(ResourcesListRequest {
308 pagination: PaginationParams { cursor: None },
309 }),
310 };
311 match request {
312 Ok(req) => handler
313 .handle_resources_list(req)
314 .await
315 .map(|r| serde_json::to_value(r).unwrap()),
316 Err(e) => Err(mocopr_core::Error::InvalidRequest(e.to_string())),
317 }
318 }
319
320 "resources/read" => {
321 let request = match params
322 .and_then(|p| serde_json::from_value::<ResourcesReadRequest>(p.clone()).ok())
323 {
324 Some(req) => req,
325 None => {
326 return Some(json!({
327 "jsonrpc": "2.0",
328 "error": {
329 "code": -32602,
330 "message": "Invalid params for resources/read"
331 },
332 "id": id
333 }));
334 }
335 };
336 handler
337 .handle_resources_read(request)
338 .await
339 .map(|r| serde_json::to_value(r).unwrap())
340 }
341
342 "resources/subscribe" => {
343 let request = match params
344 .and_then(|p| serde_json::from_value::<ResourcesSubscribeRequest>(p.clone()).ok())
345 {
346 Some(req) => req,
347 None => {
348 return Some(json!({
349 "jsonrpc": "2.0",
350 "error": {
351 "code": -32602,
352 "message": "Invalid params for resources/subscribe"
353 },
354 "id": id
355 }));
356 }
357 };
358 handler
359 .handle_resources_subscribe(request)
360 .await
361 .map(|r| serde_json::to_value(r).unwrap())
362 }
363
364 "resources/unsubscribe" => {
365 let request = match params
366 .and_then(|p| serde_json::from_value::<ResourcesUnsubscribeRequest>(p.clone()).ok())
367 {
368 Some(req) => req,
369 None => {
370 return Some(json!({
371 "jsonrpc": "2.0",
372 "error": {
373 "code": -32602,
374 "message": "Invalid params for resources/unsubscribe"
375 },
376 "id": id
377 }));
378 }
379 };
380 handler
381 .handle_resources_unsubscribe(request)
382 .await
383 .map(|r| serde_json::to_value(r).unwrap())
384 }
385
386 "tools/list" => {
387 let request = match params {
388 Some(p) => serde_json::from_value::<ToolsListRequest>(p.clone()),
389 None => Ok(ToolsListRequest {
390 pagination: PaginationParams { cursor: None },
391 }),
392 };
393 match request {
394 Ok(req) => handler
395 .handle_tools_list(req)
396 .await
397 .map(|r| serde_json::to_value(r).unwrap()),
398 Err(e) => Err(mocopr_core::Error::InvalidRequest(e.to_string())),
399 }
400 }
401
402 "tools/call" => {
403 let request = match params
404 .and_then(|p| serde_json::from_value::<ToolsCallRequest>(p.clone()).ok())
405 {
406 Some(req) => req,
407 None => {
408 return Some(json!({
409 "jsonrpc": "2.0",
410 "error": {
411 "code": -32602,
412 "message": "Invalid params for tools/call"
413 },
414 "id": id
415 }));
416 }
417 };
418 handler
419 .handle_tools_call(request)
420 .await
421 .map(|r| serde_json::to_value(r).unwrap())
422 }
423
424 "prompts/list" => {
425 let request = match params {
426 Some(p) => serde_json::from_value::<PromptsListRequest>(p.clone()),
427 None => Ok(PromptsListRequest {
428 pagination: PaginationParams { cursor: None },
429 }),
430 };
431 match request {
432 Ok(req) => handler
433 .handle_prompts_list(req)
434 .await
435 .map(|r| serde_json::to_value(r).unwrap()),
436 Err(e) => Err(mocopr_core::Error::InvalidRequest(e.to_string())),
437 }
438 }
439
440 "prompts/get" => {
441 let request = match params
442 .and_then(|p| serde_json::from_value::<PromptsGetRequest>(p.clone()).ok())
443 {
444 Some(req) => req,
445 None => {
446 return Some(json!({
447 "jsonrpc": "2.0",
448 "error": {
449 "code": -32602,
450 "message": "Invalid params for prompts/get"
451 },
452 "id": id
453 }));
454 }
455 };
456 handler
457 .handle_prompts_get(request)
458 .await
459 .map(|r| serde_json::to_value(r).unwrap())
460 }
461
462 "logging/setLevel" => {
463 let request = match params
464 .and_then(|p| serde_json::from_value::<LoggingSetLevelRequest>(p.clone()).ok())
465 {
466 Some(req) => req,
467 None => {
468 return Some(json!({
469 "jsonrpc": "2.0",
470 "error": {
471 "code": -32602,
472 "message": "Invalid params for logging/setLevel"
473 },
474 "id": id
475 }));
476 }
477 };
478 handler
479 .handle_logging_set_level(request)
480 .await
481 .map(|r| serde_json::to_value(r).unwrap())
482 }
483
484 "notifications/initialized" => {
486 let notification = match params
487 .and_then(|p| serde_json::from_value::<InitializedNotification>(p.clone()).ok())
488 {
489 Some(notif) => notif,
490 None => InitializedNotification {},
491 };
492 match handler.handle_initialized(notification).await {
493 Ok(_) => return None, Err(_) => return None, }
496 }
497
498 _ => Err(mocopr_core::Error::MethodNotFound(method.to_string())),
500 };
501
502 match result {
504 Ok(value) => Some(json!({
505 "jsonrpc": "2.0",
506 "result": value,
507 "id": id
508 })),
509 Err(e) => Some(json!({
510 "jsonrpc": "2.0",
511 "error": {
512 "code": match &e {
513 mocopr_core::Error::MethodNotFound(_) => -32601,
514 mocopr_core::Error::InvalidRequest(_) => -32602,
515 _ => -32603,
516 },
517 "message": e.to_string()
518 },
519 "id": id
520 })),
521 }
522}
523
524async fn handle_websocket(mut socket: WebSocket, handler: Arc<ServerMessageHandler>) {
526 info!("WebSocket client connected");
527
528 let mut initialized = false;
530
531 while let Some(result) = socket.recv().await {
532 match result {
533 Ok(msg) => {
534 if let Ok(text) = msg.to_text() {
535 debug!("Received WebSocket message: {}", text);
536
537 match serde_json::from_str::<serde_json::Value>(text) {
539 Ok(json_msg) => {
540 let response_json = if !initialized {
541 if let Some(method) =
543 json_msg.get("method").and_then(|m| m.as_str())
544 {
545 if method == "initialize" {
546 match serde_json::from_value::<InitializeRequest>(
548 json_msg.clone(),
549 ) {
550 Ok(init_request) => {
551 match handler.handle_initialize(init_request).await
552 {
553 Ok(init_response) => {
554 initialized = true;
555 Some(json!({
556 "jsonrpc": "2.0",
557 "result": init_response,
558 "id": json_msg.get("id")
559 }))
560 }
561 Err(e) => Some(json!({
562 "jsonrpc": "2.0",
563 "error": {
564 "code": -32603,
565 "message": e.to_string()
566 },
567 "id": json_msg.get("id")
568 })),
569 }
570 }
571 Err(e) => Some(json!({
572 "jsonrpc": "2.0",
573 "error": {
574 "code": -32602,
575 "message": format!("Invalid initialize request: {}", e)
576 },
577 "id": json_msg.get("id")
578 })),
579 }
580 } else {
581 Some(json!({
583 "jsonrpc": "2.0",
584 "error": {
585 "code": -32002,
586 "message": "Server not initialized"
587 },
588 "id": json_msg.get("id")
589 }))
590 }
591 } else {
592 Some(json!({
593 "jsonrpc": "2.0",
594 "error": {
595 "code": -32600,
596 "message": "Invalid Request"
597 },
598 "id": json_msg.get("id")
599 }))
600 }
601 } else {
602 handle_mcp_method(&handler, &json_msg).await
604 };
605
606 if let Some(response) = response_json {
608 let response_text = serde_json::to_string(&response)
609 .unwrap_or_else(|_| {
610 json!({
611 "jsonrpc": "2.0",
612 "error": {
613 "code": -32603,
614 "message": "Internal error"
615 }
616 })
617 .to_string()
618 });
619
620 if let Err(e) = socket
621 .send(axum::extract::ws::Message::Text(response_text))
622 .await
623 {
624 error!("Failed to send WebSocket response: {}", e);
625 break;
626 }
627 }
628 }
629 Err(e) => {
630 error!("Failed to parse JSON message: {}", e);
631 let error_response = json!({
632 "jsonrpc": "2.0",
633 "error": {
634 "code": -32700,
635 "message": "Parse error"
636 },
637 "id": null
638 });
639 if let Err(e) = socket
640 .send(axum::extract::ws::Message::Text(error_response.to_string()))
641 .await
642 {
643 error!("Failed to send error response: {}", e);
644 break;
645 }
646 }
647 }
648 } else {
649 warn!("Received non-text WebSocket message, ignoring");
650 }
651 }
652 Err(e) => {
653 error!("WebSocket error: {}", e);
654 break;
655 }
656 }
657 }
658
659 info!("WebSocket client disconnected");
660}
661
662pub struct ServerMessageHandler {
664 pub info: Implementation,
665 pub capabilities: ServerCapabilities,
666 pub resources: ResourceRegistry,
667 pub tools: ToolRegistry,
668 pub prompts: PromptRegistry,
669}
670
671impl ServerMessageHandler {
672 pub fn new(
673 info: Implementation,
674 capabilities: ServerCapabilities,
675 resources: ResourceRegistry,
676 tools: ToolRegistry,
677 prompts: PromptRegistry,
678 ) -> Self {
679 Self {
680 info,
681 capabilities,
682 resources,
683 tools,
684 prompts,
685 }
686 }
687}
688
689#[async_trait::async_trait]
690impl MessageHandler for ServerMessageHandler {
691 async fn handle_initialize(&self, request: InitializeRequest) -> Result<InitializeResponse> {
692 if !Protocol::is_version_supported(&request.protocol_version) {
694 return Err(Error::InvalidRequest(format!(
695 "Unsupported protocol version: {}",
696 request.protocol_version
697 )));
698 }
699
700 info!(
701 "Client initialized: {} v{}",
702 request.client_info.name, request.client_info.version
703 );
704
705 Ok(InitializeResponse {
706 protocol_version: Protocol::latest_version().to_string(),
707 capabilities: self.capabilities.clone(),
708 server_info: self.info.clone(),
709 instructions: None,
710 })
711 }
712
713 async fn handle_resources_list(
714 &self,
715 request: ResourcesListRequest,
716 ) -> Result<ResourcesListResponse> {
717 self.resources.list_resources(request).await
718 }
719
720 async fn handle_resources_read(
721 &self,
722 request: ResourcesReadRequest,
723 ) -> Result<ResourcesReadResponse> {
724 self.resources.read_resource(request).await
725 }
726
727 async fn handle_resources_subscribe(
728 &self,
729 request: ResourcesSubscribeRequest,
730 ) -> Result<ResourcesSubscribeResponse> {
731 self.resources.subscribe_resource(request).await
732 }
733
734 async fn handle_resources_unsubscribe(
735 &self,
736 request: ResourcesUnsubscribeRequest,
737 ) -> Result<ResourcesUnsubscribeResponse> {
738 self.resources.unsubscribe_resource(request).await
739 }
740
741 async fn handle_tools_list(&self, request: ToolsListRequest) -> Result<ToolsListResponse> {
742 self.tools.list_tools(request).await
743 }
744
745 async fn handle_tools_call(&self, request: ToolsCallRequest) -> Result<ToolsCallResponse> {
746 self.tools.call_tool(request).await
747 }
748
749 async fn handle_prompts_list(
750 &self,
751 request: PromptsListRequest,
752 ) -> Result<PromptsListResponse> {
753 self.prompts.list_prompts(request).await
754 }
755
756 async fn handle_prompts_get(&self, request: PromptsGetRequest) -> Result<PromptsGetResponse> {
757 self.prompts.get_prompt(request).await
758 }
759}
760
761async fn handle_http_request(
763 axum::extract::State(_handler): axum::extract::State<Arc<ServerMessageHandler>>,
764 axum::Json(request): axum::Json<serde_json::Value>,
765) -> axum::Json<serde_json::Value> {
766 axum::Json(json!({
769 "jsonrpc": "2.0",
770 "error": {
771 "code": -32601,
772 "message": "HTTP transport not fully implemented yet - use WebSocket or stdio"
773 },
774 "id": request.get("id").cloned()
775 }))
776}