Протокол контекста модели (MCP) и заметки о реализации сервера MCP на Go

Статья о спецификациях и реализации MCP на языке GO

Содержимое страницы

Здесь представлено описание Протокола Контекста Модели (MCP), краткие заметки о том, как реализовать MCP сервер на Go, включая структуру сообщений и спецификации протокола.

Роботы и MCP

Обзор Протокола Контекста Модели (MCP)

Протокол Контекста Модели (MCP) — это открытый, стандартизированный фреймворк (введенный Anthropic в конце 2024 года) для подключения языковых моделей ИИ к внешним источникам данных, инструментам и системам. Его цель — решить проблему «N×M интеграции», предоставив универсальный интерфейс для таких задач, как чтение файлов, выполнение функций (инструментов) и использование контекстных подсказок в различных приложениях. MCP — это не проприетарный или внутренний протокол; это открытый стандарт с официальной спецификацией и открытым исходным кодом. Крупные поставщики ИИ (включая OpenAI и Google DeepMind) объявили о поддержке MCP после его введения, подчеркивая, что он предназначен как широко используемый стандарт, а не решение для конкретного поставщика.

Назначение и архитектура MCP

MCP направлен на стандартизацию способов предоставления контекста LLM — часто используемая аналогия: «USB-C порт для приложений ИИ». Определяя общий протокол, MCP позволяет ИИ-ассистентам и инструментам беспрепятственно взаимодействовать с базами данных, файловыми системами, API и другими ресурсами без создания индивидуальных интеграций. Это помогает языковым моделям генерировать более релевантные и актуальные ответы, предоставляя им безопасный доступ к необходимым данным.

Архитектура: MCP следует модели клиент–сервер с четким разделением ролей:

  • MCP Хост: Родительское приложение (например, клиент чата или IDE), которое управляет подключениями. Оно содержит один или несколько MCP клиентов (коннекторов).
  • MCP Клиент: Экземпляр коннектора (внутри хоста), который устанавливает 1:1 сессию с MCP сервером. Клиент управляет жизненным циклом сессии, маршрутизирует сообщения и обеспечивает соблюдение пользовательских разрешений или политик безопасности.
  • MCP Сервер: Легковесная служба, которая предоставляет доступ к определенным возможностям (доступ к данным или функциям) через протокол MCP. Каждый сервер может оборачивать источник данных (файлы, БД, API и т.д.) или инструмент. Несколько серверов могут работать параллельно, каждый из которых предоставляет разные интеграции.
  • Источники данных/службы: Фактические ресурсы, с которыми работают серверы — это могут быть локальные файлы и базы данных или удаленные службы (веб-API, SaaS-приложения и т.д.). MCP сервер выступает в роли адаптера к этим ресурсам, обеспечивая доступ ЛЛМ только через стандартизированный протокол.

Этот дизайн вдохновлен Протоколом Языкового Сервера (LSP) из мира IDE. Так же, как LSP позволяет любому редактору поддерживать любой язык программирования через общий протокол, MCP позволяет любому приложению ИИ подключаться к любой интеграции данных/инструментов, которая поддерживает MCP. Это разделение означает, что разработчики ИИ-инструментов могут написать MCP сервер один раз и использовать его с множеством ИИ-клиентов, а разработчики ИИ-приложений могут добавлять новые интеграции, просто подключая MCP сервер, избегая создания специализированного кода интеграции.

Протокол и структура сообщений

Коммуникация: Коммуникация MCP построена на постоянных, состоятельных сессиях с использованием сообщений JSON-RPC 2.0. Все запросы и ответы соответствуют формату JSON-RPC (с полем "jsonrpc": "2.0", именами методов, параметрами и коррелирующими ID). Любая из сторон — клиент или сервер — может отправлять запросы или уведомления, обеспечивая двустороннее взаимодействие. MCP сессия обычно начинается с рукопожатия:

  • Клиент инициирует запрос initialize, предлагая версию протокола и объявляя свои возможности (какие функции он поддерживает). Например, клиент может указать, что он может обрабатывать запросы на «выборку», инициированные сервером, или предоставлять определенные корневые пути для доступа к файлам. Сервер отвечает своей поддерживаемой версией протокола и возможностями, определяя, какие функции включены для этой сессии (MCP использует систему согласования возможностей, аналогичную необязательным функциям в LSP). Если критические возможности или версия несовместимы, соединение завершается корректно.
  • После достижения соглашения клиент отправляет уведомление initialized, чтобы отметить готовность. После этого могут продолжаться нормальные операции. Сессия остается открытой для непрерывного обмена сообщениями JSON-RPC до тех пор, пока одна из сторон не инициирует завершение работы.

