מבוא: מהפכת ה-MCP בעולם הסוכנים החכמים
אם אתם עובדים עם סוכני AI בשנת 2026, כנראה שכבר נתקלתם במונח MCP — Model Context Protocol. מה שהתחיל כפרויקט קוד פתוח של Anthropic הפך בתוך זמן קצר יחסית לסטנדרט המוביל לחיבור סוכני בינה מלאכותית לכלים, מקורות מידע ושירותים חיצוניים. והמספרים מדברים בעד עצמם: כמעט 2,000 שרתי MCP רשומים — צמיחה של 407% מאז השקת הרישום בספטמבר 2025.
פלטפורמות כמו Claude, ChatGPT ו-Gemini תומכות כיום ב-MCP באופן מקורי, וארגונים ברחבי העולם כבר עברו מפיילוטים לפריסות ייצור מלאות.
אז בואו נצלול פנימה. במדריך הזה נעבור יחד את כל הדרך — מהבנת הארכיטקטורה ועד לפריסה בסביבת ייצור. נכסה את שלושת הרכיבים המרכזיים (כלים, משאבים ותבניות), נבנה שרת עובד ב-Python עם FastMCP, ונדבר על שיטות עבודה מומלצות לאבטחה, ניטור ותפעול.
מהו פרוטוקול MCP ולמה זה חשוב?
בקצרה: פרוטוקול MCP מגדיר ממשק סטנדרטי בין יישומי LLM (הלקוחות) לבין שירותים חיצוניים (השרתים). במקום לכתוב אינטגרציות ייחודיות לכל מודל שפה או פלטפורמה, שרת MCP יחיד יכול לשרת כל לקוח תואם MCP.
חשבו על זה כמו REST API בעולם הווב — סטנדרט אחד, תאימות רחבה. פשוט עובד.
שלושת עמודי התווך של MCP
כל שרת MCP חושף שלושה סוגים של יכולות:
- כלים (Tools) — פעולות שהמודל יכול לבצע, בדומה לנקודות קצה מסוג POST. לדוגמה: שליחת אימייל, שאילתת מסד נתונים, או יצירת קובץ.
- משאבים (Resources) — מקורות מידע שהמודל יכול לקרוא, בדומה לנקודות קצה מסוג GET. לדוגמה: קריאת קובץ תצורה, שליפת נתוני לקוח, או גישה לתיעוד.
- תבניות (Prompts) — תבניות אינטראקציה מוכנות מראש שמגדירות דפוסי עבודה עבור ה-LLM. לדוגמה: תבנית לניתוח קוד, תבנית ליצירת דוח, או תבנית לתמיכת לקוחות.
ארכיטקטורת התקשורת
MCP מגדיר שני מנגנוני תעבורה עיקריים, ושווה להכיר את שניהם:
- stdio — השרת רץ כתהליך מקומי, והתקשורת מתבצעת דרך קלט/פלט סטנדרטי. מתאים לפיתוח מקומי ולכלים שרצים על מחשב המפתח. ללא צורך באימות.
- Streamable HTTP — השרת פועל כתהליך עצמאי שמטפל בחיבורים מרובים. משתמש בבקשות POST ו-GET סטנדרטיות, עם אפשרות לשדרוג ל-Server-Sent Events (SSE) לזרמי תגובות ארוכים. תומך באימות OAuth 2.1.
חשוב לדעת: במפרט 2025-06-18, תעבורת Streamable HTTP החליפה את תעבורת HTTP+SSE הישנה. היתרון המרכזי? שימוש בפרוטוקול HTTP סטנדרטי שמאפשר שילוב עם middleware קיים — CORS, אימות, ניתוב ו-load balancing — בלי לפתח פתרונות מותאמים מאפס.
הקמת סביבת פיתוח
בואו נתחיל לעבוד. אנחנו ממליצים על Python עם FastMCP — שהפך לדרך הפופולרית ביותר לבניית שרתי MCP, בזכות ה-API הנקי והפייתוני שלו.
התקנת כלים
# יצירת סביבה וירטואלית
python -m venv mcp-server-env
source mcp-server-env/bin/activate
# התקנת FastMCP
pip install fastmcp
# או באמצעות uv (מומלץ)
uv pip install fastmcp
מעדיפים TypeScript? אין בעיה. התקינו את ה-SDK הרשמי:
npm install @modelcontextprotocol/sdk zod@3
מבנה הפרויקט המומלץ
my-mcp-server/
├── server.py # נקודת כניסה ראשית
├── tools/
│ ├── __init__.py
│ ├── database.py # כלים לגישה למסד נתונים
│ └── notifications.py # כלים לשליחת התראות
├── resources/
│ ├── __init__.py
│ └── config.py # משאבי תצורה
├── prompts/
│ ├── __init__.py
│ └── templates.py # תבניות אינטראקציה
├── tests/
│ └── test_server.py
├── pyproject.toml
└── README.md
בניית שרת MCP ראשון עם FastMCP
עכשיו מגיע החלק הכיף. נבנה שרת MCP לניהול משימות — דוגמה מעשית שמדגימה יפה את שלושת סוגי היכולות.
הגדרת השרת הבסיסי
from fastmcp import FastMCP
from datetime import datetime
from typing import Optional
# יצירת שרת MCP
mcp = FastMCP(
name="Task Manager",
description="שרת MCP לניהול משימות"
)
# אחסון משימות בזיכרון (בייצור — מסד נתונים)
tasks: dict[str, dict] = {}
הוספת כלים (Tools)
כלים הם הרכיב הנפוץ ביותר בשרתי MCP. כל כלי מוגדר כפונקציה עם דקורטור @mcp.tool():
@mcp.tool()
def create_task(
title: str,
description: str,
priority: str = "medium",
due_date: Optional[str] = None
) -> dict:
"""Create a new task with title, description, priority and optional due date."""
task_id = f"task_{len(tasks) + 1}"
task = {
"id": task_id,
"title": title,
"description": description,
"priority": priority,
"status": "pending",
"due_date": due_date,
"created_at": datetime.utcnow().isoformat()
}
tasks[task_id] = task
return {"success": True, "task": task}
@mcp.tool()
def update_task_status(task_id: str, status: str) -> dict:
"""Update the status of an existing task.
Valid statuses: pending, in_progress, completed, cancelled.
"""
if task_id not in tasks:
return {"success": False, "error": f"Task {task_id} not found"}
valid_statuses = ["pending", "in_progress", "completed", "cancelled"]
if status not in valid_statuses:
return {"success": False, "error": f"Invalid status. Use: {valid_statuses}"}
tasks[task_id]["status"] = status
tasks[task_id]["updated_at"] = datetime.utcnow().isoformat()
return {"success": True, "task": tasks[task_id]}
@mcp.tool()
def list_tasks(
status_filter: Optional[str] = None,
priority_filter: Optional[str] = None
) -> dict:
"""List all tasks with optional filtering by status or priority."""
filtered = list(tasks.values())
if status_filter:
filtered = [t for t in filtered if t["status"] == status_filter]
if priority_filter:
filtered = [t for t in filtered if t["priority"] == priority_filter]
return {"count": len(filtered), "tasks": filtered}
שימו לב לנקודה חשובה כאן: כל כלי מלווה ב-docstring מפורט שמסביר ל-LLM מה הכלי עושה ואילו פרמטרים הוא מקבל. מניסיון — כדאי לכתוב לפחות 3-4 משפטים בתיאור הכלי. ככל שההקשר עשיר יותר, כך המודל ישתמש בכלי בצורה מדויקת יותר. אל תחסכו במילים פה.
הוספת משאבים (Resources)
משאבים חושפים מידע לקריאה בלבד. הנה איך זה נראה בפועל:
@mcp.resource("tasks://summary")
def get_tasks_summary() -> str:
"""Get a summary of all tasks by status."""
summary = {
"total": len(tasks),
"pending": len([t for t in tasks.values() if t["status"] == "pending"]),
"in_progress": len([t for t in tasks.values() if t["status"] == "in_progress"]),
"completed": len([t for t in tasks.values() if t["status"] == "completed"]),
"cancelled": len([t for t in tasks.values() if t["status"] == "cancelled"]),
}
return str(summary)
@mcp.resource("tasks://{task_id}")
def get_task_details(task_id: str) -> str:
"""Get detailed information about a specific task."""
if task_id in tasks:
return str(tasks[task_id])
return f"Task {task_id} not found"
הוספת תבניות (Prompts)
תבניות מגדירות דפוסי אינטראקציה חוזרים — משהו שחוסך הרבה זמן כשעובדים עם סוכנים:
from fastmcp.prompts import base
@mcp.prompt()
def daily_standup() -> list[base.Message]:
"""Generate a daily standup report based on current tasks."""
return [
base.UserMessage(
content="""Review the current tasks and generate a daily standup report with:
1. What was completed yesterday
2. What is in progress today
3. Any blockers or high-priority items
Format the response as a clear, concise standup update."""
)
]
@mcp.prompt()
def prioritize_tasks() -> list[base.Message]:
"""Help prioritize the current task list."""
return [
base.UserMessage(
content="""Analyze the current task list and suggest a priority order.
Consider: due dates, current status, priority levels, and dependencies.
Provide actionable recommendations for the team."""
)
]
הרצת השרת
# בתחתית server.py
if __name__ == "__main__":
# stdio — לפיתוח מקומי
mcp.run(transport="stdio")
# או Streamable HTTP — לייצור
# mcp.run(transport="streamable-http", host="0.0.0.0", port=8000)
בדיקה ודיבאג עם MCP Inspector
לפני שממשיכים הלאה, בואו נדבר על MCP Inspector. בכנות, זה אחד הכלים שחסכו לי הכי הרבה זמן בפיתוח. זהו כלי גרפי שמאפשר להתחבר לשרת MCP, לגלות את הכלים והמשאבים שהוא חושף, ולבצע קריאות בדיקה — הכל בלי להפעיל LLM.
# התקנת MCP Inspector
npx @modelcontextprotocol/inspector
# חיבור לשרת stdio
npx @modelcontextprotocol/inspector python server.py
# חיבור לשרת HTTP
# הרצת השרת תחילה, ואז חיבור ל-http://localhost:8000/mcp
ה-Inspector מציג את כל הכלים, המשאבים והתבניות הזמינים, ומאפשר לשלוח קריאות ידניות ולבדוק את התגובות. חיוני בשלב הפיתוח — חוסך זמן רב בהשוואה לדיבאג עם LLM מלא.
שרת MCP ב-TypeScript
עבור צוותים שעובדים בסביבת TypeScript, הנה דוגמה מקבילה עם ה-SDK הרשמי. הקוד קצת יותר ארוך מגרסת ה-Python, אבל לא פחות ברור:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
const server = new McpServer({
name: "Task Manager",
version: "1.0.0"
});
// הגדרת כלי
server.tool(
"create_task",
"Create a new task with title, description and priority",
{
title: z.string().describe("Task title"),
description: z.string().describe("Task description"),
priority: z.enum(["low", "medium", "high"]).default("medium")
},
async ({ title, description, priority }) => {
const taskId = `task_${Date.now()}`;
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
task: { id: taskId, title, description, priority, status: "pending" }
})
}]
};
}
);
// הגדרת משאב
server.resource(
"tasks-summary",
"tasks://summary",
async (uri) => ({
contents: [{
uri: uri.href,
mimeType: "application/json",
text: JSON.stringify({ total: 0, pending: 0, completed: 0 })
}]
})
);
חיבור ללקוחות MCP
טוב, אז בנינו שרת. עכשיו צריך לחבר אותו ללקוחות. הנה כמה דוגמאות מעשיות:
תצורה ב-Claude Desktop
{
"mcpServers": {
"task-manager": {
"command": "python",
"args": ["path/to/server.py"],
"env": {
"DATABASE_URL": "postgresql://localhost/tasks"
}
}
}
}
חיבור תוכנתי ב-Python
from fastmcp import Client
async def main():
# חיבור לשרת stdio
async with Client("python server.py") as client:
# קריאה לכלי
result = await client.call_tool(
"create_task",
{
"title": "Review PR #42",
"description": "Review and approve pull request",
"priority": "high"
}
)
print(result)
# קריאת משאב
summary = await client.read_resource("tasks://summary")
print(summary)
import asyncio
asyncio.run(main())
דפוסי תכנון מתקדמים
ניהול מצב ומסד נתונים
בסביבת ייצור, ברור שאי אפשר לאחסן נתונים בזיכרון. הנה דוגמה לשילוב עם מסד נתונים באמצעות ה-lifespan pattern:
import asyncpg
from contextlib import asynccontextmanager
from fastmcp import FastMCP, Context
@asynccontextmanager
async def app_lifespan(server: FastMCP):
"""Manage database connection pool lifecycle."""
pool = await asyncpg.create_pool(
"postgresql://localhost/tasks",
min_size=5,
max_size=20
)
try:
yield {"db_pool": pool}
finally:
await pool.close()
mcp = FastMCP("Task Manager", lifespan=app_lifespan)
@mcp.tool()
async def create_task(title: str, description: str, ctx: Context) -> dict:
"""Create a new task in the database."""
pool = ctx.request_context.lifespan_context["db_pool"]
async with pool.acquire() as conn:
row = await conn.fetchrow(
"""INSERT INTO tasks (title, description, status, created_at)
VALUES ($1, $2, 'pending', NOW())
RETURNING id, title, description, status, created_at""",
title, description
)
return {"success": True, "task": dict(row)}
הזרמת תוצאות (Streaming)
עבור פעולות שלוקחות זמן, אפשר להזרים תוצאות חלקיות ללקוח. זה עושה הבדל גדול בחוויית המשתמש:
@mcp.tool()
async def analyze_large_dataset(dataset_path: str, ctx: Context) -> str:
"""Analyze a large dataset and report progress."""
total_rows = count_rows(dataset_path)
for i, chunk in enumerate(read_in_chunks(dataset_path)):
# דיווח התקדמות
await ctx.report_progress(
progress=i * 100,
total=total_rows
)
# עיבוד הנתונים
process_chunk(chunk)
return "Analysis complete"
טיפול בשגיאות והתאוששות
from fastmcp.exceptions import ToolError
@mcp.tool()
async def query_external_api(endpoint: str, params: dict) -> dict:
"""Query an external API with retry logic."""
import httpx
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(min=1, max=10))
async def _fetch():
async with httpx.AsyncClient(timeout=30) as client:
response = await client.get(endpoint, params=params)
response.raise_for_status()
return response.json()
try:
data = await _fetch()
return {"success": True, "data": data}
except httpx.HTTPStatusError as e:
raise ToolError(f"API returned {e.response.status_code}: {e.response.text}")
except Exception as e:
raise ToolError(f"Failed to query API: {str(e)}")
אבטחת שרת MCP בסביבת ייצור
אוקיי, עכשיו נגיע לנושא שהכי חשוב (ולצערי, הכי מוזנח): אבטחה. בשנת 2026, עם כניסתו לתוקף של חוק ה-AI של האיחוד האירופי (EU AI Act), ארגונים חשופים לקנסות של עד 7% מההכנסות השנתיות הגלובליות בגין הפרות חמורות. זה לא משחק.
אימות והרשאות
from fastmcp import FastMCP
from fastmcp.server.auth import BearerTokenAuth
# הגדרת אימות OAuth 2.1
auth = BearerTokenAuth(
jwks_url="https://auth.example.com/.well-known/jwks.json",
issuer="https://auth.example.com",
audience="mcp-task-manager"
)
mcp = FastMCP(
"Task Manager",
auth=auth,
# הגבלת גישה ברמת כלי
permissions={
"create_task": ["tasks:write"],
"list_tasks": ["tasks:read"],
"update_task_status": ["tasks:write"],
}
)
וולידציית קלט ומניעת הזרקות
כל קלט שמגיע מ-LLM חייב לעבור וולידציה קפדנית. וזה הדבר שרוב המפתחים מפספסים — ה-LLM עשוי להיות מושפע מהזרקת prompt, אז אל תסמכו על הקלט שלו באופן עיוור:
from pydantic import BaseModel, Field, validator
import re
class TaskInput(BaseModel):
title: str = Field(..., min_length=1, max_length=200)
description: str = Field(..., min_length=1, max_length=2000)
priority: str = Field(default="medium")
@validator("title", "description")
def sanitize_input(cls, v):
# הסרת תווים מסוכנים ומניעת הזרקת SQL/XSS
v = re.sub(r'[<>"\';]', '', v)
# מניעת הזרקת prompt
dangerous_patterns = [
r'ignore\s+previous\s+instructions',
r'system\s*:',
r'<\|.*\|>',
]
for pattern in dangerous_patterns:
if re.search(pattern, v, re.IGNORECASE):
raise ValueError("Input contains potentially harmful content")
return v.strip()
@mcp.tool()
async def create_task_safe(input_data: TaskInput) -> dict:
"""Create a task with validated input."""
# הקלט כבר עבר וולידציה דרך Pydantic
return await _create_task(input_data.title, input_data.description)
בידוד רשתי
שרתי MCP צריכים לפעול בסביבות מבודדות. כמה כללי אצבע:
- הפעלה ב-VPC ייעודי או namespace מבודד ב-Kubernetes
- הימנעות מחשיפת שרתים ישירות לאינטרנט — תמיד דרך API Gateway
- הצפנת תעבורה עם mTLS בין רכיבים פנימיים
- שימוש ב-Web Application Firewall (WAF) לסינון בקשות חשודות
אימות כותרות Origin
# Streamable HTTP — הגנה מפני התקפות DNS rebinding
mcp = FastMCP(
"Task Manager",
allowed_origins=["https://app.example.com", "https://claude.ai"],
cors_allow_methods=["GET", "POST"],
cors_allow_headers=["Authorization", "Content-Type"]
)
ניטור, לוגים וניהול בייצור
לוגים מובנים
לוגים טובים הם לא רק "נחמד שיש" — הם מה שמציל אתכם ב-3 בלילה כשמשהו נשבר. הנה דוגמה לגישה מובנית:
import structlog
import time
logger = structlog.get_logger()
@mcp.tool()
async def create_task_with_logging(
title: str,
description: str,
ctx: Context
) -> dict:
"""Create a task with comprehensive audit logging."""
start_time = time.time()
log = logger.bind(
tool="create_task",
user_id=ctx.request_context.get("user_id"),
session_id=ctx.request_context.get("session_id")
)
log.info("tool_invoked", title=title)
try:
result = await _create_task(title, description)
duration = time.time() - start_time
log.info(
"tool_completed",
task_id=result["task"]["id"],
duration_ms=round(duration * 1000)
)
return result
except Exception as e:
log.error("tool_failed", error=str(e))
raise
מטריקות וניטור
from prometheus_client import Counter, Histogram
# הגדרת מטריקות
tool_calls_total = Counter(
"mcp_tool_calls_total",
"Total number of MCP tool calls",
["tool_name", "status"]
)
tool_duration_seconds = Histogram(
"mcp_tool_duration_seconds",
"Duration of MCP tool calls",
["tool_name"],
buckets=[0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0]
)
# שילוב בכלי
@mcp.tool()
async def monitored_tool(query: str) -> dict:
"""A tool with Prometheus metrics."""
with tool_duration_seconds.labels(tool_name="monitored_tool").time():
try:
result = await process_query(query)
tool_calls_total.labels(
tool_name="monitored_tool", status="success"
).inc()
return result
except Exception:
tool_calls_total.labels(
tool_name="monitored_tool", status="error"
).inc()
raise
בדיקות בריאות
@mcp.tool()
async def health_check() -> dict:
"""Check the health of the MCP server and its dependencies."""
checks = {}
# בדיקת מסד נתונים
try:
await db_pool.fetchval("SELECT 1")
checks["database"] = "healthy"
except Exception as e:
checks["database"] = f"unhealthy: {str(e)}"
# בדיקת שירותים חיצוניים
try:
async with httpx.AsyncClient(timeout=5) as client:
resp = await client.get("https://api.example.com/health")
checks["external_api"] = "healthy" if resp.status_code == 200 else "degraded"
except Exception:
checks["external_api"] = "unhealthy"
overall = "healthy" if all(v == "healthy" for v in checks.values()) else "degraded"
return {"status": overall, "checks": checks}
פריסה בסביבת ייצור
קונטיינריזציה עם Docker
הנה Dockerfile שעובד טוב עבור שרתי MCP (שימו לב שאנחנו מריצים כמשתמש לא-root — זה חשוב):
FROM python:3.12-slim
WORKDIR /app
# התקנת תלויות
COPY pyproject.toml .
RUN pip install --no-cache-dir -e .
# העתקת קוד
COPY . .
# הגדרת משתנים
ENV MCP_TRANSPORT=streamable-http
ENV MCP_HOST=0.0.0.0
ENV MCP_PORT=8000
# הגדרת משתמש לא-root
RUN useradd -m mcpuser
USER mcpuser
EXPOSE 8000
CMD ["python", "server.py"]
פריסה ב-Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcp-task-manager
spec:
replicas: 3
selector:
matchLabels:
app: mcp-task-manager
template:
metadata:
labels:
app: mcp-task-manager
spec:
containers:
- name: mcp-server
image: myregistry/mcp-task-manager:latest
ports:
- containerPort: 8000
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: mcp-secrets
key: database-url
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: mcp-task-manager
spec:
selector:
app: mcp-task-manager
ports:
- port: 80
targetPort: 8000
type: ClusterIP
שיטות עבודה מומלצות ולקחים מהשטח
1. תיאורי כלים מפורטים — באמת
לא מספיק לכתוב docstring של שורה אחת. איכות תיאורי הכלים משפיעה ישירות על הדיוק שבו ה-LLM ישתמש בהם. כתבו לפחות 3-4 משפטים לכל כלי, ציינו סוגי פרמטרים, ערכים חוקיים, ודוגמאות. עבור כלים מורכבים, השתמשו בשדה input_examples עם דוגמאות מאומתות סכמה.
2. מצב strict לייצור
הוסיפו strict: true להגדרות הכלים כדי להבטיח שקריאות הכלי של ה-LLM תמיד תואמות את הסכמה — ללא אי-התאמות סוגים או שדות חסרים. קריטי בייצור, שם פרמטרים לא תקינים גורמים לכשלים שקשה לאבחן.
3. טיפול חסין בקלט
לעולם אל תסמכו על קלט מ-LLM ללא וולידציה. השתמשו ב-Pydantic או zod לאימות סכמה, סננו תווים מסוכנים, והגנו מפני הזרקות SQL, XSS והזרקות prompt. אמרנו את זה קודם, אבל שווה לחזור על זה.
4. ביצועים ותגובתיות
- השתמשו בחיבורי מסד נתונים מאוגדים (connection pooling)
- הגדירו timeouts סבירים לפעולות חיצוניות (30 שניות זה מקסימום סביר ברוב המקרים)
- הזרימו תוצאות לפעולות ארוכות במקום להמתין להשלמה
- השתמשו במטמון (caching) לנתונים שמשתנים לעיתים רחוקות
5. ניהול ממשל (Governance)
- הקימו מועצת אישור לפריסת שרתי MCP חדשים שכוללת אנשי אבטחה, משפט ועסקים
- הגדירו בקרת גישה מבוססת תפקידים (RBAC) בהתאם למבנה הארגוני
- תעדו כל שרת MCP — מי פיתח אותו, מה הוא עושה, ולאילו מקורות מידע יש לו גישה
- ערכו סקירות אבטחה תקופתיות ובדקו עמידה בתקנות כמו GDPR ו-EU AI Act
בדיקות אוטומטיות לשרת MCP
לא משנה כמה אתם בטוחים בקוד — כתבו בדיקות. הנה דוגמה מלאה:
import pytest
from fastmcp import Client
@pytest.fixture
async def client():
"""Create a test client for the MCP server."""
async with Client("python server.py") as c:
yield c
@pytest.mark.asyncio
async def test_create_task(client):
result = await client.call_tool("create_task", {
"title": "Test Task",
"description": "A test task",
"priority": "high"
})
assert result["success"] is True
assert result["task"]["title"] == "Test Task"
assert result["task"]["status"] == "pending"
@pytest.mark.asyncio
async def test_update_task_status(client):
# יצירת משימה
create_result = await client.call_tool("create_task", {
"title": "Status Test",
"description": "Testing status update"
})
task_id = create_result["task"]["id"]
# עדכון סטטוס
update_result = await client.call_tool("update_task_status", {
"task_id": task_id,
"status": "completed"
})
assert update_result["success"] is True
assert update_result["task"]["status"] == "completed"
@pytest.mark.asyncio
async def test_invalid_status_rejected(client):
create_result = await client.call_tool("create_task", {
"title": "Validation Test",
"description": "Testing validation"
})
task_id = create_result["task"]["id"]
result = await client.call_tool("update_task_status", {
"task_id": task_id,
"status": "invalid_status"
})
assert result["success"] is False
@pytest.mark.asyncio
async def test_tasks_summary_resource(client):
summary = await client.read_resource("tasks://summary")
assert "total" in summary
מבט לעתיד: מגמות MCP בשנת 2026 ואילך
המערכת האקולוגית של MCP ממשיכה להתפתח במהירות מרשימה. הנה המגמות שכדאי לשים אליהן לב:
- תמיכה מולטימודלית — MCP מתחיל לתמוך בתמונות, וידאו, אודיו וסוגי מדיה נוספים. לא רק טקסט יותר.
- MCP Apps — יורשי MCP-UI, שמאפשרים לסוכנים להציג ממשקים חזותיים ולא רק להגיב בטקסט. זה משנה את חוויית המשתמש לחלוטין.
- MCP Gateway — שכבת ניהול מרכזית לארגונים שמפעילים עשרות או מאות שרתי MCP, עם אימות, ניתוב, rate limiting ולוגים מרכזיים.
- גרסת v2 יציבה — צפויה ברבעון הראשון של 2026, עם שיפורים משמעותיים בממשק ובביצועים.
- שוק שרתים (Marketplace) — גלישה, גילוי והתקנת שרתי MCP מוכנים לשימוש, בדומה ל-npm או PyPI. פשוט מחפשים, מתקינים, ומתחילים לעבוד.
סיכום
פרוטוקול MCP משנה את הדרך שבה סוכני AI מתקשרים עם מערכות חיצוניות, ובשנת 2026 הוא כבר לא ניסיוני — הוא סטנדרט ייצור אמיתי.
מבחינה טכנית, בניית שרת MCP היא לא מסובכת. FastMCP ב-Python או ה-SDK הרשמי ב-TypeScript מאפשרים להקים שרת עובד בדקות ספורות. האתגר האמיתי? פריסת ייצור — אבטחה, ניטור, ניהול ממשל ועמידה בתקנות.
ההמלצה שלי: התחילו בשרת פשוט עם כלי אחד או שניים, בדקו אותו עם MCP Inspector, ורק אחרי שהוא עובד כמו שצריך — הוסיפו אימות, לוגים ומטריקות. הרחיבו בהדרגה, ותעדו כל כלי ומשאב. כך בונים שרתי MCP שעובדים באמת.