Budowanie skalowalnych, bezstanowych serwerów MCP 2026 (szczegółowe omówienie techniczne)
Krok po kroku instrukcja tworzenia skalowalnych, bezstanowych serwerów MCP 2026 (szczegółowe omówienie techniczne): kontrakty, sprawdzania oraz gotowe elementy kodu dostępne dla zespołów wdrażających ten wzorzec.
Niech to służy jako wersja przeznaczona dla operatorów, zawierająca zwięzłe przedstawienie idei z dokumentu „Stateless Model Context Protocol: Building Scalable MCP 2026 Specification Servers (Technical Deepdive)”: wyraźne etapy, uporządkowane sekcje kodu oraz notatki dotyczące przywracania stanu po przeniesieniu obowiązków. Etap Przeglądu działa najlepiej, gdy traktowany jest jako mierzalna powierzchnia do analizy. Zapisz jeden idealny zapis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. Zapisuj czasy wykonywania operacji oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy przechodzi się od wersji demonstracyjnej do środowisk współdzielonych.
Wąskie gardło związane ze stanem: dlaczego MCP sprzed 2026 roku miał trudności z skalowalnością
W fazie „The Stateful Bottleneck Why” należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepiej używać ustrukturyzowanych wyników z walidacją schematu niż tekstu w formie swobodnej.
+--------------------------------------------------------------------------+
| Pre-2026 Stateful Architecture |
| |
| +--------------+ WebSocket / SSE +-----------------------+ |
| | Client Agent | <=======================> | MCP Server Pod A | |
| +--------------+ (Session Pinned) | (In-Memory Session) | |
| +-----------------------+ |
| | |
| State Lookup |
| v |
| +-----------------------+ |
| | Central Redis Cache | |
| +-----------------------+ |
+--------------------------------------------------------------------------+
Tarcie spowodowane powiązaniami sesji
Dla etapu The Friction of Session należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponownych działań, mechanizmy ludzkiej kontroli oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, należy preferować ustrukturyzowane wyniki z walidacją schematu zamiast tekstów w formie swobodnej.
Wnętrze MCP 2026–07–28: routowanie nagłówków i samopisowe RPC
W fazie Under the Hood należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy dany krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepsze są ustrukturyzowane wyniki z walidacją schematu niż swobodny tekst. W fazie Under the Hood należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Obok wyników funkcjonalnych należy rejestrować czas wykonywania oraz koszt tokenów lub zapytań. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk.
+--------------------------------------------------------------------------+
| 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 | |...||
| +--------+ +--------+ +---+|
+--------------------------------------------------------------------------+
Samoopisowy JSON-RPC 2.0 za pomocą _meta
Gdy przechodzisz przez etap samoopisowego JSON-RPC 2.0, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Zachowuj w pamięci podręcznej stabilne instrukcje systemowe oraz schematy narzędzi. Ponowne wysyłanie identycznego prefiksu jest częstą przyczyną marnotrawstwa zasobów.
{
"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"
}
}
}
Obowiązkowe nagłówki routingu HTTP warstwy 7
Gdy przechodzisz przez etap obowiązkowego routingu HTTP na warstwie 7, najpierw zapisz specyfikację: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę przywracania stanu systemu. Próby ponownych wysyłek, mechanizmy ludzkiej kontroli oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później w celu udoskonalenia. Zachowuj w pamięci podręcznej stabilne instrukcje systemu oraz schematy narzędzi. Ponowne wysyłanie identycznego preambułu jest częstą przyczyną marnotrawstwa zasobów.
Odkrywanie serwerów i inteligentne cacheowanie
Podczas prace nad etapem Odkrywania Serwerów i Inteligentnego Zarządzania, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Zachowuj w pamięci tymczasowej stabilne instrukcje systemowe oraz schematy narzędzi. Ponowne wysyłanie identycznego prefiksu to częsty powód marnotrawstwa zasobów. Podczas prace nad etapem Odkrywania Serwerów i Inteligentnego Zarządzania, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy przechodzi się z środowiska demonstracyjnego do współdzielonych środowisk.
{
"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"
}
Budowa serwera bezstanowego do produkcji: FastAPI, FastMCP 2.0 i OAuth 2.1
Etap budowy serwera bezstanowego do produkcji działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię do analizy. Zapisz jeden idealny przykład działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. Utrzymuj konfigurację poza kodem aplikacji. Pliki środowiskowe, składyce z danymi poufnymi oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Określ budżet tokenów na jeden ruch i jedną sesję. Narzędzia typu agentic intensywnie rozszerzają kontekst; sztywne limity zapobiegają temu, by demonstracje przerodziły się w niespodziewane rachunki.
+-----------------------------------------------------------------------------+
| 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
}
Zarządzanie ruchem z zerowym analizowaniem na poziomie warstwy 7: konfiguracja Envoy i Gateway
Faza zarządzania ruchem z zerowym analizowaniem na poziomie 7 działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię. Zanim rozszerzysz zakres, zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian.
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
Zarządzanie stanem bez sesji: prośby wielokrotnych wyjść i kompromisy
Etap zarządzania stanem bez sesji działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię. Zapisz jeden idealny zapis rozmowy, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Wolij małe, testowalne jednostki nad rozbudowane skrypty. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Określ budżet tokenów na jeden ruch i na jedną sesję. Narzędzia typu agentic intensywnie rozszerzają kontekst; sztywne limity zapobiegają temu, by demonstracje przerodziły się w niespodziewane rachunki. Etap zarządzania stanem bez sesji działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię. Zapisz jeden idealny zapis rozmowy, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy przechodzi się od demonstracji do wspólnych środowisk.
Interaktywny cykl wielokrotnych żądań (MRTR)
W fazie MRTR (Multi Round-Trip Request) należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić, nie musząc czytać całej struktury. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepiej używać ustrukturyzowanych wyników z walidacją schematu niż tekstu swobodnego.
Analiza kompromisów architektonicznych
W fazie analizy kompromisów architektonicznych należy zdefiniować dane wejściowe, osobę odpowiedzialną za daną czynność oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić tę czynność na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg procesu, jak i ścieżkę naprawczą. Próby ponownych działań, kontrola przez ludzi oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, należy preferować ustrukturyzowane wyniki z walidacją schematu zamiast tekstów w formie swobodnej.
Rozwój typu cloud-native: skalowanie MCP na Kubernetes i Serverless
Dla etapu MCP dotyczącego skalowania wdrożeń typu Cloud-Native należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, testowalne jednostki nad rozbudowanymi skryptami. Gdy dany krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepsze są ustrukturyzowane wyniki z walidacją schematu niż tekst w formie swobodnej.
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
Wniosek i kolejne kroki
W fazie Wniosków i Kolejnych Kroków należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadania. Przy następnym kroku, który polega na pisaniu kodu lub wywoływaniu narzędzia, preferuj strukturyzowane wyniki z walidacją schematu zamiast tekstów w formie swobodnej.
Zasoby z dodatkowymi informacjami
W fazie dostarczania zasobów i dodatkowych informacji należy określić dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy rejestrować czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepiej używać ustrukturyzowanych wyników z walidacją schematu niż tekstu w formie swobodnej.
Lista kontrolna operacyjna
Podczas pracy nad fazą listy kontrolnej operacyjnej najpierw należy spisać warunki umowy: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie.
Rozpatruj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy artefaktom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadań.
Zachowuj w pamięci tymczasowej stabilne instrukcje systemu oraz schematy narzędzi. Ponowne wysyłanie identycznego prefiksu jest częstą przyczyną problemów.
Ujawniaj narzędzia o wąskich schematach oraz z wyraźnymi oznaczeniami efektów ubocznych. Hostowie muszą wiedzieć, które wywołania zmieniają stan systemu, zanim je automatycznie zatwierdzą.
Gdy budżet na to pozwala, dodaj test dymny, który symuluje kluczową ścieżkę w procesie CI przy użyciu fixitów, a nie rzeczywistych, płatnych API.
Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponownych wywołań, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później.
Zanim zaczniesz promować tę architekturę, zamroź wersje, utwórz dokładny zapis dla kluczowych etapów realizacji oraz potwierdź kroki odwracania zmian. Środowiska współdzielone wymagają ograniczeń szybkości, weryfikacji przynależności użytkowników oraz wyraźnego właściciela odpowiedzialnego za rotację haseł. Wolisz nudną niezawodność od pomysłowych, jednorazowych demonstracji.
Uwaga dotycząca ecba7bb3b9c6: trzymaj klucze dostawcy poza repozytorium, ustaw ograniczenie liczby tokenów na sesję oraz przechowuj zapisy obok plików przygotowawczych do testów, aby późniejsze zmiany modeli pozostawały porównywalne.