mcp-stdio-proxy 0.2.8

MCP (Model Context Protocol) proxy server and CLI tool for protocol conversion and remote service access
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use serde::{Deserialize, Serialize, Serializer, ser::SerializeStruct};
use utoipa::ToSchema;

#[allow(dead_code)]
#[derive(Debug, Deserialize, ToSchema)]
pub struct HttpResult<T> {
    pub code: String,
    pub message: String,
    pub data: Option<T>,
    pub tid: Option<String>,
    // 手写 Serialize 恒输出该字段;skip_deserializing 仅让 derive(Deserialize)
    // 走 Default(与原 #[serde(skip)] 行为一致),同时 utoipa 不会把它排除出 schema
    #[serde(skip_deserializing)]
    pub success: bool,
}

impl<T> HttpResult<T> {
    pub fn success(data: T, tid: Option<String>) -> Self {
        HttpResult {
            code: "0000".to_string(),
            message: "成功".to_string(),
            data: Some(data),
            tid,
            success: true,
        }
    }

    pub fn error(code: &str, message: &str, tid: Option<String>) -> Self {
        HttpResult {
            code: code.to_string(),
            message: message.to_string(),
            data: None,
            tid,
            success: false,
        }
    }
}

impl<T: Serialize> Serialize for HttpResult<T> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state = serializer.serialize_struct("HttpResult", 5)?;
        state.serialize_field("code", &self.code)?;
        state.serialize_field("message", &self.message)?;
        state.serialize_field("data", &self.data)?;
        state.serialize_field("tid", &self.tid)?;
        let is_success = self.code == "0000";
        state.serialize_field("success", &is_success)?;
        state.end()
    }
}

impl<T: Serialize> IntoResponse for HttpResult<T> {
    fn into_response(self) -> Response {
        match serde_json::to_string(&self) {
            Ok(body) => (
                StatusCode::OK,
                [(axum::http::header::CONTENT_TYPE, "application/json")],
                body,
            )
                .into_response(),
            Err(_) => (
                StatusCode::INTERNAL_SERVER_ERROR,
                [(axum::http::header::CONTENT_TYPE, "text/plain")],
                "Internal Server Error",
            )
                .into_response(),
        }
    }
}