← 返回部落格

我們如何為 Godot 打造即時 MCP Server

拆解 VberAI 的 Godot MCP 架構:即時 Model Context Protocol 服務如何在不卡死場景樹的前提下,把 Godot 編輯器接到 AI 客戶端。

發布於
  • vberai
  • godot
  • mcp
  • architecture
  • realtime

為什麼 Godot 上的 MCP Server 必須「即時」

多數 MCP Demo 活在 REST 心態裡:模型問一句,工具回一段 JSON,往返兩秒也沒人在意。Godot 不一樣。編輯器握著活的 場景樹、資源導入管線,以及 Play 迴圈。若 MCP Server 堵住主執行緒——或只能看見過期的專案快照——AI 就不再像副駕,而像「多繞了一步的遠端檔案編輯器」。

我們為 VberAI 設計 Godot MCP 時,目標寫得很清楚:

  • AI 助手(Cursor、Claude、Windsurf 等 MCP 客戶端)必須能 操作編輯器,而不能只讀寫磁碟上的 .gd
  • 建立節點、重新命名、掛腳本、查詢選中項等動作,要在編輯器保持可回應的前提下完成
  • Play 模式與編輯模式上下文必須誠實——不安全的操作應結構化報錯,而不是悄悄失敗

本文是工程側的復盤:我們如何做出一個貼著 Godot 跑的 即時 MCP Server,而不是把工程假裝成靜態倉庫。

「只碰檔案」的 MCP 對引擎為何不夠

天真方案很誘人:

  1. 把 MCP Server 指到專案目錄
  2. 暴露 read_file / write_file / list_dir
  3. 讓模型編 GDScript,祈禱編輯器 Reload 順利

這對文件站夠用,對引擎工作會翻車:

  • 場景所有權在記憶體裡 — 未儲存的 .tscn、開啟的場景、編輯器選中,磁碟上都看不見
  • 導入管線有狀態 — 寫入 PNG ≠「資源已按正確導入設定就緒」
  • 訊號與節點路徑是圖資料 — 字串亂改會靜默拆線
  • 延遲會疊加 — 每次確認「節點出現了嗎」都再掃一遍檔案系統

我們需要的 MCP 表面,要貼近人在 Godot 停靠欄裡已經看到的東西:層級、類似 Inspector 的屬性、資源句柄——而不只是路徑字串。

架構總覽

Godot MCP 可看成三層協作:

MCP 客戶端(Cursor / Claude / …)
        │  JSON-RPC(stdio 或本地傳輸)

MCP Server(VberAI Godot 橋接程序)
        │  命令佇列 + 結果信封

Godot 編輯器外掛(GDExtension / Editor Plugin)
        │  主執行緒延遲呼叫

編輯器場景樹 / ResourceDB / 腳本編輯器

第一層 — MCP 工具面

工具刻意做小、做成動詞形態:

  • godot_get_scene_tree — 當前編輯場景的快照(類型 + 路徑)
  • godot_create_node / godot_set_property
  • godot_attach_script / godot_run_script_snippet(受控)
  • godot_list_resources / godot_get_selection

避免一個巨大的 do_anything。小工具更容易校驗、更好記日誌,模型也更難刷出失控大補丁。

第二層 — 即時橋

「即時」真正發生在這裡:

  • MCP 程序與編輯器外掛之間的 雙向通道(開發期常用本地 socket / 命名管道;產品建構可由 VberAI 桌面助手封裝)
  • 命令佇列,把寫操作序列化,避免兩次工具呼叫在場景樹上競態
  • 請求 ID + 確認,讓 MCP 客戶端等待「已應用」,而不是輪詢檔案系統
  • 心跳 / 編輯器存活探測,客戶端能立刻知道 Godot 中途退出

第三層 — Godot 主執行緒安全

Godot 的 UI 與場景 API 不是自由多執行緒的。外掛從不在 MCP I/O 執行緒上改節點,而是:

  1. 橋執行緒收到 MCP 命令
  2. 入隊
  3. 編輯器在空閒幀 / call_deferred 上執行
  4. 結果信封回傳成功、結構化錯誤,或「Play 結束後再試」

這套模式刻意無聊。無聊,才能讓「即時」不變成「隨機卡死編輯器」。

