Построение масштабируемых безсостоянийных серверов MCP 2026 (технический разбор)
Пошаговое руководство по созданию масштабируемых серверов MCP 2026 без состояния (технический разбор): контракты, проверки и готовые блоки кода для команд, использующих эту архитектурную схему.
Используйте это как переработанную версию идей из документа «Stateless Model Context Protocol: Building Scalable MCP 2026 Specification Servers (Technical Deepdive)», ориентированную на операторов: четкие этапы, упорядоченные блоки кода и записи о восстановлении, сохраняющиеся при передаче задач. Этап Обзора работает наилучшим образом, если рассматриваться как измеримая основа. Сначала зафиксируйте один идеальный пример работы, один случай сбоя и записи о возврате к предыдущему состоянию, прежде чем расширять объем работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости на ранних этапах предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
Проблема состояний: почему MCP до 2026 года сталкивалась с трудностями при масштабировании
На этапе «Проблема состояний» необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг, исходя из известной точки контроля, без необходимости угадывать скрытое состояние. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища конфиденциальных данных и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь кодовый граф. При следующем шаге, представляющем собой код или вызов инструмента, следует предпочитать структурированные выходные данные с проверкой схемы вместо свободного текста.
+--------------------------------------------------------------------------+
| Pre-2026 Stateful Architecture |
| |
| +--------------+ WebSocket / SSE +-----------------------+ |
| | Client Agent | <=======================> | MCP Server Pod A | |
| +--------------+ (Session Pinned) | (In-Memory Session) | |
| +-----------------------+ |
| | |
| State Lookup |
| v |
| +-----------------------+ |
| | Central Redis Cache | |
| +-----------------------+ |
+--------------------------------------------------------------------------+
Препятствия, связанные с аффинностью сессий
Для этапа «The Friction of Session» необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо одновременно задокументировать успешный сценарий выполнения и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. При следующем шаге, представляющем собой код или вызов инструмента, следует отдавать предпочтение структурированным выводам с проверкой по схеме перед свободным текстовым описанием.
Внутренние механизмы MCP 2026–07–28: маршрутизация заголовков и самоописывающиеся RPC
Для этапа «Под капотом» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций. При следующем шаге, представляющем собой код или вызов инструмента, лучше использовать структурированные выводы с проверкой схемы вместо свободного текста. Для этапа «Под капотом» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Регистрируйте время выполнения, а также стоимость токенов или запросов вместе с функциональными результатами. Отображение стоимости на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
+--------------------------------------------------------------------------+
| MCP 2026-07-28 Stateless Architecture |
| |
| +--------------+ HTTP POST (Self-Describing) +---------------+ |
| | Client Agent | --------------------------------> | Round-Robin | |
| +--------------+ Headers: Mcp-Method, Mcp-Name | Load Balancer | |
| +---------------+ |
| | |
| Any Worker Pod | |
| +----------------------+--------+ |
| | | | |
| v v v |
| +--------+ +--------+ +---+|
| | Pod 1 | | Pod 2 | |...||
| +--------+ +--------+ +---+|
+--------------------------------------------------------------------------+
Самоописывающийся JSON-RPC 2.0 с использованием _meta
При работе с механизмом самоописывающегося JSON-RPC 2.0 сначала запишите условия использования: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет избежать ошибок при последующих изменениях кода. Храните конфигурацию вне кода приложения. Файлы с настройками окружения, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять без необходимости просматривать весь код. Храните в кэше стабильные инструкции системы и схемы инструментов. Повторная отправка одинаковых данных является распространенной причиной ресурсозатрат.
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "query_database",
"arguments": {
"query": "SELECT count(*) FROM users WHERE status = 'active';"
}
},
"id": "req-98421",
"_meta": {
"protocolVersion": "2026-07-28",
"clientInfo": {
"name": "AutonomousAgentWorker",
"version": "4.1.0"
},
"progressToken": "tok_998122",
"traceContext": {
"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
}
}
}
Обязательные заголовки маршрутизации HTTP уровня 7
При работе над этапом обязательной маршрутизации HTTP на уровне 7 сначала запишите описание функционала: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Документируйте одновременно успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки со стороны оператора и обработка некорректных сообщений являются частью продукта, а не элементами последующей доработки. Храните в кэше стабильные инструкции системы и схемы инструментов. Пересылка одинаковых заголовков — распространенная причина избыточных ресурсов.
Обнаружение серверов и интеллектуальный кэширование
При работе над этапами обнаружения серверов и интеллектуальной обработки сначала запишите условия взаимодействия: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Предпочитайте небольшие, тестируемые модули большим скриптам. Если какой-то шаг не сработает, причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций. Храните в кэше стабильные инструкции системы и схемы инструментов. Повторная отправка одинаковых данных — распространенная причина избыточных затрат. При работе над этапами обнаружения серверов и интеллектуальной обработки сначала запишите условия взаимодействия: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Регистрируйте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
{
"jsonrpc": "2.0",
"result": {
"protocolVersion": "2026-07-28",
"capabilities": {
"tools": { "listChanged": false }
},
"serverInfo": {
"name": "Scalable-Stateless-MCP-Server",
"version": "2.0.0"
},
"cacheControl": {
"ttlMs": 3600000,
"cacheScope": "public"
}
},
"id": "disc-001"
}
Создание производственного сервера без состояния: FastAPI, FastMCP 2.0 и OAuth 2.1
Этап создания производственного сервера без состояния работает наилучшим образом, если рассматривать его как измеримую основу. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Установите лимиты на количество токенов за одну операцию и за сессию. Инструменты-агенты активно расширяют объём контекста; жесткие ограничения предотвращают появление неожиданных счетов.
+-----------------------------------------------------------------------------+
| Stateless Request Dispatching |
| |
| Client Request w/ Bearer JWT |
| + Header: Mcp-Method: tools/call |
| + Header: Mcp-Name: query_database |
| |
| │ |
| ▼ |
| +------------------------------------+ |
| | OAuth 2.1 Bearer Validation | ---> (401 Unauthorized if invalid)|
| | verify_token() | |
| +------------------------------------+ |
| │ |
| ▼ Decoded Claims (user_info) |
| +------------------------------------+ |
| | Header-Based Route Dispatcher | |
| | extract Mcp-Method / Mcp-Name | |
| +------------------------------------+ |
| │ |
| ├──────────────────────────────┐ |
| ▼ ▼ |
| [ tools/call ] [ server/discover ] |
| Execute tool handler Return cached capability |
| Scoped to user_info['sub'] manifest & protocol specs |
+-----------------------------------------------------------------------------+
from fastapi import FastAPI, Depends, HTTPException, Header, Security
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from pydantic import BaseModel
from typing import Dict, Any, Optional
import jwt
app = FastAPI(title="Stateless MCP 2026 Server")
security = HTTPBearer()
JWT_SECRET = "production_secret_key"
JWT_ALGORITHM = "HS256"
def verify_token(credentials: HTTPAuthorizationCredentials = Security(security)) -> Dict[str, Any]:
"""
Validates incoming OAuth 2.1 Bearer JWT tokens.
Converts the MCP server into a standard OAuth Resource Server.
"""
try:
payload = jwt.decode(credentials.credentials, JWT_SECRET, algorithms=[JWT_ALGORITHM])
return payload
except Exception:
raise HTTPException(status_code=401, detail="Invalid Bearer token")
class JsonRpcRequest(BaseModel):
jsonrpc: str = "2.0"
method: str
params: Optional[Dict[str, Any]] = None
id: Any
_meta: Optional[Dict[str, Any]] = None
@app.post("/mcp")
async def handle_mcp_request(
request: JsonRpcRequest,
mcp_method: Optional[str] = Header(None, alias="Mcp-Method"),
mcp_name: Optional[str] = Header(None, alias="Mcp-Name"),
user_info: Dict[str, Any] = Depends(verify_token)
):
"""
Stateless MCP Request Handler conforming to the 2026-07-28 specification.
Prefers Mcp-Method and Mcp-Name headers for fast execution dispatch.
"""
effective_method = mcp_method or request.method
# Route: Tool Execution
if effective_method == "tools/call":
tool_name = mcp_name or (request.params.get("name") if request.params else None)
arguments = request.params.get("arguments", {}) if request.params else {}
if tool_name == "query_database":
query = arguments.get("query")
user_id = user_info.get("sub", "anonymous")
# Context is scoped directly to the authenticated token claims
return {
"jsonrpc": "2.0",
"result": {
"content": [
{
"type": "text",
"text": f"Executed query '{query}' for user {user_id}"
}
]
},
"id": request.id
}
# Standard JSON-RPC Method Not Found (-32601)
return {
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": f"Tool '{tool_name}' not found"
},
"id": request.id
}
# Route: Server Discovery
elif effective_method == "server/discover":
return {
"jsonrpc": "2.0",
"result": {
"protocolVersion": "2026-07-28",
"capabilities": {
"tools": {"listChanged": False}
},
"serverInfo": {
"name": "Scalable-Stateless-MCP-Server",
"version": "2.0.0"
}
},
"id": request.id
}
# Unsupported Protocol Method
return {
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": f"Method '{effective_method}' unsupported"
},
"id": request.id
}
Управление трафиком с нулевой обработкой на уровне 7: конфигурация Envoy и Gateway
Этап управления трафиком с нулевой обработкой на уровне 7 работает наилучшим образом, когда рассматривается как измеримая среда. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Документируйте одновременно успешный и восстановительный пути работы. Повторные попытки, проверка оператором и обработка некорректных сообщений являются частью продукта, а не последующими доработками. Установите лимиты на количество токенов за одну операцию и за сессию. Инструменты с агентным подходом активно расширяют объем данных; жесткие ограничения предотвращают появление неожиданных счетов при демонстрации функций.
routes:
- match:
prefix: "/mcp"
headers:
- name: "Mcp-Method"
exact_match: "tools/call"
- name: "Mcp-Name"
exact_match: "query_database"
route:
cluster: mcp_database_tools_cluster
- match:
prefix: "/mcp"
route:
cluster: mcp_general_cluster
Управление состоянием без сессий: многократные запросы и связанные с ними компромиссы
Этап управления состоянием без сессий работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-то шаг сбивается, причина сбоя должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Установите лимиты на количество токенов за один ход и за сессию. Инструменты агентов активно расширяют объем контекста; жесткие ограничения предотвращают появление неожиданных счетов. Этап управления состоянием без сессий работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-версии к общим средам.
Интерактивный цикл многократных запросов (MRTR)
Для этапа MRTR с несколькими итерациями необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. При следующем шаге, представляющем собой выполнение кода или вызов инструмента, предпочтительнее использовать структурированные выходные данные с проверкой схемы вместо свободного текста.
Анализ архитектурных компромиссов
На этапе анализа архитектурных компромиссов необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо задокументировать как успешный, так и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. При следующем шаге, представляющем собой код или вызов инструмента, следует отдавать предпочтение структурированным выводам с проверкой по схеме перед свободным текстовым описанием.
Развертывание в облаке: масштабирование MCP на Kubernetes и Serverless
Для этапа MCP масштабирования в облачной среде необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не пытаясь угадать скрытое состояние системы. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной структурой всего процесса. При следующем шаге, представляющем собой код или вызов инструмента, целесообразно использовать структурированные выходные данные с проверкой соответствия шаблону вместо свободного текста.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: mcp-tool-server-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: mcp-tool-server
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: External
external:
metric:
name: nginx_ingress_controller_requests
target:
type: Value
averageValue: 1000m
Заключение и следующие шаги
На этапе «Заключение и следующие шаги» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Укажите названия результатов работы, определите критерии успеха и не допускайте молчаливого частичного завершения задачи. При следующем шаге, представляющем собой код или вызов инструмента, отдавайте предпочтение структурированным выходным данным с проверкой по шаблону перед произвольными текстовыми описаниями.
Ресурсы с дополнительной информацией
На этапе подготовки ресурсов для получения дополнительной информации необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг, исходя из известной точки контроля, без необходимости угадывать скрытое состояние. Рядом с функциональными результатами следует записывать время выполнения и стоимость токенов или запросов. Отображение стоимости заранее помогает избежать неожиданных счетов при переходе от демо-среды к общедоступным средам. При следующем шаге, представляющем собой код или вызов инструмента, следует отдавать предпочтение структурированным выводам с проверкой схемы перед свободным текстом.
Чек-лист операций
При работе над чек-листом операций сначала необходимо зафиксировать условия работы: требуемые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист обеспечивает прозрачность последующих изменений в коде.
Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успешности и не соглашайтесь на молчаливое частичное выполнение задачи.
Храните в кэше стабильные инструкции системы и схемы инструментов. Пересылка одинакового входного данных является распространенной причиной ошибок.
Обеспечьте доступ к инструментам с узкими схемами и четкими метками о побочных эффектах. Хостам необходимо знать, какие вызовы изменяют состояние, прежде чем они автоматически одобрят операцию.
При наличии бюджета добавляйте тесты для проверки критического пути в процессе CI с использованием фикстчеров, а не реальных платных API.
Документируйте как успешный, так и восстановительный пути выполнения. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не этапом последующей доработки.
Перед тем как запускать стек в продакшн, заморозьте версии, сделайте «золотой» отчет для критического пути и уточните шаги возврата к предыдущей версии. В совместных средах необходимы ограничения на частоту запросов, проверки принадлежности пользователя и четко определенный ответственный за обновление секретов. Лучше выбирать надежность, чем креативные одноразовые демонстрации.
Примечание для ecba7bb3b9c6: не храните ключи поставщика в репозитории, установите лимит токенов на сессию и сохраняйте отчеты рядом с фикстурами для оценки, чтобы последующие замены моделей оставались сопоставимыми.