| 6334 | } |
| 6335 | |
| 6336 | fn normalize_mcp_server_config( |
| 6337 | mut value: serde_json::Value, |
| 6338 | ) -> PyResult<a3s_code_core::mcp::protocol::McpServerConfig> { |
| 6339 | let obj = value |
| 6340 | .as_object_mut() |
| 6341 | .ok_or_else(|| PyValueError::new_err("MCP server config must be a dict"))?; |
| 6342 | |
| 6343 | for key in [ |
| 6344 | "timeout_ms", |
| 6345 | "timeoutMs", |
| 6346 | "tool_timeout_ms", |
| 6347 | "toolTimeoutMs", |
| 6348 | ] { |
| 6349 | if let Some(timeout_ms) = obj.remove(key) { |
| 6350 | let timeout_ms = timeout_ms |
| 6351 | .as_u64() |
| 6352 | .ok_or_else(|| PyValueError::new_err(format!("{key} must be an integer")))?; |
| 6353 | obj.entry("toolTimeoutSecs".to_string()) |
| 6354 | .or_insert_with(|| serde_json::json!(timeout_ms_to_secs(timeout_ms))); |
| 6355 | break; |
| 6356 | } |
| 6357 | } |
| 6358 | |
| 6359 | if let Some(transport) = obj.get_mut("transport") { |
| 6360 | normalize_mcp_transport_alias(transport); |
| 6361 | } |
| 6362 | |
| 6363 | serde_json::from_value(value) |
| 6364 | .map_err(|e| PyValueError::new_err(format!("Invalid MCP server config: {e}"))) |
| 6365 | } |
| 6366 | |
| 6367 | fn normalize_mcp_transport_alias(transport: &mut serde_json::Value) { |
| 6368 | match transport { |