use crate::mcp::{QualifiedMcpToolName, protocol::Tool};
use serde_json::{Value, json};
pub(crate) fn provider_tool_definition(qualified: &QualifiedMcpToolName, tool: &Tool) -> Value {
let name = qualified.as_str();
let description = tool
.description
.as_deref()
.or(tool.title.as_deref())
.map(str::trim)
.filter(|value| !value.is_empty())
.map(ToString::to_string)
.unwrap_or_else(|| format!("MCP tool from server {}", qualified.server()));
json!({
"type": "function",
"name": name,
"description": description,
"parameters": crate::tools::contract::with_required_intent(json!({
"type": "object",
"properties": {"arguments": object_schema_or_default(&tool.input_schema, name)},
"required": ["arguments"],
"additionalProperties": false
})),
})
}
fn object_schema_or_default(schema: &Value, name: &str) -> Value {
if schema.as_object().and_then(|object| object.get("type"))
== Some(&Value::String("object".to_string()))
{
let mut schema = schema.clone();
schema
.as_object_mut()
.expect("object schema")
.entry("$id")
.or_insert_with(|| json!(format!("urn:magi-code:mcp:{name}")));
schema
} else {
default_schema()
}
}
fn default_schema() -> Value {
json!({"type":"object","properties":{},"additionalProperties":true})
}