Инструменты
В главе Основы мы научились вызывать простой инструмент. В этом разделе подробнее рассмотрим, как вызывать инструменты, передавать аргументы, обрабатывать структурированные результаты и валидировать выходные данные по схемам инструментов, предоставляемым MCP-сервером.
Вызов инструмента
Для вызова инструмента используйте метод call_tool().
Он принимает имя инструмента и необязательные аргументы.
use neva::prelude::*;
#[tokio::main]
async fn main() -> Result<(), Error> {
let mut client = Client::new()
.with_options(|opt| opt
.with_stdio(
"cargo",
["run", "--manifest-path", "./neva-mcp-server/Cargo.toml"]));
client.connect().await?;
let args = ("name", "John");
let result = client.call_tool("hello", args).await?;
println!("{:?}", result.content);
client.disconnect().await
}
Передача аргументов
Если инструмент принимает один параметр, передайте кортеж с именем параметра и его значением:
let args = ("name", "John");
let result = client.call_tool("hello", args).await?;
Если инструмент принимает несколько параметров, передайте их в виде массива, Vec или HashMap:
let args = [
("name", "John"),
("say", "Hi"),
];
let result = client.call_tool("hello", args).await?;
Если инструмент не принимает параметров, передайте тип-единицу ():
let result = client.call_tool("hello", ()).await?;
Структурированное содержимое
Некоторые инструменты возвращают структурированные JSON-данные (см. спецификацию MCP Structured Content).
Доступ к ним можно получить напрямую через поле struct_content:
let result = client.call_tool("weather-forecast", args).await?;
println!("{:?}", result.struct_content);
Или десериализовать в типизированную структуру с помощью as_json():
#[derive(Debug, serde::Deserialize)]
struct Weather {
conditions: String,
temperature: f32,
humidity: f32,
}
let args = ("location", "London");
let result = client.call_tool("weather-forecast", args).await?;
let weather: Weather = result.as_json()?;
Валидация структурированных результатов
Хорошей практикой является валидация структурированных ответов по схеме выходных данных, которую должен предоставлять каждый MCP-сервер.
При вызове list_tools() вы получаете метаданные каждого инструмента, включая схемы входных и выходных данных.
#[json_schema(de, debug)]
struct Weather {
conditions: String,
temperature: f32,
humidity: f32,
}
// Получаем список доступных инструментов
let tools = client.list_tools(None).await?;
// Находим конкретный инструмент
let tool = tools.get("weather-forecast")
.expect("No weather-forecast tool found");
// Вызываем инструмент
let args = ("location", "London");
let result = client.call_tool(&tool.name, args).await?;
// Валидируем и десериализуем результат
let weather: Weather = tool
.validate(&result)
.and_then(|res| res.as_json())?;
Макрос json_schema автоматически выводит метаданные JSON-схемы из ваших Rust-структур, обеспечивая совместимость с serde.
Его поведение можно настроить с помощью атрибутов:
de— только десериализацияser— только сериализацияserde— и сериализация, и десериализацияdebug— включение отладочных метаданных в сгенерированную схему
Обучение на примерах
Полный пример доступен здесь.