Как использовать “MCP-серверы”
В предыдущем уроке вы узнали, как добавить к агенту дополнительные инструменты. Для этого нужно передать модели описание инструментов в виде подробной JSON-схемы всех функций и параметров. На основе этого модель решит, какую функцию вызывать. При этом в программном коде нужно отработать вызов функции.
ЛогикаНо часто нужна простая, готовая функциональность для агента, например запрос погоды или отправка email. Протокол MCP позволяет подключать такие функции напрямую, чтобы модель могла ими пользоваться без дополнительной настройки.

MCP-серверы — это инструменты удалённого вызова
Что такое MCP
💡 MCP (Model Context Protocol) — это удалённый вызов инструментов.Функциональность инструмента реализуется на удалённом сервере, а агент получает адрес этого MCP-сервера. Агент автоматически запрашивает список доступных инструментов с их описанием и при необходимости выполняет удалённый вызов.

Работа MCP-сервера с агентом
Ранее фитнес-ассистент сохранял выполненные упражнения как заметки, но они были доступны только внутри агента.
Если использовать MCP-сервер для хранения заметок, то:
- Логика заметок полностью реализуется на сервере, не загружая агент. Это разделяет функции агента и инструмента.
- Один MCP-сервер можно использовать с разными агентами или диалоговыми инструментами вроде ChatGPT — достаточно указать его адрес. Заметки из фитнес-ассистента можно обрабатывать и делать выводы в другом приложении или интерфейсе.
- Можно подключать разные сервисы ведения заметок. Например, если заметки ведутся в Obsidian и доступен соответствующий MCP-сервер, фитнес-ассистент автоматически адаптируется под возможности сервера.
Виды MCP-серверов
Протокол MCP можно использовать для вызова функций на удалённом сервере и для общения между инструментами на одном устройстве/сервере. Протокол MCP можно реализовать тремя способами:
- Через стандартный ввод-вывод. Такой подход чаще всего используется для запуска локальных MCP-инструментов.
- HTTP + SSE. Наиболее используемый подход, когда агент посылает запрос по протоколу HTTP, а результат возвращается в виде SSE (Server-Sent Events). Это обеспечивает постепенный возврат результата агенту для поддержки потоковой генерации ответа.
- Потоковый HTTP. Позволяет установить потоковое соединение с сервером. Он работает только для stateless-сессий.
Механика вызова MCP
Выше вы рассмотрели упрощённую схему вызова MCP-инструментов. На практике возникают следующие особенности:
- Для критических функций (например, списание денег, изменение документа или отправка email от имени пользователя) важно подтверждать или отклонять действие. Так как вызов MCP происходит в облаке, предусмотрен промежуточный шаг: получение подтверждения на вызов. В запросе можно указать, требуется ли оно.
- MCP-сервер предоставляет множество инструментов, но чтобы использовать только часть из них, перед вызовом модели выполняется фильтрация инструментов. Это помогает лучше ориентироваться и принимать правильные решения о вызове.

