rmcp_openapi/
openapi_to_tool.rs1use crate::openapi_spec::{OpenApiOperation, OpenApiParameter};
2use crate::server::ToolMetadata;
3use crate::tool_generator::ToolGenerator;
4use serde_json::{Value, json};
5
6pub fn convert_path_to_tool_metadata(
9 path_info: Value,
10 method: String,
11 path: String,
12) -> Result<ToolMetadata, serde_json::Error> {
13 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
23fn 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
60fn 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"); 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}