Глава 3 — Серверные примитивы: экспонирование контекста и возможностей
Третий пост поглавного разбора LLM Primer IV: Designing AI Cognition with MCP. В котором мы узнаём, что MCP-сервер на самом деле может сказать — три существительных, три жизненных цикла, три модели ошибок — и почему дисциплина выбора правильного решает, масштабируется сервер или обрастает наслоениями.
Почему существует эта глава
Протокол ровно настолько полезен, насколько полезны вещи, которые он позволяет говорить. Глава 2 построила ментальную модель Host, Client и Server и проследила оживление сессии через согласование возможностей. Когда рукопожатие завершено и обе стороны знают, что умеет другая, что конкретно лежит на столе? MCP отвечает тремя существительными: Resources, Prompts и Tools. На поверхности они похожи — каждое именованная, описанная схемой вещь, которую сервер может произвести или запустить, — но соответствуют трём разным намерениям. Resources — это чтение состояния. Prompts — переиспользуемые каркасы. Tools — действия записи. Глава проходит каждое по очереди: схема, жизненный цикл, модель ошибок и места, где инженеры ошибаются.
3.1 Resources: контекстные данные только для чтения
Ресурс — это данные, которые сервер может передать модели как контекст. Определяющее слово — только чтение. Ресурс не меняет мир; он его описывает. Если выборка вызывает изменение состояния где-то ещё — строку аудита, инкремент счётчика, отстреливаемый вебхук, — это не ресурс, это инструмент в чужом костюме. Чётко проведённая линия — первая дисциплина дизайна MCP-сервера.
У каждого ресурса есть стабильный URI в схеме, выбранной сервером (file://, postgres://, linear://issue/ENG-1234), плюс метаданные: имя, опциональное описание, MIME-тип, опциональный размер. Ни одно из этих полей не декоративно. Ресурс без описания — это ресурс, который модель не может оценить. Жизненный цикл прост: resources/list для перечисления, resources/read для выборки. resources/write не существует — если сервер хочет записи, он обязан выставить инструмент. Асимметрия держит границу доверия видимой.
Два паттерна делают ресурсы практичными в масштабе. URI-шаблоны позволяют серверу выставить параметризованную точку чтения (db://orders/{order_id}) вместо перечисления миллионов строк. Подписки позволяют хосту зарегистрировать интерес к URI и получать notifications/resources/updated, когда подлежащие данные меняются — альтернатива в виде опроса на каденции LLM расточительна с обеих сторон. Ловушка, которой следует избегать, — сбрасывать каждый внутренний объект в список ресурсов на старте сессии: список из трёх тысяч ресурсов съедает десятки тысяч токенов до того, как пользователь хоть что-то набрал. Выставьте курируемый верхний уровень плюс шаблоны и позвольте модели искать в длинном хвосте.
3.2 Prompts: переиспользуемые шаблоны и сценарии
Prompts в MCP не имеют ничего общего с системным промптом LLM. Это переиспользуемые, определённые сервером шаблоны, которые пользователь — или хост от его имени — может вызвать, чтобы начать конкретное взаимодействие. Prompt ближе к slash-команде, чем к личности. Смысл в том, чтобы сервер мог отгружать заведомо рабочие паттерны взаимодействия рядом с инструментами и ресурсами, которые он выставляет, — чтобы человеку у клавиатуры не приходилось помнить, как сформулировать запрос.
У prompt-а есть имя, опциональное описание и список аргументов. Хост вызывает prompts/list для обнаружения, затем prompts/get, чтобы развернуть prompt в последовательность сообщений, которые хост может скормить своему модельному циклу. Prompt может ссылаться на ресурсы через URI; тогда хост встраивает их перед отправкой. Сервер пишет сценарий открывающих ходов; модель забирает дальше.
Различие между prompts и системными сообщениями имеет значение. Пользователь, вызвавший /review_pr, видит в логе разговора, что ассистент начинает работать над ревью — он понимает, что началось, может прервать, может проверить. Если бы сервер вместо этого тихо дописал инструкции в системный промпт хоста, у пользователя не было бы понимания, почему ассистент внезапно ведёт себя иначе. Prompts — это видимый пользователю каркас; системные промпты — обрамление хоста. Их не следует смешивать. Дисциплина в том, что любое содержимое prompt-а, которое пользователь не одобрил бы при явном показе, — это дефект.
3.3 Tools: действия, структурированные выходы, идемпотентность
Tools — это место, где MCP становится интересным и опасным в равной мере. Resources — чтение; prompts — каркас; tools — запись: они создают строки, отправляют сообщения, разворачивают сервисы, списывают деньги. У каждого инструмента есть имя, описание и входная схема в JSON Schema. Описание — самое важное поле во всей поверхности MCP, потому что это текст, который модель использует, чтобы решить, вызывать ли инструмент, когда и с какими аргументами. Инструмент, чьё описание говорит «отправляет email», — это тот, к которому модель будет тянуться всякий раз, когда появляется намерение в форме email. Инструмент, чьё описание говорит «отправляет транзакционный email через маркетинговую платформу, только верифицированным адресам клиентов; не для личной переписки», — это тот, который модель использует разборчивее.
У модели ошибок два канала. Протокольная ошибка (некорректные аргументы, неизвестный инструмент) возвращает JSON-RPC error и является сбоем кадрировки. Ошибка инструмента (получатель отказал, диск переполнен) возвращает успешный ответ с isError: true и блоком content, объясняющим, что случилось. Различие важно: модель должна видеть ошибки инструментов и адаптироваться; хост должен видеть протокольные ошибки и восстанавливать транспорт. Смешение лишает модель информации, которая ей нужна.
Современный MCP поддерживает structuredContent рядом с массивом текстового content, соответствующий объявленной outputSchema. Накопительный эффект на длинной трассе реален: короткие, структурированные выходы инструментов оставляют модели запас для собственно рассуждения; длинные прозаические выходы съедают бюджет контекста. Ещё две дисциплины заслуживают именования. Минимальность: двенадцать хорошо описанных инструментов бьют шестьдесят почти в каждом бенчмарке; выставьте find_users со структурированным фильтром вместо list_users, get_user, search_users, count_users. Идемпотентность: штормы повторов неизбежны; инструмент, принимающий ключ идемпотентности или использующий детерминированную схему идентификаторов, превращает сетевые сбои в no-op-ы, а не в инциденты целостности данных.
3.4 Композиция: как три примитива сотрудничают
Примитивы наиболее полезны, когда работают вместе. Хорошо спроектированный сервер обычно выставляет понемногу каждого: несколько prompts для затравки типичных взаимодействий, небольшой набор tools для значимых действий и потенциально большой набор resources, поставляющих контекст. Сервер поддержки клиентов мог бы выставить профили клиентов и историю тикетов как resources, reply_to_ticket и escalate_ticket как tools и /triage_ticket как prompt, загружающий нужные ресурсы и просящий модель классифицировать. Prompts затравляют; resources наполняют ситуацию; tools меняют мир.
Соблазн, как только вы видите, насколько гибки примитивы, — пропускать всё через один. Можно подделать ресурсы инструментами только для чтения, подделать инструменты prompts-ами, подталкивающими модель выдавать команды, подделать prompts ресурсами с инструкциями. Каждое сжимает пространство дизайна и теряет что-то. Ресурсы, подделанные инструментами, нельзя кэшировать, на них нельзя подписаться, нельзя встроить в развёртывание prompt-а. Инструменты, подделанные prompts-ами, нельзя авторизовать на месте вызова, у них нет структурированного канала вывода. Примитивы не произвольны; они факторизованы так, чтобы хост знал, как безопасно обращаться с каждым. Уважение к факторизации — часть контракта протокола.
Что подготавливает глава 3
Вы прошли серверную сторону сделки. Сервер выставляет Resources, Prompts и Tools, у каждого собственная схема, жизненный цикл и модель ошибок. Дисциплина — выбирать правильный примитив под каждое умение сервера, аккуратно их именовать и описывать и сопротивляться перегрузке. Но MCP — не улица с односторонним движением. Хост может тоже отдавать возможности обратно серверу — и именно там живут самые интересные и самые чувствительные к безопасности проектные выборы протокола.
Дальше — Глава 4: Клиентские примитивы — Sampling, Roots, Elicitation. Обратная поверхность — то, что хост отдаёт обратно серверу, — и последствия безопасности каждой возможности, переданной через границу доверия.