Smithery דחה את fast-mcp. Claude העביר את כל ה-MCP server ל-SDK הרשמי בחצי שעה — הכתיבה מחדש הייתה זולה כי השכבה הראשונה הייתה דקה.
בפרויקט smarts חיברנו MCP לפני שישה ימים. ביקשתי מ-Claude Code להעלות שלושה tools באמצעות ה-gem fast-mcp:
get_contract_info(chain, address) — שם החוזה, תג של מתאם פרוטוקול, ספירת function / eventread_contract_state(chain, address, function_name, args?) — קריאה אחת view / pure, cache של 60 שניותget_uniswap_v3_pool(chain, address) — פאנל V3 מלא: מחיר דו-כיווני, liquidity, tick, TVL בדולריםה-commit ההוא היה 27ca82e feat(mcp): serve live contract data over MCP via fast-mcp, ב-2026-04-21 ב-1:37 לפנות בוקר. בערך 30 דקות. עבר חלק.
שישה ימים אחר כך, הערב — 2026-04-27 ב-20:24 — דחפתי commit נוסף: 4df08fa feat(mcp): switch to official mcp gem with Streamable HTTP transport.
מה קרה בין שני ה-commits האלה?
הגשתי את smarts ל-Smithery (אינדקס של MCP servers) לרישום. הסורק שלהם זרק 405 מיד:
POST /mcp/sse → 405 Method Not Allowed
לקח לי קצת זמן להבין: fast-mcp 1.6.0 (latest release) עדיין מיישם את HTTP+SSE transport של MCP spec 2024-11-05. אבל לקוחות MCP מודרניים כבר עברו ל-Streamable HTTP של spec 2025-03-26 — endpoint יחיד, POST + DELETE על אותו URL, בלי נתיב נפרד של /sse.
במילים אחרות: ה-spec זז קדימה, וה-gem הדומיננטי בקהילה עוד לא הדביק.
לא התכוונתי לחכות ל-fast-mcp. שכבת ה-MCP server קיימת בשביל שהלקוחות יצרכו אותה — תאימות ל-spec שוקלת יותר מאיזה gem נעים יותר לכתוב.
החלפתי את fast-mcp ב-gem הרשמי של Anthropic — mcp 0.14.0. בסיבוב הזה פתחתי thread חדש ב-Amp (מתחת עדיין רץ Claude Opus, אותו אחד כמו ב-Claude Code).
מה נחת במהלך ההגירה:
Transport מחווט מחדש
# ישן: fast-mcp עושה mount אוטומטי על /mcp עם /sse
# חדש: mount מפורש, endpoint יחיד
mount StreamableHTTPTransport.new(server, stateless: true), at: "/mcp"
stateless: true הוא העיקר. ה-server לא מחזיק state per-session בזיכרון, מה שמאפשר ל-Puma לרוץ עם workers > 0 ולעלות בקנה מידה אופקי בלי sticky session.
שינוי מבנה של Tool API
הצורה הישנה של fast-mcp:
class GetContractInfoTool < ApplicationTool
arguments do
required(:chain).filled(:string)
required(:address).filled(:string)
end
def call(chain:, address:)
# לוגיקת ביזנס
end
end
ה-gem הרשמי דוחף את הצנרת של ה-SDK למחלקת הבסיס:
class ApplicationTool < MCP::Tool
def self.call(**args, server_context: nil)
hash = payload(**args)
MCP::Tool::Response.new([{ type: "text", text: hash.to_json }])
end
end
class GetContractInfoTool < ApplicationTool
input_schema(
properties: {
chain: { type: "string" },
address: { type: "string" }
},
required: %w[chain address]
)
def self.payload(chain:, address:)
# לוגיקת ביזנס, מחזיר Hash
end
end
תת-המחלקות אכפת להן רק איזה Hash מחזיר payload(**args); מחלקת הבסיס עוטפת אותו ב-text block JSON-encoded בתוך MCP::Tool::Response. שני יתרונות:
Tool.payload(chain:, address:), בלי לקלף את envelope הפרוטוקולאת ה-DSL של dry-schema החלפתי בליטרלים גולמיים של JSON Schema. נראה כמו צעד אחורה, אבל input_schema הוא בדיוק מה שלקוח קורא ישירות מ-MCP spec — לכתוב כמו פרימיטיב ה-spec יותר ישר.
טסטים בהעברה
433 טסטים, הוחלפו מ-Tool.new.call(...) ל-Tool.payload(...). כולם ירוקים.
סנכרון discovery / docs
.well-known/mcp.json עם transport: "streamable-http", protocol_version: "2025-03-26"https://smarts.md/mcpclaude mcp add שונה מ---transport sse ל---transport httpmcp כ-primary ו-fast-mcp כ-legacy/deprecatedהאינטגרציה הראשונה של MCP לקחה 30 דקות. הכתיבה מחדש בערך אותו דבר. שישה ימים בין השניים.
מה שהתבהר לי: באקוסיסטם צעיר כמו של MCP, gems מפגרים אחרי ה-spec — זו נורמה. fast-mcp לא רע — המתחזק שלו פעיל. הבעיה היא שהפרוטוקול עצמו מתקדם מהר יותר ממימושי צד שלישי. gem שנראה יציב השנה, יכול להיות "זה של ה-spec הישן" בעוד חצי שנה.
לו לפני חצי שנה הייתי כותב עשרת אלפי שורות לוגיקת ביזנס מעל fast-mcp, היום הייתי תקוע על ה-spec הישן — כי עלות הכתיבה מחדש הייתה גבוהה מדי בשבילי להתגייס אליה.
אבל מה שקרה באמת: שכבת fast-mcp הייתה מההתחלה wrapper דק. לוגיקת הביזנס חיה בתת-מחלקות של ApplicationTool. לכן עלות הכתיבה מחדש האמיתית הייתה:
היקר זה לוגיקת הביזנס. עוטפי פרוטוקול אמורים להיות זולים וניתנים לכתיבה מחדש. זה הטובה הכי גדולה ש-Claude Code עשה לי לפני שישה ימים — הוא לא דחף את לוגיקת הביזנס לתוך callbacks של fast-mcp. הוא בנה הפשטה נקייה של ApplicationTool שבולעת את ה-SDK. בגלל זה שישה ימים אחר כך החלפת SDK הצריכה רק מחלקת בסיס + schema.
מה שאפשר לי לעבור ב-6 ימים מ"אינטגרציה ראשונה" ל"שדרוג spec וכתיבה מחדש" זה היציבות של Claude כמודל הבסיסי — באיזה agent shell ספציפי הייתי, פחות משנה.
קוד מקור: https://github.com/defi-io/smarts