Транспорты: MCP не требует единственного транспорта — он работает через любой канал, который может передавать текст JSON. Обычно MCP сервер запускается как подпроцесс и общается через STDIO (потоки stdin/stdout) для локальных интеграций. Это аналогично тому, как работают языковые серверы, и удобно для локальных инструментов (хост может запускать процесс сервера и передавать сообщения). Альтернативно, MCP серверы могут работать как независимые службы, доступные через HTTP. Спецификация MCP определяет потоковый HTTP транспорт, где сервер предоставляет один HTTP-конец для вызовов JSON-RPC (клиенты отправляют POST-запросы, а сервер может отвечать или передавать результаты через Server-Sent Events для длительных операций). В любом случае сообщения — это строки UTF-8 JSON, а протокол поддерживает потоковые ответы и сообщения, инициированные сервером (подход HTTP+SSE позволяет серверу асинхронно отправлять уведомления или частичные результаты). Рекомендации по безопасности предполагают, что локальные серверы должны привязываться к localhost и проверять заголовки Origin, чтобы предотвратить нежелательный удаленный доступ, и что для удаленных серверов должна использоваться правильная аутентификация (например, токены или OAuth-потоки).

Формат сообщений: MCP использует три типа сообщений JSON-RPC: Запросы, Ответы и Уведомления. Запрос содержит id, строку method и (опционально) params (обычно JSON-объект аргументов). Получатель должен ответить соответствующим ответом (с совпадающим id), содержащим либо result, либо объект error. Уведомления похожи на односторонние сообщения с method и params, но без id (поэтому они не получают ответа). MCP накладывает несколько правил поверх базового JSON-RPC (например, id должен быть ненулевым и не переиспользоваться в течение сессии), чтобы поддерживать ясность.

Сессия и состояние: Соединение считается состоятельным — клиент и сервер поддерживают контекст о возможностях друг друга и, возможно, некоторое состояние сессии (например, подписки на изменения, текущие операции и т.д.). Также определены процедуры для корректного завершения работы (например, клиент может отправить запрос на завершение работы или просто закрыть транспорт; серверы должны обрабатывать очистку, и обе стороны реализуют тайм-ауты для висячих операций). Обработка ошибок следует соглашениям JSON-RPC (ответы об ошибках содержат код и сообщение), и спецификация определяет стандартные коды ошибок для определенных условий (например, отказано в доступе, инструмент не найден и т.д.). MCP также предоставляет утилиты для межпотоковых задач: например, есть встроенные уведомления для обновлений прогресса, отмены длительного запроса (CancelledNotification), сообщений для логирования/отладки и изменений конфигурации. Эти утилиты помогают управлять длительными или сложными взаимодействиями (клиент может отменить выполняющийся вызов инструмента, или сервер может отправить предупреждения клиенту и т.д.).

MCP Features and Operations

