mcp_stdio_proxy/
mcp_error.rs1use axum::{
2 Json,
3 response::{IntoResponse, Response},
4};
5use http::StatusCode;
6use serde::{Deserialize, Serialize};
7use thiserror::Error;
8
9#[derive(Error, Debug)]
13pub enum AppError {
14 #[error("服务 {0} 未找到")]
16 ServiceNotFound(String),
17
18 #[error("服务 {0} 在重启冷却期内,请稍后再试")]
20 ServiceRestartCooldown(String),
21
22 #[error("服务 {0} 正在启动中,请稍后再试")]
24 ServiceStartupInProgress(String),
25
26 #[error("服务启动失败: {mcp_id}: {reason}")]
28 ServiceStartupFailed { mcp_id: String, reason: String },
29
30 #[error("后端连接错误: {0}")]
32 BackendConnection(String),
33
34 #[error("配置解析错误: {0}")]
36 ConfigParse(String),
37
38 #[error("MCP 服务器错误: {0}")]
40 McpServerError(#[from] anyhow::Error),
41
42 #[error("JSON 序列化错误: {0}")]
44 SerdeJsonError(#[from] serde_json::Error),
45
46 #[error("IO 错误: {0}")]
48 IoError(#[from] std::io::Error),
49
50 #[error("路由未找到: {0}")]
52 RouteNotFound(String),
53
54 #[error("无效的请求参数: {0}")]
56 InvalidParameter(String),
57}
58
59impl AppError {
60 pub fn error_code(&self) -> &'static str {
62 match self {
63 Self::ServiceNotFound(_) => "0001",
64 Self::ServiceRestartCooldown(_) => "0002",
65 Self::ServiceStartupInProgress(_) => "0003",
66 Self::ServiceStartupFailed { .. } => "0004",
67 Self::BackendConnection(_) => "0005",
68 Self::ConfigParse(_) => "0006",
69 Self::McpServerError(_) => "0007",
70 Self::SerdeJsonError(_) => "0008",
71 Self::IoError(_) => "0009",
72 Self::RouteNotFound(_) => "0010",
73 Self::InvalidParameter(_) => "0011",
74 }
75 }
76
77 pub fn status_code(&self) -> StatusCode {
79 match self {
80 Self::ServiceNotFound(_) => StatusCode::NOT_FOUND,
81 Self::ServiceRestartCooldown(_) => StatusCode::TOO_MANY_REQUESTS,
82 Self::ServiceStartupInProgress(_) => StatusCode::SERVICE_UNAVAILABLE,
83 Self::ServiceStartupFailed { .. } => StatusCode::INTERNAL_SERVER_ERROR,
84 Self::BackendConnection(_) => StatusCode::BAD_GATEWAY,
85 Self::ConfigParse(_) => StatusCode::BAD_REQUEST,
86 Self::McpServerError(_) => StatusCode::INTERNAL_SERVER_ERROR,
87 Self::SerdeJsonError(_) => StatusCode::BAD_REQUEST,
88 Self::IoError(_) => StatusCode::INTERNAL_SERVER_ERROR,
89 Self::RouteNotFound(_) => StatusCode::NOT_FOUND,
90 Self::InvalidParameter(_) => StatusCode::BAD_REQUEST,
91 }
92 }
93}
94
95#[derive(Debug, Serialize, Deserialize)]
96pub struct ErrorOutput {
97 pub code: String,
98 pub error: String,
99}
100
101impl ErrorOutput {
102 pub fn with_code(code: &'static str, error: impl Into<String>) -> Self {
103 Self {
104 code: code.to_string(),
105 error: error.into(),
106 }
107 }
108}
109
110impl IntoResponse for AppError {
111 fn into_response(self) -> Response<axum::body::Body> {
112 (
113 self.status_code(),
114 Json(ErrorOutput::with_code(self.error_code(), self.to_string())),
115 )
116 .into_response()
117 }
118}