Диаграмма состояний вызова MCP-инструмента в Responses API
Как реализовать свой MCP-сервер
В качестве практики вы можете повторить шаги. Полный код проекта доступен в репозитории на GitHub.Реализовать свой MCP-сервер на языке Python можно через использование библиотеки FastMCP. Достаточно описать необходимые функции на языке Python и декорировать их с помощью @mcp.tool.Например, нужно реализовать MCP-сервер для хранения заметок. Функция добавления заметок может выглядеть так:
from fastmcp import FastMCP
from datetime import datetime
mcp = FastMCP("PersonalNotes")
NOTES_BY_ID: dict[int, dict] = {}
NEXT_ID = 1
@mcp.tool(description="Добавить заметку в блокнот")
def add_note(title: str, body: str, notebook: str = "scrapbook") -> dict:
"""Создаёт новую заметку и сохраняет её в блокнот.
Args:
title: Заголовок заметки. Не может быть пустым.
body: Текст заметки. Не может быть пустым.
notebook: Имя блокнота. Если не указано, используется ``"scrapbook"``.
"""
global NEXT_ID
note = {
"id": NEXT_ID,
"notebook": notebook,
"created_at": datetime.now().to_iso_format(),
"title": title,
"body": body
}
NOTES_BY_ID[NEXT_ID] = note
NEXT_ID += 1
return note
Всё, что нужно было сделать, — это декорировать функцию, написать её словесное описание (по которому LLM будет принимать решение, вызывать ли инструмент или нет) и указать типизацию всех аргументов — она помогает построить правильную схему вызова функции и определить, какие параметры являются обязательными.Для подключения функции к MCP достаточно:
- Декорировать функцию.
- Составить её описание, по которому LLM решает, вызывать инструмент или нет.
- Указать типизацию всех аргументов — это помогает построить корректную схему вызова и определить обязательные параметры.
if __name__ == "__main__":
mcp.run(transport="sse", host="0.0.0.0", port="8000")
📚 Полный код заметок MCP-сервера содержится в GitHub-репозитории.Для запуска MCP-сервера нужна среда выполнения, например виртуальная машина в облаке Yandex Cloud. Загрузите на неё файл notes.py из репозитория и выполните команду:
python notes.py
В сообщениях сервера будет указан адрес для подключения к серверу.
Использование MCP-сервера
Для использования MCP-сервера достаточно передать информацию о нём в виде инструмента в Responses API. Описание инструмента:
notes_tool = {
"type": "mcp",
"server_label": "PersonalNotes",
"server_url": "http://cathy.ycloud.eazify.net:8000/sse",
# Это адрес виртуальной машины
"require_approval": "never",
}
Здесь указывается название сервера и адрес виртуальной машины. Остальную информацию о назначении сервера, доступных инструменах и их параметрах модель запрашивает у MCP-сервера перед началом работы над запросом.Запрос к LLM с использованием заметок MCP-сервиса:
res = client.responses.create(
model=model,
tools=[notes_tool],
input="Добавь в мой дневник заметку о том, что я сегодня купил хлеб и молоко"
)
Запрос к MCP-серверу происходит на стороне облака. Параметр require_approval=never указывает, что в ответе можно проследить за совершёнными вызовами:
for x in res.output:
if x.type=='mcp_call':
print(f" + Вызов {x.name}{x.arguments}")
print(f" Результат: {x.output}")
Будет получен следующий ответ:
+ Вызов add_note{"title": "Покупки", "body": "Сегодня купил хлеб и молоко.", "notebook": "дневник"}
Результат: {"id":1,"notebook":"дневник","created_at":"2026-02-18T09:04:51Z","title":"Покупки","body":"Сегодня купил хлеб и молоко."}
Если MCP-инструмент выполняет критическое действие, например списание средств с аккаунта, необходимо предоставить пользователю возможность подтвердить операцию. Для этого указывается параметр require_approval=always. Перед вызовом MCP-инструмента Responses API возвращает ответ типа mcp_approval_request с названием инструмента и параметрами запроса. После получения подтверждения от пользователя его можно передать в следующем вызове client.responses.create.
MCP Hub в Yandex Cloud
В примере выше для размещения MCP-сервера потребовались вычислительные ресурсы — виртуальная машина, где выполняется код сервера. Иногда сервер нужен только как шлюз для существующих API по протоколу MCP, переадресующий вызовы другому сервису.Для таких случаев в Yandex Cloud есть встроенный MCP-шлюз — MCP Server Gateway. Он позволяет представлять разные ресурсы как MCP-сервер: от бессерверных функций до REST API.