После инициализации сессия MCP позволяет обмениваться контекстом и командами структурированным образом. Основные серверные функции MCP — это Запросы, Ресурсы и Инструменты (каждый из которых сервер объявляет, если поддерживает их во время инициализации):

  • Запросы: Предопределенные шаблоны запросов или инструкции, которые сервер может предоставить клиенту. Обычно это запрашиваемые пользователем помощники (пользователь явно выбирает запрос для вставки в беседу, например, через команду со знаком / в интерфейсе). MCP предоставляет методы для перечисления доступных запросов и получения содержимого запроса. Например, клиент может вызвать prompts/list, чтобы получить список шаблонов запросов (каждый с именем, описанием и необязательными параметрами). Чтобы получить запрос, клиент использует prompts/get с именем запроса и любыми значениями аргументов; сервер затем возвращает содержимое запроса (часто в виде набора сообщений, которые клиент введет в контекст LLM). Запросы позволяют повторно использовать сложные инструкции или рабочие процессы (например, «шаблон проверки кода»), которые пользователь может вызывать по требованию. Серверы указывают возможность prompts (с необязательными подфункциями, такими как listChanged, чтобы уведомить клиента, если набор запросов изменяется динамически).

  • Ресурсы: Структурированные данные или контент, предоставляющие контекст модели. Ресурсы обычно представляют собой файлы, документы, записи баз данных — информацию, которую может читать или ссылаться на нее ИИ-ассистент. MCP стандартизирует способ идентификации и передачи ресурсов: каждый ресурс имеет идентификатор URI (например, file:///path/to/file.txt или пользовательскую схему для баз данных). Клиенты могут запросить, какие ресурсы доступны, через resources/list (сервер может предоставить дерево каталогов, список недавних документов и т. д.). Ответ сервера включает метаданные для каждого ресурса (URI, имя, тип, описание и т. д.). Затем клиент может запросить содержимое конкретного ресурса с помощью resources/read, передавая URI. Сервер отвечает содержимым ресурса, которое может быть текстом (для файлов) или структурированными данными (MCP поддерживает различные типы контента, такие как текст, JSON, бинарные данные и т. д., с типами MIME). Также есть поддержка шаблонов ресурсов (параметризованные ресурсы, идентифицируемые шаблонами URI, которые клиент может заполнить, например, запрос к базе данных, где пользователь предоставляет параметр). Если включено, серверы могут отправлять уведомления при изменении ресурсов (например, notifications/resources/updated) или позволяют клиентам подписываться на изменения ресурса (resources/subscribe). В проектировании MCP ресурсы являются контекстом, контролируемым приложением: обычно хост-приложение (клиент) решает, какое содержимое ресурса фактически передавать в запрос модели (часто после подтверждения пользователя или на основе контекста интерфейса).

  • Инструменты: Выполняемые функции или действия, которые сервер предоставляет для вызова модели. Инструменты представляют операции, которые может выполнять ИИ — например, вызвать внешний API, выполнить запрос к базе данных, отправить электронное письмо или изменить файл. У каждого инструмента есть имя и JSON-схема для входных (и необязательно выходных) параметров, поэтому ИИ (или клиент) знает, какие аргументы он ожидает. Инструменты обычно контролируются моделью: идея заключается в том, что языковая модель (агент) решает когда и когда использовать инструмент в ходе беседы для выполнения запроса пользователя. Однако для безопасности человек или хост-приложение могут посредничать в использовании инструментов (например, требовать подтверждающего клика). Использование инструментов в MCP включает две основные операции: перечисление и вызов. Клиент может вызвать tools/list, чтобы получить доступные инструменты и их схемы. Например, сервер может перечислить инструмент get_weather с описанием и входной схемой, которая требует строки «location». Затем, когда модель решает использовать инструмент (или пользователь его вызывает), клиент отправляет запрос tools/call с именем инструмента и JSON-объектом аргументов. Сервер выполняет функцию и возвращает результат, обычно в виде поля result.content, которое может содержать текст или структурированные данные (MCP поддерживает возвращение нескольких частей контента, например, текст плюс изображение и т. д., хотя текст является распространенным). Простой пример: вызов инструмента get_weather может вернуть текстовое сообщение, такое как «Текущая погода в Нью-Йорке: 72°F, частично облачно» в качестве контента для ассистента. Инструменты также могут указывать на ошибки (ответ содержит флаг isError или объект ошибки, если что-то пошло не так). Как и запросы и ресурсы, возможность tools может иметь необязательный флаг listChanged, чтобы уведомить, когда доступные инструменты изменяются в процессе выполнения (например, динамически загруженный/разгруженный плагин).

Помимо вышеупомянутых серверных функций, MCP также определяет функции, предлагаемые клиентом (возможности, которые серверы могут использовать, если клиент их поддерживает). К ним относятся Выборка, Корни и Вызывание:

  • Выборка позволяет серверу запрашивать у клиента (и его LLM) выполнение модели инференции в рамках сессии. Например, сервер может инициировать вызов LLM (возможно, для продолжения цепочки мыслей или для резюмирования чего-либо) путем отправки запроса, такого как sampling/request — клиент затем запросит модель и вернет результат. Это позволяет агентским поведениям, где сервер может управлять ИИ для помощи в собственных подзадачах. (Все такие действия подлежат одобрению пользователя и политике — например, пользователю, возможно, придется согласиться, чтобы сервер мог инициировать модель для дополнительных запросов.)

  • Корни позволяют серверу запрашивать или работать в пределах определенных разрешенных корневых каталогов или URI. Клиент может предоставить список «корневых» каталогов/URI, к которым сервер имеет право доступа, через roots/list. Это функция безопасности, обеспечивающая, что сервер знает границы (например, какие деревья каталогов он может читать).

  • Вызывание позволяет серверу запрашивать у клиента получение дополнительной информации от пользователя при необходимости. Например, если инструменту не хватает части информации, которая не была предоставлена, сервер может отправить запрос на вызывание, который клиент (интерфейс) преобразует в запрос пользователя («Интеграция X требует вашего API-ключа, пожалуйста, введите его»). Таким образом сервер может интерактивно собирать входные данные через клиента.

Все эти функции являются необязательными и согласовываются заранее. Ключевой аспект проектирования MCP заключается в том, что переговоры о возможностях происходят во время инициализации — клиент и сервер объявляют, какие из вышеупомянутых функций они поддерживают, поэтому обе стороны знают, какие операции доступны в сессии. Например, если сервер не объявляет возможность tools, клиент не будет пытаться выполнять операции tools/list или tools/call с ним. Эта расширяемость означает, что MCP может развиваться с новыми функциями со временем, сохраняя при этом обратную совместимость (неподдерживаемые методы просто не будут использоваться, если они не согласованы).

Реализации, SDK и создание сервера MCP (особенно на Go)

Официальная спецификация и документация: Авторитетная спецификация MCP доступна открыто, включая формальную схему всех типов сообщений. Она поддерживается на сайте Model Context Protocol и GitHub. Спецификация определена в файле схемы TypeScript (с соответствующей JSON Schema), которая точно документирует все запросы, ответы и структуры. Документационный сайт (modelcontextprotocol.io) предоставляет руководства, FAQ и подробные описания каждой функции и типа сообщений, а также инструмент «MCP Inspector» для интерактивной отладки. Хотя MCP пока не является стандартом IETF или ISO, он разрабатывается как открытый стандарт с участием сообщества и использует знакомую терминологию RFC 2119 для требований. Это развивающийся протокол (версии датированы; например, 2025-06-18 — это недавняя редакция), с политикой версионирования для управления изменениями.

Эталонные реализации: Anthropic открыла исходный код нескольких коннекторов серверов MCP и SDK при представлении MCP. Существует организация GitHub modelcontextprotocol, которая размещает спецификацию и несколько репозиториев. Особенно стоит отметить, что репозиторий «servers» содержит коллекцию предварительно собранных реализаций серверов MCP для распространенных сервисов и источников данных. Эти серверы служат эталонными интеграциями и часто могут использоваться «из коробки» или в качестве шаблонов для пользовательских серверов. Например, официальный репозиторий включает серверы для Google Drive (доступ к файлам и поиск в Google Drive), Slack (обмен сообщениями в рабочей области и контент каналов), GitHub/Git (контекст репозиториев кода), PostgreSQL (только для чтения запросы к базе данных со схемой), Google Maps (API местоположения и маршрутов), Puppeteer (веб-серфинг и парсинг), и многие другие. Установив или запустив эти серверы, приложение ИИ, такое как Claude или Cursor, сразу получит эту интеграцию. Также существует сообществом поддерживаемая регистрационная служба MCP (открытый исходный код на Go) для индексирования доступных серверов, и множество сторонних вкладов, расширяющих MCP на различные области (от CRM до данных блокчейна).

SDK и библиотеки: Для облегчения создания собственных серверов/клиентов MCP существуют официальные SDK на нескольких языках. По состоянию на 2025 год проект предоставляет SDK для TypeScript/Node, Python, Java (и Kotlin), C# (разработанный с Microsoft), Ruby (с Shopify), Swift и других. Эти библиотеки обрабатывают «протоколную настройку» — например, управление транспортом JSON-RPC, реализацию схемы спецификации и предоставление вспомогательных API для регистрации инструментов или обслуживания ресурсов. Например, SDK TypeScript можно использовать для быстрого написания сервера в Node.js, а SDK Python позволяет интегрировать MCP в приложения Python. Подход SDK означает, что разработчикам не нужно вручную создавать сообщения JSON-RPC или реализовывать полную машину состояний; вместо этого они вызывают высокоуровневые методы для отправки запросов или публикации возможностей.

Реализация на Go: Go стал популярным выбором для серверов MCP благодаря своей производительности и возможностям параллелизма (хорошо подходит для обработки нескольких одновременных запросов). Официальный SDK Go теперь доступен, поддерживается в сотрудничестве с командой Go в Google. (Это было объявлено около апреля 2025 года, а первая стабильная версия запланирована на август 2025 года.) SDK Go предоставляет пакет mcp для создания клиентов/серверов и вспомогательный jsonschema для схем инструментов. Используя SDK Go, разработчики могут создать сервер MCP всего несколькими вызовами. Например, можно создать новый сервер с именем и версией, а затем добавить инструменты через AddTool, предоставив определение инструмента (имя, описание, схема ввода) вместе с функцией обработчика Go для выполнения при вызове этого инструмента. SDK занимается предоставлением инструмента в протоколе (рекламой его в tools/list и обработкой запросов tools/call). Аналогично, можно предоставить ресурсы или шаблоны с аналогичными API. Наконец, запустите сервер — например, server.Run(ctx, mcp.NewStdioTransport()) начнет обработку сообщений JSON-RPC через stdio до отключения клиента. На стороне клиента SDK Go может запустить подпроцесс и подключиться через mcp.NewCommandTransport(exec.Command("myserver")), затем клиент может вызвать session.CallTool(ctx, params) для вызова инструмента и получения результата легко в коде Go.

Пример: Официальная документация SDK Go показывает простой сервер «приветствия». Сервер регистрирует инструмент "greet", который принимает имя и возвращает строку приветствия. Затем клиент вызывает этот инструмент по имени и выводит результат. Это иллюстрирует базовый шаблон: определить инструмент -> клиент вызывает инструмент -> получить результат. Под капотом это соответствует сообщениям JSON-RPC ("method": "tools/call", params: {"name": "greet", ...} и ответ, содержащий result.content с текстом) как определено спецификацией MCP.

До выхода официального SDK Go сообщество создало свои собственные библиотеки Go. Особенно стоит отметить проект mcp-go Эда Зинды (mark3labs/mcp-go), который широко использовался и повлиял на дизайн официального SDK. Другая библиотека, mcp-golang от Metoro, предоставила реализацию и API Go (пост в блоге сообщества разработчиков от Элтона Минетто использует эту библиотеку с начала 2025 года). Эти сообществом поддерживаемые SDK позволили разработчикам Go экспериментировать с MCP на ранних этапах — например, один туториал показывает, как создать сервер MCP, который ищет бразильские почтовые индексы (CEP), предоставив инструмент «zipcode» через библиотеку mcp-golang от Metoro. В этом примере сервер Go регистрирует функцию, которая вызывает внешний API для поиска адреса по почтовому индексу и возвращает результат в виде текста — это позволяет помощнику ИИ запрашивать информацию об адресах по запросу через MCP. Другое руководство демонстрирует обертку пользовательской базы данных в памяти (DiceDB) как сервер MCP с использованием SDK mcp-go от mark3labs: оно определяет инструмент ping для проверки подключения к БД и другие инструменты для операций с данными. Эти примеры подчеркивают, насколько просто можно создать интеграцию MCP: большая часть кода — это бизнес-логика (вызовы API, запросы к БД и т.д.), в то время как SDK обрабатывает подключение JSON-RPC.

Создание сервера MCP на Go (основные моменты туториала)

Чтобы описать процесс, вот типичный поток с SDK Go или подобной библиотекой:

  1. Настройка сервера: Инициализируйте новый экземпляр сервера с базовой информацией (имя, версия и объявление поддерживаемых возможностей). Например, на Go: server := mcp.NewServer("MyServer", "1.0.0", nil) создаст сервер, который (по умолчанию) поддерживает основные функции протокола. Вы можете включить конкретные возможности, такие как шаблоны/ресурсы/инструменты, через опции или просто зарегистрировав эти функции (добавление инструмента или ресурса подразумевает эту возможность).

  2. Регистрация функций: Добавьте функциональности, которые вы хотите предоставить:

    • Если вы предоставляете Инструменты, определите схему и обработчик для каждого инструмента. Например, с помощью AddTool SDK Go: предоставьте mcp.Tool{Name: "...", Description: "..."} и функцию обработчика, которая принимает запрос вызова и возвращает результат (который может включать текст или другой контент). SDK автоматически сгенерирует JSON Schema для входных данных из типов параметров вашей функции обработчика (или вы можете указать его).
    • Если вы предоставляете Ресурсы, вы можете использовать API для регистрации списков ресурсов или колбэка для чтения контента. Например, в SDK Python вы можете подклассифицировать ResourceProvider; в Go SDK все еще развивается, но вы, вероятно, предоставите функции для перечисления и чтения ресурсов. Каждый ресурс должен иметь стабильный URI.
    • Если вы предоставляете Шаблоны, определите шаблоны (могут быть статическими файлами или строками) и зарегистрируйте их с именами и необязательными параметрами. Сервер будет рекламировать их, чтобы клиент мог получить и отобразить их пользователям.
  3. Реализация транспорта: Решите, как будет работать сервер. Самый простой для локального использования — это stdio — например, server.Run(ctx, mcp.NewStdioTransport()) на Go начнет считывать JSON-RPC со stdin. Если ваш сервер должен быть сетевым, вы можете реализовать обработчик HTTP, который использует SDK Go для приема JSON-RPC через HTTP (официальный SDK Go, возможно, скоро включит вспомогательный элемент для транспорта HTTP/SSE).

  4. Тестирование клиента: Вы можете протестировать сервер с клиентом, совместимым с MCP. Например, Anthropic’s Claude 2 (Claude для настольных ПК) поддерживает загрузку локальных серверов MCP; вы бы настроили Claude для запуска или подключения к вашему бинарному файлу сервера. Также существует CLI-инструмент, называемый mcp-cli, и MCP Inspector GUI для тестирования серверов без полного клиента ИИ — эти инструменты отправляют запросы MCP вашему серверу и показывают результаты, помогая в отладке.

  5. Безопасность и разрешения: При создании сервера учитывайте аутентификацию и ограничение доступа. Для локальных серверов хост может запускать его с определенными разрешениями ОС или предоставлять ключи API через переменные окружения. Для удаленных серверов используйте заголовки аутентификации или потоки OAuth. MCP включает спецификацию авторизации для транспортов HTTP (сервер может требовать токен, а клиент может его отправить). Всегда убедитесь, что сервер получает доступ только к данным, которые пользователь разрешил (например, уважайте корневые каталоги, предоставленные клиентом, и не утекайте данные в другие места) — руководства MCP подчеркивают пользовательское согласие, конфиденциальность данных и безопасность инструментов как фундаментальные принципы.

В итоге, MCP — это формальный, но гибкий протокол для соединения ЛЛМ с внешним миром. Это не внутренний API, привязанный к одной компании, а открытый стандарт с растущим принятием и богатым экосистемой интеграций. Протокол определяет четкие структуры сообщений (на основе JSON-RPC) и набор операций (методы для шаблонов, инструментов, ресурсов и т.д.), которые любой соответствующий клиент/сервер может реализовать. Официальная документация и спецификации доступны, и множество SDK, библиотек и примеров серверов (включая Go) облегчают реализацию. Используя MCP, разработчики могут создавать AI-приложения, которые безопасно используют существующие данные и сервисы, не изобретая заново логику интеграции для каждой новой модели или набора данных.

Полезные ссылки