rmcp_openapi/
openapi_to_tool.rs

1use crate::openapi_spec::{OpenApiOperation, OpenApiParameter};
2use crate::server::ToolMetadata;
3use crate::tool_generator::ToolGenerator;
4use serde_json::{Value, json};
5
6/// Legacy function for backward compatibility
7/// Use ToolGenerator::generate_tool_metadata for new code
8pub fn convert_path_to_tool_metadata(
9    path_info: Value,
10    method: String,
11    path: String,
12) -> Result<ToolMetadata, serde_json::Error> {
13    // Convert to OpenApiOperation and use the new generator
14    let operation = convert_to_operation(path_info, method, path)?;
15    ToolGenerator::generate_tool_metadata(&operation).map_err(|e| {
16        serde_json::Error::io(std::io::Error::new(
17            std::io::ErrorKind::InvalidData,
18            e.to_string(),
19        ))
20    })
21}
22
23/// Convert legacy path_info format to OpenApiOperation
24fn convert_to_operation(
25    path_info: Value,
26    method: String,
27    path: String,
28) -> Result<OpenApiOperation, serde_json::Error> {
29    let operation_id = path_info["operationId"]
30        .as_str()
31        .unwrap_or(&format!(
32            "{}_{}",
33            method,
34            path.replace('/', "_").replace(['{', '}'], "")
35        ))
36        .to_string();
37
38    let summary = path_info["summary"].as_str().map(|s| s.to_string());
39    let description = path_info["description"].as_str().map(|s| s.to_string());
40
41    let mut parameters = Vec::new();
42    if let Some(params_array) = path_info["parameters"].as_array() {
43        for param in params_array {
44            if let Ok(parameter) = convert_to_parameter(param.clone()) {
45                parameters.push(parameter);
46            }
47        }
48    }
49
50    Ok(OpenApiOperation {
51        operation_id,
52        method,
53        path,
54        summary,
55        description,
56        parameters,
57    })
58}
59
60/// Convert legacy parameter format to OpenApiParameter
61fn convert_to_parameter(param_value: Value) -> Result<OpenApiParameter, serde_json::Error> {
62    let name = param_value["name"]
63        .as_str()
64        .ok_or_else(|| {
65            serde_json::Error::io(std::io::Error::new(
66                std::io::ErrorKind::InvalidData,
67                "Parameter missing 'name'",
68            ))
69        })?
70        .to_string();
71
72    let location_str = param_value["in"].as_str().unwrap_or("query"); // Default to query if not specified
73    let location = crate::openapi_spec::ParameterLocation::try_from(location_str)
74        .unwrap_or(crate::openapi_spec::ParameterLocation::Query);
75
76    let required = param_value["required"].as_bool().unwrap_or(false);
77    let description = param_value["description"].as_str().map(|s| s.to_string());
78
79    let schema = param_value["schema"].clone();
80    let schema = if schema.is_null() {
81        json!({"type": "string"})
82    } else {
83        schema
84    };
85
86    let param_type = schema["type"].as_str().unwrap_or("string").to_string();
87
88    Ok(OpenApiParameter {
89        name,
90        location,
91        required,
92        param_type,
93        description,
94        schema,
95    })
96}