Представьте задачу: фитнес-ассистент должен предложить оптимальный вариант тренировки на сегодня. Логично учитывать погодные условия — в солнечную погоду подойдёт пробежка на улице, а в дождь или мороз лучше выбрать занятие в помещении. Для такого сценария модели требуется доступ к актуальной погоде.Получить данные о погоде можно через сервис OpenWeather. Он предоставляет REST-интерфейс и позволяет запрашивать погодные данные по географическим координатам или по названию города. Нужно отправить GET-запрос вида [https://api.openweathermap.org/data/2.5/weather?q={city name}&appid={API key}](https://api.openweathermap.org/data/2.5/weather?q={city name}&appid={API key}). При необходимости можно добавить параметр units=metric, чтобы получить температуру в градусах Цельсия. API-ключ выдаётся после регистрации на сайте.Этот REST-интерфейс удобно обернуть в MCP-сервер через MCP Hub. Для этого:1️⃣ Войдите в раздел MCP Servers в интерфейсе AI Studio.2️⃣ Выберите Создать MCP-сервер → Создать.3️⃣ Ниже в списке инструментов выберите HTTPS-запрос.

Создание MCP-сервера для REST API

4️⃣ Настройте параметры инструмента. В данном случае это будет один инструмент для получения текущей погоды в городе, с единственным параметром city— названием города. При необходимости в этот же MCP-сервер можно добавить и другие инструменты, например для получения прогноза погоды, которые будут транслироваться в соответствующие REST-запросы.

Задание параметров инструмента MCP-сервера💡
В описании параметра city указано, что название города должно быть на английском — в том формате, который ожидает REST API. Поэтому, если пользователь спросит о погоде в Москве, модель сама переведёт название и вызовет MCP-инструмент с параметром city=Moscow.5️⃣ Укажите параметры MCP-сервера. Сделайте его публичным:

Задание параметров MCP-сервера
6️⃣ Теперь скопируйте базовый URL MCP-сервера. Он будет выглядеть примерно так: https://db8ubou2m0vmu17biigk.58zke0qh.mcpgw.serverless.yandexcloud.net/sse.Процесс создания MCP-сервера, который вызывает REST API OpenWeatherMap:https://code.s3.yandex.net/Cloud/mcp-hub-rest-new.mp4?etag=73022a66da220bf312016f6be357420c
7️⃣ Для вызова сервера задайте его описание в виде словаря и передайте в параметр запроса:
weather_tool = {
"type": "mcp",
"server_label": "weather",
"server_url": "https://db8ubou2m0vmu17biigk.58zke0qh.mcpgw.serverless.yandexcloud.net/sse",
"require_approval": "never",
}
res = client.responses.create(
model=model,
tools=[weather_tool],
input="Какая погода в Москве?",
)
printx(res.output_text)
8️⃣ Чтобы убедиться, что MCP-сервер был вызван, проинспектируйте ответ модели на наличие записей типа mcp_call:
for x in res.output:
if x.type=='mcp_call':
print(f" + Вызов {x.name}{x.arguments}")
print(f" Результат: {x.output}")
Будет получен примерно такой результат:
+ Вызов getweather{"city": "Moscow"}
Результат: {"coord":{"lon":37.6156,"lat":55.7522},"weather":[{"id":801,"main":"Clouds","description":"few clouds"}],"base":"stations","main" {"temp":-11.43,"feels_like":-17.91, "temp_min":-11.46,"temp_max":-10.71,"pressure":1015,"humidity":85}, "visibility":10000,"wind":{"speed":3.59,"deg":352,"gust":5.77},
"clouds":{"all":22},"dt":1771326993,"sys":{"country":"RU","sunrise":1771303826, "sunset":1771339018},"timezone":10800,"id":524901,"name":"Moscow","cod":200}
MCP-сервер на Cloud Functions
Часто MCP-сервер выступает в роли лёгкого посредника между агентом и внешними сервисами. Если каждый вызов MCP-инструмента можно напрямую преобразовать в один REST-запрос — отлично, достаточно подхода из предыдущего примера. Но бывает и сложнее: один содержательный вызов инструмента требует нескольких REST-запросов, дополнительной логики или преобразования данных. То есть нужен небольшой кусок кода.
Для таких задач удобно использовать бессерверные вычисления — Cloud Functions. Это фрагменты кода, которые выполняет облачная среда — вам не нужно выделять вычислительные ресурсы для этой задачи. Например, OpenWeatherMap рекомендует не передавать название города напрямую при запросе погоды. Вместо этого сначала нужно вызвать GeoCoding API, получить координаты — и только затем запрашивать погоду по широте и долготе. Такой небольшой конвейер действий удобно оформить в виде облачной функции:
import os
import requests
def get_weather(event, context):
city = event['city']
api_key = os.environ['api_key']
geo = requests.get(f"http://api.openweathermap.org/geo/1.0/direct?q={city}&limit=1&appid={api_key}").json()
lat = geo[0]['lat']
lon = geo[0]['lon']
res = requests.get(f"https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={api_key}&units=metric")
return {
'statusCode': 200,
'body': res.json(),
}
При определении этой функции нужно задать ключ appid для OpenWeatherMap в виде переменной окружения или секрета Yandex Locker.Далее мы описываем MCP-сервер примерно также, как описано выше, выбирая инструмент типа Cloud Function (вместо HTTPS-запрос) и выбирая созданную нами выше функцию.Процесс создания MCP-сервера на основе Cloud Function:https://code.s3.yandex.net/Cloud/mcp-hub-serverless-new.mp4?etag=f44c970a8e799068fe818707db329568
Использование MCP-серверов в фитнес-ассистенте
Теперь осталось подключить MCP-серверы к фитнес-ассистенту. Делается это максимально просто: вы уже заранее описали два инструмента — сервер персональных заметок (notes_tool) и сервер погоды (weather_tool). Поэтому единственное, что требуется, — передать их в список инструментов при создании агента:
instruction = """
Ты — опытный фитнес-тренер, задача которого — помочь мне тренироваться в зале. Ты можешь советовать упражнения, давать рекомендации по питанию и т. д. Отвечай на основе имеющейся дополнительной информации из файловой базы знаний, вызывая инструмент поиска `search_tool`.
В случае, если запрос касается упоминания абстрактных фитнес-клубов или новостей, используй поиск в интернет `web_search_tool`. Если тебя спрашивают про рекомендации о физической активности или стоит ли сегодня заниматься на улице, используй `weather_tool` для получения информации о погоде.
Ты также можешь вести дневник выполненных пользователем упражнений — для этого используй MCP-сервер PersonalNotes и веди заметки в блокноте "Упражнения" .
"""
assistant = Agent(instruction,
[web_search_tool, search_tool, notes_tool, weather_tool],
tool_choice='required')
res = assistant("Скажи, стоит ли сегодня побегать?")
printx(res.output_text)
Вы получите примерно такой ответ:
Чтобы ответить на вопрос, стоит ли сегодня бегать, мне нужно узнать погодные условия. Подскажи, в каком городе ты находишься или планируешь бегать?
Почему так произошло? В MCP-сервере параметр city указан как обязательный, но модель не знает, какой именно город нужно подставить. Поэтому она уточняет это у пользователя. Как только вы назовёте город, эта информация сохранится в текущем контексте — и в дальнейшем, пока идёт тот же диалог, модель уже не будет задавать этот вопрос повторно:
res = assistant("Я в Москве")
printx(res.output_text)
💡 Чтобы агент не задавал уточняющих вопросов, ему передают дополнительную информацию в системном промпте: местоположение пользователя, текущие дату и время, предпочтения.Альтернативный подход — дать агенту инструменты для доступа к профилю пользователя, чтобы он сначала искал недостающие данные в профиле или памяти. При необходимости агент использует другие инструменты для обработки дополнительных запросов.Вы также можете задавать другие вопросы, и будут вызываться соответствующие инструменты:
res = assistant("Решил побегать в зале, запиши это!")
printx(res.output_text)
Архитектурные преимущества MCP
В ассистенте используются только инструменты Responses API и MCP-серверы. Такая архитектура даёт несколько преимуществ.
- MCP-сервер — отдельное приложение, которое разрабатывается автономно. Разделение кода упрощает тестирование, поддержку и изоляцию функционала.
- Один MCP-сервер доступен нескольким агентам. Например, фитнес-агент фиксирует упражнения, агент покупок — формирует список товаров, а чат-интерфейс получает доступ ко всем записям.
- Агент может переключаться между MCP-серверами — достаточно лишь поменять адрес в списке инструментов. Это позволяет хранить данные в любом совместимом сервисе.
- Агент может использовать разные MCP-серверы — для этого достаточно поменять адрес в списке инструментов. Например, если вы хотите использовать записную книжку Obsidian для хранения списка упражнений — замените адрес MCP-сервера.
- MCP-сервер не обязан следовать единому API для ведения заметок. Он сам публикует набор доступных функций, и модель адаптируется под предоставленный интерфейс.
Ссылка: https://practicum.yandex.ru/trainer/yc-ml-aiagents/lesson/1744b192-fa0b-432f-8d82-5f47496563a7/
0 комментариев