כל אתר WIZZO CMS מכיל שרת MCP (Model Context Protocol) מובנה בכתובת POST /system/mcp. הוא מאפשר ללקוח AI לקרוא ולערוך תוכן באתר באותן הרשאות של מנהל אנושי: אותם פאנלים, אותה ולידציית טפסים ואותם hooks. בדף הזה תלמדו איך השרת עובד, אילו טוקנים קיימים, איך מגבילים כלים, ואיך מתחברים אליו.
system/ הוא api/core בריפו (בשרת: /system/core). {admin} הוא כתובת הפאנל של האתר. הגרסה הנוכחית של הליבה נמצאת ב-api/core/version.txt.מה השרת עושה#
השרת מממש את Streamable HTTP בגרסת JSON בלבד (בלי SSE). הוא מפרסם כלים שמפעילים את פאנלי הניהול של האתר, ומריץ אותם ב"loopback": בקשת HTTP פנימית לפאנל עם session זמני של המנהל שבשמו הטוקן רץ. לכן כל בדיקת הרשאה, ולידציה ו-callback של הפאנל פועלים בדיוק כמו בעבודה ידנית.
| רכיב | קובץ | תפקיד |
|---|---|---|
| שרת MCP | controllers/mcp.php | פרוטוקול, אימות טוקן, מסנן allowed_tools, לוג |
| מימוש הכלים | libraries/admin_mcp_tools.php | קטלוג, dispatch, dry-run, ledger, תור אישורים, loopback |
| כלים ייעודיים לאתר | libraries/agent_tools.php | רישום כלים עם AGENT_TOOLS::add_tool |
| שער חיצוני | libraries/external_mcp.php | חיבור לשער mcp.wizzo.market וכלי המוצרים |
מצבים אחרים של אותה מערכת מתוארים ב-קטלוג כלי ה-MCP, ב-כתיבת כלי MCP לאתר וב-סוכני AI.
הפרוטוקול#
- GET מחזיר
405עם שגיאת JSON-RPC-32000(אין תמיכה ב-SSE). DELETE מחזיר200ריק. OPTIONS מחזיר200עם CORS. כל שיטה אחרת מחזירה405. - הודעה אחת בכל בקשה. גוף שאינו אובייקט מחזיר
-32700, ומערך (batch) מחזיר-32600. - הודעות
notifications/...מחזירות202בלי גוף, עוד לפני האימות.
| method | תוצאה |
|---|---|
initialize | גרסת פרוטוקול (2024-11-05, 2025-03-26 או 2025-06-18; כל ערך אחר מקבל 2025-06-18), capabilities.tools.listChanged=false, serverInfo ו-instructions עם הנחיות שימוש |
ping | {} |
tools/list | {tools: [...]} מסונן לפי allowed_tools של הטוקן. עם ?native=1 כלי המוצרים החיצוניים מושמטים |
tools/call | {content:[{type:"text", text:<JSON>}], isError:bool} |
| אחר | -32601 Method not found |
שגיאות נפוצות: 401 עם -32000 כשאין טוקן תקף, 403 עם -32000 כשמוצר "mcp" לא פעיל (טוקן אנושי בלבד), ו--32602 לכלי לא מוכר או כזה שהטוקן לא מורשה לו. פרמטרים שגויים בתוך כלי חוזרים כ-isError:true ולא כשגיאת JSON-RPC.
native=1 מסנן רק את הרשימה
tools/call מאמת את שם הכלי מול המניפסט המלא ולא מול הרשימה המסוננת. לקוח שביקש native=1 עדיין יכול לקרוא לכלי מוצר בשמו. אל תסתמכו על native=1 כעל מנגנון הרשאות, השתמשו ב-allowed_tools.אימות וסוגי טוקנים#
הטוקן נקרא מ-Authorization: Bearer <token>, ואם הכותרת לא הגיעה (למשל באחסון cgi-fcgi שמפיל אותה) גם מ-?key= או מ-?token=. הוא נבדק בטבלה CRM_adminPanel_mcp_tokens: השורה חייבת להצביע על מנהל קיים, ו-expires_at לא יכול להיות בעבר. בכל קריאה last_used_at מתעדכן.
| סוג טוקן | מי מנפיק | המנהל שבשמו הוא רץ | תוקף | allowed_tools |
|---|---|---|---|---|
| Gateway ("Wizzo Market gateway") | external_mcp בחיבור האתר לשער, או POST /system/connector/mcp_connect | המנהל המחובר, ואם אין כזה המנהל הוותיק ביותר | ללא תפוגה | ללא הגבלה |
| Run token ("run #N, slug") | ai_agents_lib::mint_run_token() בתחילת ריצת סוכן | מנהל-בוט ייעודי לסוכן (agent_<slug>) | שעתיים (RUN_TOKEN_TTL_HOURS) | כלי הבסיס ועוד כלי הסוכן |
| Chat job token | ai_agents_lib::dispatch_chat_job() | המנהל האנושי ששיגר את המשימה | שעתיים | כמו בריצת סוכן |
טוקן בלי agent_id נחשב טוקן אנושי, ולכן מחייב שמוצר "mcp" יהיה פעיל ב-Wizzo Market של האתר. טוקן ריצה או chat job פטורים מהבדיקה.
בליבה אין ממשק להנפקת טוקן אישי למנהל. מנהל שרוצה לחבר לקוח MCP משלו עושה זאת דרך השער של Market. לבדיקות בסביבת פיתוח אפשר להכניס שורה ידנית:
INSERT INTO CRM_adminPanel_mcp_tokens (admin_id, name, token, expires_at, allowed_tools)
VALUES (7, 'dev laptop', '<64 hex תווים אקראיים>', DATE_ADD(NOW(), INTERVAL 7 DAY), '["list_panels","panel_schema","list_rows"]');
אין hashing לטוקנים בטבלה. כל מי שיש לו קריאת SELECT על CRM_adminPanel_mcp_tokens (למשל דרך כלי db_query) יכול להפעיל את הטוקן. תנו לטוקנים תוקף קצר, הגבילו אותם עם allowed_tools, ואל תכניסו אותם ל-git או ללוגים.
הגבלת כלים עם allowed_tools#
העמודה allowed_tools היא מערך JSON. ערך ריק או לא תקין אומר "הכל מותר". ההתאמה היא לשם מדויק, או לערך בצורת prefix:tool שהחלק שאחרי הנקודתיים שווה לשם הכלי (לכן cms:list_rows מתיר את list_rows). אין wildcards: הערך kama:* לא מתאים לאף כלי, וזה מכוון.
["list_panels", "panel_schema", "list_rows", "cms:search_media"]
לוג#
כל tools/call נרשם בטבלה CRM_safe_sql_log: admin_name בצורת mcp:<uname>, sql_query בצורת MCP <tool>, ב-details 2000 התווים הראשונים של הארגומנטים, וכתובת ה-IP.
חיבור לקוח#
בדיקה ידנית עם curl:
curl -s https://example.co.il/system/mcp \
-H 'Authorization: Bearer <token>' -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
curl -s 'https://example.co.il/system/mcp?native=1' \
-H 'Authorization: Bearer <token>' -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
curl -s https://example.co.il/system/mcp \
-H 'Authorization: Bearer <token>' -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"list_rows","arguments":{"panel":"articles","pgnm":1}}}'
השרת אינו תומך ב-OAuth, ולכן Claude Desktop ו-Cursor מתחברים דרך mcp-remote עם כותרת:
{
"mcpServers": {
"wizzo-site": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://example.co.il/system/mcp",
"--header", "Authorization: Bearer ${WIZZO_MCP_TOKEN}"],
"env": { "WIZZO_MCP_TOKEN": "<token>" }
}
}
}
שימוש מתוך PHP, בלי HTTP#
קוד של האתר יכול להפעיל את אותם כלים ישירות. call מחזיר ["ok" => true, "data" => ...] או ["ok" => false, "error" => ..., "extra" => ...]:
$this->load->library("admin_mcp_tools");
$tools = new admin_mcp_tools((int)ADMIN::get_id()); // בשם המנהל המחובר
$ret = $tools->call("list_rows", ["panel" => "articles", "q" => "ירושלים"]);
if ($ret["ok"]) print_r($ret["data"]["rows"]);
else echo $ret["error"];
הבנאי הוא admin_mcp_tools::__construct($admin_id, $context = []). ב-$context מעבירים agent_id ו-run_id כשרוצים התנהגות של ריצת סוכן (ledger, תור אישורים).
נקודות שכדאי להכיר#
הכלים פונים ל-CONFIG::$env_url. באתר שמאחורי Cloudflare או WAF יש להחריג את {admin}/* מאתגרים (challenge) עבור בקשות עם הכותרת AI-Client: mcp, אחרת כל כלי ייכשל ב-HTTP 403 או HTTP 503.
- פאנל בלי
panel_table(מסך מותאם) לא נתמך ב-list_rows,set_fieldו-delete_record. פאנל בלי טופס AJAX לא נתמך ב-save_record.panel_schemaמחזירtable_errorאוform_errorכשזה המצב. tools/listעשוי להתעכב עד כמה עשרות שניות כשה-cache של השער קר. לקוח עם timeout קצר יראה כשל בניסיון הראשון.- ה-session של ה-loopback תקף 600 שניות, ו-
mcp.phpיוצר מופע חדש בכלtools/call.
מפתח WizzoAI של האתר מוזרק לדפדפן של כל מנהל מחובר, והוא משמש גם לאימות קריאות מה-stream לאתר. גשר agent_mcp (ראו שרת הסוכן) מעניק יכולות רחבות למי שעובר את שער ה-IP והטוקן. ובצ'אט ה-AI של האדמין קיימות פעולות קריאה ל-DB שפתוחות לכל מנהל מחובר (ראו צ'אט AI ואוטומציות). הקפידו על רשימת מנהלים מצומצמת ועל הרשאות קבוצה מינימליות.