如何讓它「感覺」即時(又不撒謊)

這裡的即時不是魔法零延遲,而是 回饋環貼近人在編輯器裡的工作節奏

快照 vs 增量

早期原型每次整樹序列化,大開放世界工程一碰就塌。我們改成:

  • 預設 淺快照(根 + 一層,或以選中為中心)
  • 模型已知子樹時用 路徑作用域讀取
  • 可選 變更 token:後續只問「相對 X 改了什麼」,而不是整樹重傳

便於模型繼續操作的結果

工具回傳盡量包含:

  • 規範的 NodePath
  • 類型名(CharacterBody2DControl 等)
  • 能映射到 Inspector 欄位的屬性鍵
  • 寫入已生效但場景仍 dirty / 未儲存時的明確警告

結果看起來像 UI 狀態,而不是散文,模型迭代會快很多。

有邊界的 Play 行為

一半「AI 弄壞工程」的工單都發生在 Play 模式。我們的規則:

模式允許禁止或閘控
編輯場景變更、資源查詢無確認的破壞性工程刪除
Play多為唯讀 / 查詢執行時期節點改正在編輯的場景結構
切換中等待 / 重試提示靜默空操作

清晰錯誤勝過自作聰明。若 Play 中不可編輯,MCP 就用結構化結果說清楚——客戶端可提示使用者先停 Play,再重試。

我們踩過、並且留下的硬問題

1. 編輯器不是資料庫

節點順序、owner 關係、打包場景的組合,在展示 GIF 裡很簡單,在 .tscn 裡很髒。我們盡量站在 Godot 自有 API 上(NodeEditorInterface、資源載入),而不是另造一套會漂移的平行場景模型。

2. 腳本與場景是兩套真相源

掛上腳本 ≠ 編譯通過且類名已解析。Server 把編譯 / 掛載結果分開回報,壓掉一類「工具報成功、Inspector 什麼也沒有」的故障。

3. 多視窗 / 多工程會話

開發者會開多個 Godot 實例。橋綁定明確的編輯器會話 ID,避免週末睡一覺再打開後,工具呼叫打進錯誤工程。

4. 安全邊界

能改寫場景的 MCP Server 權限很大。本地優先傳輸、明確工具白名單、禁止靜默外傳整棵工程樹,是底線。「AI 助手」和「對著你的遊戲開遠端殼」必須是不同品類。

與 AI Studio 及 VberAI 棧的銜接

Godot MCP 扮演 引擎操作者。互補部件包括:

  • VberAI AI StudioAI Studio)— 設計稿(Figma/PSD)到引擎結構;MCP 再在導入後接線、重新命名節點
  • Unity MCP / Cocos MCP — 同一套 MCP 思路,不同宿主編輯器與安全規則
  • AI Super Matting — 貼圖進入引擎、再被 MCP 賦值之前做透明去背

共同主張:AI 應觸達 活的生產面(編輯器、資源、場景),而不只是倉庫文字。

若你要自建引擎 MCP:幾條實用建議

  1. 寫操作排隊到引擎主執行緒 — 別假裝遊戲引擎是無共享的伺服器
  2. 工具宜小、有 schema — 校驗勝過堆砌提示詞
  3. 回傳 NodePath 與類型,而不是散文 — 模型需要可操作句柄
  4. 每次回應標明 Play / 編輯模式 — 這裡含糊會毀掉信任
  5. 度量「停靠欄裡看見了」的往返 — 不只量 JSON 編碼時間

若只優化 MCP 程序、忽略編輯器橋,你只會得到一條更快的幻覺迴路。

結語

為 Godot 打造即時 MCP Server,本質是把編輯器當成線上協作者:佇列化、主執行緒安全的橋;形狀像編輯器動作的工具;以及對 Play 邊界的誠實。只用檔案的 MCP 更簡單——但對場景原生工作來說不完整。

想直接走現成路徑,而不是週末原型?從 VberAI Godot MCP 起步,接上你常用的 MCP 客戶端,先做一次最簡單的工具呼叫:列出當前場景樹,再在選中節點下建立一個子節點。查詢 → 變更 → 在停靠欄看見——這就是產品本身;其餘都是圍繞它的可靠性工程。

你可能還會喜歡這些文章