MCP: как это работает — сообщения JSON-RPC, серверы FastMCP и трейс ReAct
Следуйте запросу протокола модельного контекста от инструментов/списков к окончательному ответу с использованием серверов FastMCP, агента LangGraph ReAct и трекера, который записывает каждый шаг.
Источники: How MCP Works: A Deep Dive with Code
Протокол контекста моделей, или MCP, — это открытый стандарт от Anthropic, позволяющий ИИ-моделям, таким как Claude, обращаться к внешним инструментам, источникам данных и сервисам. Хорошим аналогией может служить универсальный разъем: вместо того чтобы писать индивидуальную интеграцию для каждого инструмента, существует стандартный способ для взаимодействия модели с внешними системами.
Компоненты
Структуру составляют три элемента. Хост MCP — это приложение, которым фактически пользуется человек, будь то окно чата или IDE, и в нем содержится клиент, отвечающий за управление соединением. Протокол MCP представляет собой стандартизированный слой коммуникации между хостом и серверами. Каждый сервер MCP подключается к определенному типу ресурса — например, к базе данных, внешнему API или среде выполнения кода — и выступает в роли моста к нему.
Что происходит во время выполнения
На высоком уровне запрос проходит через следующие этапы:
- Пользователь отправляет запрос хосту.
- Хост спрашивает серверы MCP, какие инструменты они предлагают.
- Серверы возвращают свои списки инструментов.
- Хост отправляет запрос вместе с списком инструментов в LLM.
- LLM выбирает один из инструментов и сообщает об этом хосту.
- Хост вызывает соответствующий сервер MCP для его выполнения.
- Сервер выполняет инструмент и возвращает результат.
- Хост передает этот результат обратно в LLM.
- LLM формирует окончательный ответ, который затем передаёт хост.
Сервер предоставляет три вида ресурсов. Инструменты — это функции, которые может вызывать модель, такие как search_web, query_database или send_email. Ресурсы — это читаемые данные, которые хост может загрузить в качестве контекста, например файлы, записи базы данных, календарные события и документы; модель может их читать, но не выполнять. Подсказки — это заранее написанные шаблоны, предлагаемые сервером. Например, сервер GitHub может предоставить шаблон «подготовить краткое резюме этого PR», который хост может показать пользователю.
По сути, MCP — это лишь стандартизированный способ взаимодействия хоста с сервером. Он определяет формат сообщений и правила диалога, и ничего более. В частности, он определяет четыре элемента.
- Формат сообщений. Всё работает по стандарту JSON-RPC 2.0. Запрос содержит поля
id,methodиparams, а ответ повторяет полеidвместе с полемresultилиerror; таким образом обе стороны используют одинаковый формат обмена данными. - Доступные методы. Протокол определяет фиксированный набор вызовов, которые может выполнять хост: например,
tools/listдля поиска информации,tools/callдля запуска инструмента,resources/readдля загрузки данных иprompts/getдля получения шаблона. Серверы обязаны реализовать эти методы. - Процедура установления соединения. При первом подключении обе стороны обмениваются сообщениями типа
initialize, в которых указываются версия протокола и имеющиеся возможности; это позволяет каждой стороне знать, что поддерживает другая, прежде чем начнётся любая дальнейшая работа.
Один вызов инструмента разделяется на четыре сообщения. Сначала хост запрашивает, какие инструменты доступны:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
Сервер отвечает описаниями своих инструментов:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "search_web",
"description": "Search the web for a given query",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string" }
},
"required": ["query"]
}
}
]
}
}
Затем ведущий зовет одного из них:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "search_web",
"arguments": {
"query": "latest news on MCP protocol"
}
}
}
И сервер возвращает результат:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Anthropic released MCP in Nov 2024 as an open standard..."
}
]
}
}
Лучший способ обучения — это практика через создание кода, поэтому далее будет рассмотрен небольшой сервер MCP, используемый агентом.
Что делает FastMCP
FastMCP — это фреймворк на Python для создания серверов MCP с минимальным количеством шаблонного кода. Без него разработчику пришлось бы реализовывать цикл обработки сообщений JSON-RPC, сериализовать и десериализовать каждый запрос и ответ, вручную писать схемы JSON для каждой предоставляемой функции, а также обрабатывать протокольные сообщения вроде initialize, tools/list, tools/call, resources/list и prompts/list. С его помощью достаточно обычной функции на Python вместе с декоратором, а фреймворк берет на себя остальное:
from fastmcp import FastMCP
mcp = FastMCP("My Server") # creates the server
@mcp.tool() # registers the function as an MCP tool
def add(a: float, b: float) -> float:
"""Add two numbers.""" # docstring → tool description sent to the LLM
return a + b # type hints → JSON Schema sent to the LLM
mcp.run() # starts the stdio message loop
На основе аннотаций типов FastMCP самостоятельно создаёт схему JSON, а документация служит описанием на простом языке, которое модель читает при принятии решения о том, стоит ли вызывать тот или иной инструмент. Вызов mcp.run() запускает цикл, который блокируется на stdin и stdout при использовании формата передачи данных MCP, и именно к этому циклу подключается MultiServerMCPClient.
Три примитива в примерах серверов
Каждый сервер в проекте представляет собой автономное приложение FastMCP, предоставляющее три вида примитивов.
Сначала идут инструменты: функции, которые модель может вызывать. Для этого достаточно просто оформить функцию на Python с помощью @mcp.tool(), после чего FastMCP преобразует эти аннотации и документацию в схему JSON, которая передается клиенту во время запроса tools/list. Модель изучает эту схему, чтобы определить, когда следует использовать тот или иной инструмент и какие аргументы необходимо передать.
# servers/math_server.py
@mcp.tool()
def divide(a: float, b: float) -> float:
"""Divide a by b. Raises an error if b is zero."""
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
Ресурсы — это только для чтения данные, находящиеся по определённому URI. Модель не вызывает их автоматически, поэтому к ним необходимо обращаться явно. В этом проекте они используются лишь для иллюстрации концепции, тогда как в реальных приложениях это могут быть конфигурационные файлы, снимки базы данных или справочная документация.
# servers/math_server.py
@mcp.resource("math://constants")
def get_math_constants() -> str:
"""Common mathematical constants."""
return f"π = {math.pi}\n e = {math.e}\n ..."
@mcp.resource("math://formulas/{category}")
def get_formulas(category: str) -> str:
"""Retrieve mathematical formulas by category (geometry | algebra | statistics)."""
catalog = {
"geometry": (
"Geometry Formulas:\n"
" Circle area: A = π × r²\n"
" Circle circumference: C = 2π × r\n"
" Rectangle area: A = length × width\n"
" Triangle area: A = (base × height) / 2\n"
" Sphere volume: V = (4/3) × π × r³\n"
),
"algebra": (
"Algebra Formulas:\n"
" Quadratic formula: x = (−b ± √(b²−4ac)) / 2a\n"
" Difference of squares: a²−b² = (a+b)(a−b)\n"
" Perfect square: (a+b)² = a²+2ab+b²\n"
" Sum of arithmetic seq: S = n(a₁+aₙ)/2\n"
),
"statistics": (
"Statistics Formulas:\n"
" Mean: μ = Σx / n\n"
" Variance: σ² = Σ(x−μ)² / n\n"
" Std Dev: σ = √(Σ(x−μ)² / n)\n"
" Z-score: z = (x−μ) / σ\n"
),
}
return catalog.get(
category,
f"Unknown category '{category}'. Available: geometry, algebra, statistics",
)
URI math://formulas/{category} представляет собой шаблон. Часть {category} является параметром пути, благодаря чему math://formulas/geometry и math://formulas/algebra становятся двумя отдельными ресурсами, обслуживаемыми одной и той же функцией.
Инструкции-шаблоны могут использоваться повторно. Инструкция — это параметризованное сообщение системы, которое может запросить клиент; это способ упаковки профиля эксперта или инструкций к заданию внутри сервера, чтобы любой подключенный клиент мог использовать их единообразно.
# servers/math_server.py
@mcp.prompt()
def math_tutor(difficulty: str = "intermediate") -> str:
return (
f"You are an expert math tutor for {difficulty}-level students. "
"Break every problem into numbered steps..."
)
Как показано в следующих разделах, серверы в совокупности предоставляют 19 инструментов.
Пункт зрения клиента
Вот что происходит после запуска python main.py с запросом. Путь запроса от начала до конца выглядит следующим образом:
You type a query
│
▼
main.py ← entry point, parses args, kicks off async loop
│
▼
client/agent.py ← spawns 3 MCP servers, builds the agent, invokes it
│ │
│ ▼
│ utils/tracker.py ← fires on every LLM call, tool call, and result
│
▼
LangGraph ReAct loop ← think → call tool → observe → repeat
│
▼
servers/{math,text,data}_server.py ← each runs as an isolated subprocess
Шаг 1: где начинается выполнение
main.py — это первый файл, который выполняет Python. Он загружает переменные окружения, парсит аргументы командной строки, выводит приветственную панель и передаёт управление асинхронному запускачу.
async def _run(queries: list) -> None:
from client.agent import run_query # imported here (late) to keep startup fast
for i, q in enumerate(queries):
await run_query(q)
def main() -> None:
...
asyncio.run(_run(queries))
asyncio.run() создает новый цикл событий и блокируется до завершения выполнения _run(). Запрос, использованный для демонстрации, был следующим:
Generate 8 random numbers between 5 and 50 using seed=42,
then calculate their statistics, and tell me if there are any outliers.
Запустите из командной строки следующим образом:
python3 main.py --query "Generate 8 random numbers between 5 and 50 using seed=42, \
then calculate their statistics, and tell me if there are any outliers."
Затем панель статической информации выводится с помощью _print_header():
╭────────────────────────────── 🔌 MCP Example ───────────────────────────────╮
│ Multi-Server MCP Demo │
│ │
│ Three FastMCP servers, each exposing tools + resources + prompts: │
│ ● Math Server — add, subtract, multiply, divide, power, sqrt, │
│ percentage │
│ ● Text Server — count_words, word_frequency, reverse, transform, │
│ extract_emails │
│ ● Data Server — generate_numbers, calculate_statistics, find_outliers, │
│ normalise │
│ │
│ Stack : FastMCP · LangChain · LangGraph · OpenAI · Rich │
│ Track : live Rich panels + JSONL log files under logs/ │
╰──────────────────────────────────────────────────────────────────────────────╯
Шаг 2: создание агента
client/agent.py содержит функцию run_query(query) — асинхронную функцию, которая координирует всю работу. Она начинается с создания трекера и файла журнала.
log_file = str(LOGS_DIR / f"run_{int(time.time())}.jsonl")
tracker = MCPTracker(log_file=log_file)
Перед подключением любого сервера создается экземпляр MCPTracker, и в папке logs/ готовится файл JSONL с временной меткой. С этого момента каждое событие записывается туда в реальном времени.
Затем выводится запрос пользователя:
╭──── 💬 USER QUERY ────╮
│ Generate 8 random... │
╰────────────────────────╯
Затем определяются серверы для генерации:
def _server_config() -> Dict[str, Any]:
silent_env = {**os.environ, "FASTMCP_LOG_LEVEL": "ERROR"}
return {
"math_server": {
"command": sys.executable,
"args": ["servers/math_server.py"],
"transport": "stdio",
"env": silent_env,
},
"text_server": { ... },
"data_server": { ... },
}
Каждая запись описывает один сервер MCP, работающий в качестве подпроцесса. Поле command указывает на уже запущенный интерпретатор (sys.executable), args — имя скрипта сервера, а transport определяет способ общения клиента и сервера; здесь stdio означает стандартные потоки ввода и вывода. Поле env задаёт среду выполнения подпроцесса, а параметр FASTMCP_LOG_LEVEL=ERROR подавляет сообщение о запуске FastMCP.
Способ передачи данных через stdio является самым простым в MCP: клиент записывает сообщения в формате JSON-RPC в stdin сервера и считывает ответы из его stdout, поэтому не открываются сетевые порты.
После этого клиент подключается к каждому серверу и выявляет доступные инструменты:
client = MultiServerMCPClient(_server_config())
tools = await client.get_tools()
MultiServerMCPClient из пакета langchain-mcp-adapters выполняет следующие действия для каждой записи сервера одновременно: он создаёт дочерний процесс, отправляет сигнал инициализации MCP initialize через стандартные ввод-выводы, отправляет запрос tools/list, получает список схем инструментов и оборачивает каждую схему в объект Tool из LangChain.
После завершения вызова await client.get_tools() результатом становится однородный список из 19 объектов StructuredTool: семь из сервера для математических вычислений, семь из сервера для обработки текста и пять из сервера данных. Этот список представляет собой полный набор действий, доступных для модели.
Connected to 3 servers (math_server, text_server, data_server) with 19 tools: add, subtract, multiply,
divide, power, square_root, calculate_percentage, count_words, word_frequency, reverse_text,
transform_case, find_and_replace, extract_emails, count_vowels_consonants, generate_numbers,
calculate_statistics, find_outliers, sort_values, normalize_values
Затем создаются модель языка и агент:
model = ChatOpenAI(model=model_name, temperature=0)
agent = create_react_agent(model, tools)
Функция create_react_agent из LangGraph создаёт скомпилированную графическую структуру состояния с такой организацией:
START
│
▼
[call_model] ─── no tool call ──▶ END
│
tool call requested
│
▼
[call_tools]
│
▼
[call_model] (loop again with tool result in context)
Это шаблон ReAct — рассуждения плюс действия. Модель рассуждает о следующем шаге, выполняет действие путем вызова инструмента, наблюдает за результатом и повторяет процесс до тех пор, пока у неё не будет достаточно информации для ответа.
В конце вызывается агент:
config = {"callbacks": [tracker]}
result = await agent.ainvoke({"messages": [("human", query)]}, config=config)
Элемент "callbacks": [tracker] интегрируется в систему обратных вызовов LangChain. Каждый раз, когда фреймворк выполняет важное действие, такое как запуск или завершение вызова большой языковой модели или инструмента, он вызывает соответствующий метод в объекте tracker. Благодаря этому трекер может отслеживать всё происходящее, не находясь внутри какой-либо логики.
Шаг 3: просмотр в реальном времени
MCPTracker расширяет класс BaseCallbackHandler из LangChain. Его методы никогда не вызываются напрямую, поскольку LangChain вызывает их в подходящие моменты.
agent.ainvoke() called
│
├─▶ on_chain_start() "▶ AGENT STARTED" panel
│
├─▶ on_chat_model_start() "🤖 LLM CALL #1" panel (timer starts)
├─▶ on_llm_end() "LLM responded ⏱ 1.23s → will call: add, multiply"
│
├─▶ on_tool_start() "🔧 TOOL CALL #1" panel (timer starts)
├─▶ on_tool_end() "✓ TOOL RESULT ⏱ 0.01s" panel
│
├─▶ on_tool_start() (second tool, if any)
├─▶ on_tool_end()
│
├─▶ on_chat_model_start() "🤖 LLM CALL #2" (LLM synthesises final answer)
├─▶ on_llm_end() no tools this time → loop ends
│
└─▶ agent.ainvoke() returns
Каждый раз, когда срабатывает on_tool_start, трекер определяет, какой сервер управляет инструментом, и присваивает соответствующий цвет. Единственная цель — улучшение читаемости.
TOOL_SERVER_MAP = {
"add": "math_server",
"count_words": "text_server",
"generate_numbers": "data_server",
...
}
SERVER_COLORS = {
"math_server": "cyan",
"text_server": "green",
"data_server": "yellow",
}
Каждое событие становится одной строкой JSON в файле logs/run_<timestamp>.jsonl. Файл открывается в режиме добавления и запись в него происходит немедленно, поэтому выполнение команды tail -f logs/run_*.jsonl в другой терминале показывает сырые события, появляющиеся по мере работы агента. После возврата значения от функции agent.ainvoke() файл client/agent.py вручную вызывает функцию print_summary(), которая сообщает общее количество вызовов LLM, вызовов инструментов и времени работы с момента начала выполнения.
Первым, что появляется, является запись о первом вызове LLM с одним сообщением:
── 🤖 LLM CALL #1 model=gpt-5-mini messages=1 ──╮
│ Role Content preview │
│ Human Generate 8 random numbers between 5 and 50… │
╰──────────────────────────────────────────────────────╯
Граф ReAct только что начал работу. Модель получает системное сообщение, введённое LangGraph вместе с списком инструментов и их схемами, а также одно сообщение от человека, поэтому messages=1.
LLM responded ⏱ 5.35s → will call: generate_numbers
Трекер проанализировал необработанный ответ модели. Вместо прозы модель ответила структурированным запросом на вызов инструмента:
{
"name": "generate_numbers",
"arguments": {"count": 8, "min_val": 5, "max_val": 50, "seed": 42}
}
Внутри response.generations[0][0].message.tool_calls трекер обнаружил запрос и вывел его название. 5,35 секунды — это просто время на передачу данных туда и обратно к API OpenAI. LangGraph считывает это решение и переходит к узлу call_tools, что приводит к первому вызову инструмента:
╭── 🔧 TOOL CALL #1 ──────────────────╮
│ Tool : generate_numbers │
│ Server: data_server │
│ Args : │
│ {'count': 8, 'min_val': 5, │
│ 'max_val': 50, 'seed': 42} │
╰───────────────────────────────────────╯
Исходя из названия инструмента generate_numbers, трекер обратился к маппингу TOOL_SERVER_MAP, которое соответствует data_server, и покрасил панель в жёлтый цвет, поскольку значение SERVER_COLORS["data_server"] равно "yellow". Именно в этот момент LangChain отправляет сообщение JSON-RPC типа tools/call по трубопроводу stdio в дочерний процесс data_server:
{"method": "tools/call", "params": {"name": "generate_numbers",
"arguments": {"count": 8, "min_val": 5, "max_val": 50, "seed": 42}}}
Процесс получает его, запускает функцию на Python и записывает результат обратно в свой stdout.
╭── ✓ TOOL RESULT ⏱ 0.63s ────────────────────────────╮
│ [33.77, 6.13, 17.38, 15.04, 38.14, 35.45, 45.15, 8.91] │
╰──────────────────────────────────────────────────────────╯
Он выполнил именно этот код:
random.seed(42)
return [round(random.uniform(5, 50), 2) for _ in range(8)]
# → [33.77, 6.13, 17.38, 15.04, 38.14, 35.45, 45.15, 8.91]
0,63 секунды — это время от отправки запроса до получения ответа по каналу связи, включая накладные расходы на планирование процессов в Python. LangGraph добавляет результат в список сообщений агента в виде ToolMessage, так что теперь в списке три элемента: сообщение от человека, сообщение от ИИ (решение о вызове инструмента) и результат от инструмента.
Затем следует второй вызов LLM с тремя сообщениями:
╭── 🤖 LLM CALL #2 model=gpt-5-mini messages=3 ──╮
│ Role Content preview │
│ Human Generate 8 random numbers… │
│ AI (the tool-call decision) │
│ Tool [33.77, 6.13, 17.38, ...] │
╰──────────────────────────────────────────────────────╯
Модель снова запускается с полной историей действий до этого момента. Она видит исходный вопрос, свое собственное ранее принятое решение вызвать функцию generate_numbers, а также полученные числа. Ее логика примерно такова: числа уже имеются, к тому же в вопросе просились статистические данные, поэтому следует вызвать функцию calculate_statistics с их использованием. Это приводит к второму вызову инструмента и его результату:
Tool : calculate_statistics
Server: data_server
Args : {'numbers': [33.77, 6.13, 17.38, 15.04, 38.14, 35.45, 45.15, 8.91]}
Result: {"count":8, "min":6.13, "max":45.15, "mean":24.9962,
"median":25.575, "std_dev":14.8181, "variance":219.5755,
"range":39.02, "q1":15.04, "q3":38.14}
Здесь модель ничего не запоминала. Она буквально брала значения по одному из предыдущего объекта ToolMessage в своем окне контекста и вставляла их в аргументы следующего инструмента. Именно так выглядит цепочка операций в цикле ReAct: результат работы одного инструмента становится контекстом, который может быть прочитан и повторно использован при следующем вызове модели.
В третьем вызове LLM содержится пять сообщений, и модель вызывает функцию find_outliers:
Tool : find_outliers
Server: data_server
Args : {'numbers': [...], 'threshold': 2}
Result: {"outliers": [], "outlier_count": 0,
"total_checked": 8, "mean": 24.9962, "std_dev": 14.8181}
Функция find_outliers вычисляет коэффициент z для каждого значения (z = (x − mean) / std_dev) и проверяет, превышает ли какой-либо из них порог в 2. Ни один из коэффициентов не превышает этот порог, поэтому список outliers пуст.
В вызове LLM под номером 4 обработано семь сообщений:
╭── 🤖 LLM CALL #4 messages=7 ──╮
│ Human / AI / Tool │
│ AI / Tool │
│ AI / Tool │
╰───────────────────────────────────╯
LLM responded ⏱ 30.25s
Отсутствие суффикса «will call» указывает на то, что модель сгенерировала обычный текст, а не запрос к инструменту, что прерывает цикл ReAct. Обработка заняла 30 секунд, поскольку контекст был обширным (семь сообщений, включая необработанные результаты в формате JSON), и модели пришлось провести длительную и тщательную синтезацию, вручную вычисляя значение z-коэффициента для каждого показателя. LangGraph не обнаруживает в ответе никаких вызовов инструментов и перенаправляет процесс к команде END, которая выводит окончательный ответ:
╭── ✅ FINAL ANSWER ───────────────────────────────╮
│ Random numbers: [33.77, 6.13, 17.38, ...] │
│ Mean: 24.9962 / Median: 25.575 / Std Dev: 14.8181│
│ Outliers: none (all |z| < 2) │
╰───────────────────────────────────────────────────╯
Затем отображается краткое описание пробежки:
╭─────────────────────────────────────────────────────╮
│ LLM Calls 4 │
│ Tool Calls 3 │
│ Total Time 42.25s │
│ Log File logs/run_1776864980.jsonl │
╰─────────────────────────────────────────────────────╯
Полная последовательность сообщений
Это все элементы списка сообщений агента, которые были возвращены после вызова agent.ainvoke():
1 HumanMessage "Generate 8 random numbers…"
2 AIMessage [tool_call: generate_numbers({count:8, min:5, max:50, seed:42})]
3 ToolMessage [33.77, 6.13, 17.38, 15.04, 38.14, 35.45, 45.15, 8.91]
4 AIMessage [tool_call: calculate_statistics({numbers:[...]})]
5 ToolMessage {count:8, mean:24.9962, std_dev:14.8181, ...}
6 AIMessage [tool_call: find_outliers({numbers:[...], threshold:2})]
7 ToolMessage {outliers:[], outlier_count:0, ...}
8 AIMessage "Here are the results. Random numbers: …" ← final answer
При каждом вызове большой языковой модели используется вся накопленная ранее информация, поэтому значение messages в панелях отслеживания увеличивается на 1, 3, 5, 7.
Журнал в формате JSONL
Все вышеупомянутые события также записывались в logs/run_x.jsonl по мере их возникновения; каждая строка содержит один объект JSON:
{"timestamp": "...", "event": "agent_start", "data": {"runnable": "LangGraph", "run_id": "..."}}
{"timestamp": "...", "event": "llm_call", "data": {"call_number": 1, "model": "gpt-5-mini", "messages": 1}}
{"timestamp": "...", "event": "llm_end", "data": {"elapsed": "5.35s", "tool_calls_requested": ["generate_numbers"]}}
{"timestamp": "...", "event": "tool_start", "data": {"call_number": 1, "tool": "generate_numbers", "server": "data_server", "args": "..."}}
{"timestamp": "...", "event": "tool_end", "data": {"elapsed": "0.63s", "output_preview": "[33.77, 6.13, ...]"}}
{"timestamp": "...", "event": "llm_call", "data": {"call_number": 2, "model": "gpt-5-mini", "messages": 3}}
...
{"timestamp": "...", "event": "run_summary", "data": {"llm_calls": 4, "tool_calls": 3, "total_elapsed": "42.25s"}}
Почему это важно
Настоящая ценность MCP заключается в возможности распространения. До появления стандарта любая команда, желавшая расширить возможности LLM за его пределы, должна была создавать собственный слой интеграции, причем весь этот код не мог быть перенесен на другие модели или фреймворки. Теперь сервер пишется один раз и может обслуживать любого соответствующего клиента. Команда, занимающаяся базами данных, может опубликовать сервер с ограниченными правами доступа для своей схемы, команда DevOps может предоставить инструменты для развертывания, а платформа для обработки данных — функции по выполнению запросов и анализу данных. Любой агент может подключаться ко всем им, и командам больше не нужно договариваться о деталях реализации.
Связанные материалы
- Пересоздание агента в стиле Claude Code с использованием LangChain Deep Agents — Как работает механизм управления кодирующим агентом, от основного цикла до инструментов, планирования, памяти, подагентов и процедур проверки в изолированной среде, с пошаговым описанием использования deepagents.
- Десять серверов MCP, которые стоит установить в первую очередь, для разработчиков — Рейтинг серверов MCP для помощников в программировании на основе ИИ, от Context7 и GitHub до Postgres и механизмов хранения памяти, с настройками установки и рекомендациями по разрешениям.