Skip to main content
本地函式是你放進 BRICKS Buttress 伺服器某個目錄裡的 .ts / .js 檔案。每個檔案同時成為一個 MCP 工具一個 HTTP 端點,讓 agent(或任何 HTTP 用戶端)能在伺服器上執行工作:呼叫 ffmpeg、使用該伺服器自己的 LLM、語音轉文字與文字轉語音 generator,或連線到內部服務。你只需要寫一個檔案,不需要另外架一套服務。
本地函式屬於實驗性功能。端點、函式檔案契約、context API、自訂 _auth 以及 [functions] 設定鍵都可能在版本之間變動,且不保證有淘汰緩衝期。伺服器啟動時會顯示這項提醒。若你要以此為基礎開發,請鎖定 bricks-buttress 版本,並在升級後重新閱讀本頁。
本地函式與 Buttress 的其他部分不同。其他地方的 Buttress 是把 BRICKS Foundation 裝置原本要自己跑的 generator 卸載到伺服器;本地函式則是在伺服器上執行,由維運者撰寫,並由 agent 與 HTTP 用戶端呼叫,而不是由應用程式執行階段呼叫。

啟用

本地函式預設關閉。在伺服器 TOML 中加入 [functions] 區段即可啟用:
前三個鍵有對應的環境變數:ENABLE_FUNCTIONS_ENDPOINT=1BUTTRESS_FUNCTIONS_DIR=<dir>BUTTRESS_FUNCTIONS_HOT_RELOAD=1BUTTRESS_FUNCTIONS_ALLOW_UNAUTHENTICATED=1 則對應 allow_unauthenticated
若設定了 enabled = true 但未指定目錄,伺服器會記錄警告並維持關閉,而不會自行猜測路徑。

伺服器會產生的檔案

每次啟動時,伺服器會在目錄不存在時建立它,並寫入 buttress-functions.d.ts,其中包含 ButtressFunctionMetaButtressFunctionContextButtressAuth* 等型別。這個檔案每次啟動都會重新產生,因此永遠與執行中的伺服器一致。當本頁與你的伺服器不一致時,以該檔案為準。 若目錄中尚無任何函式,伺服器還會一併產生 tsconfig.json 與附註解的 _example.ts。這兩個檔案一旦你編輯過就不會再被覆寫。

撰寫函式

一個檔案就是一個函式,而且檔名就是工具名稱video-duration.ts 會成為 video-duration 工具。
規則:
  • 預設匯出必須是函式,並接收 (input, context)
  • meta 為選填。meta.parameters 是純 JSON Schema,會原封不動交給 MCP 用戶端,因此你只需描述輸入一次,所有介面就會一致。若省略,工具會宣告一個空的 object schema。
  • 回傳可序列化為 JSON 的值。若要回傳檔案,請寫入 context.tempDir 並回傳 context.fileUrl(path),參見傳入與傳出檔案
  • 函式名稱必須以字母或數字開頭,其餘可包含字母、數字、-_
探索時會略過以 _ 開頭的檔案、隱藏檔、*.d.ts*.test.**.spec.* 以及子目錄 — 子目錄是給你匯入的輔助模組使用。_auth.ts 是底線規則的唯一例外:它是有效的,而且會改變每個端點的驗證方式,參見自訂驗證。若同名的 .ts.js 並存,以 .ts 為準。 mcpfilesupload 是保留名稱,因為 /functions/mcp/functions/files/*/functions/upload 都是路由。使用這些名稱的檔案會被略過。

Context

第二個參數提供函式可以取用的一切:

匯入

函式可以匯入 Node 內建模組、函式目錄內的同層檔案,以及兩個列入允許清單的套件:sqlite3sqlite-vec。其他套件一律拒絕 — 內建的輔助函式庫請改用 context.libs
sqlite-vec 提供 macOS 與 Linux 的 x64、arm64 擴充功能,以及 Windows x64。它沒有 Windows arm64 版本,因此該平台的獨立版建置不提供這兩個 SQLite 匯入;本頁其餘功能在該平台仍可正常使用。

檢索

只要 tokenizeembedding 與這兩個 SQLite 匯入,就能在單一函式內完成檢索:依 token 邊界切塊、為每個片段產生嵌入向量、把向量存進 sqlite-vec 虛擬資料表,再把最相近的結果交給 completion 嵌入需要以嵌入模式載入的模型,chat 模型並不是。請為嵌入模型建立獨立的 [[generators]] 區塊,並讓 chat 模型維持在第一個 LLM:
接著在每次 embeddingtokenizedetokenize 呼叫時把該 repo_id 當作 model 傳入,並在 completion 省略 model,讓答案由第一個 LLM 產生。完整的鍵列表請見設定 索引本身就是一般的 SQLite:開啟 sqlite3 資料庫,用 getLoadablePath() 載入 sqlite-vec 擴充功能,再把每個向量以 float32 BLOB 寫入。:memory: 會建立拋棄式索引;改用檔案路徑(絕對路徑,或相對於函式目錄的路徑)則可在多次呼叫之間保留索引。

迭代開發

編輯會在下一次呼叫時生效。每次呼叫前,伺服器會檢查該函式模組圖中的每個檔案,只要有變動就重新載入,因此你不需要重新啟動伺服器。載入失敗的檔案會被記錄並略過,其他函式照常運作 — 如果某個函式突然不見了,請檢查伺服器日誌。 若想更快得到回饋,可設定 hot_reload = true。伺服器會額外監看目錄並在存檔時重新載入,因此檔案一存檔就會立刻記錄錯誤,函式數量也不必等到有人呼叫才更新。這純粹是加分項:每次呼叫前的檢查依然存在作為後盾;在不支援遞迴目錄監看的平台上,伺服器會記錄警告並退回原本的行為。 模組層級的狀態(處理常式外的 let)會在多次呼叫之間保留,並在你編輯檔案時重設。

呼叫函式

錯誤會以 { "error": { "code", "message" } } 回傳: 驗證遭拒時會回傳專屬代碼,參見安全性

以 GET 呼叫

GET /functions/<name> 執行同一個呼叫,而且完全不需要 body — 查詢字串就是輸入。瀏覽器網址列、webhook、EventSource 或單純的 curl 都能輕鬆產生這種請求:
查詢字串的值一律是字串,因此函式宣告的 meta.parameters 同時也是型別轉換表。宣告為 number / integerbooleanarrayobject 的屬性會被轉換,未宣告的則維持字串: 轉換永遠不會拒絕請求。不符合宣告型別的值會原封不動傳入,而不會變成 NaN,因此處理常式看到的是呼叫端實際送出的內容,驗證的責任仍在處理常式。 若不論 schema 為何都想要精確的型別,請把整個物件以 JSON 放進 input。一般參數會疊加在它之上,行為與 multipart 呼叫完全相同:
streamtokenaccess_token 用於控制請求本身,永遠不會傳到處理常式 — 若函式真的需要名為 token 的輸入,請改用 input 傳入。 串流的用法相同:加上 ?stream=1,或送出 Accept: text/event-stream(這是 EventSource 唯一能表達的方式)。由於 EventSource 同樣無法設定標頭,在已繫結的伺服器上請以 ?token=… 傳遞 token。
每個函式都支援 GET,且回應皆帶有 no-store。HTTP 預期 GET 可以安全地重複執行,而只有你知道自己的函式是否如此 — 請依函式實際的行為選擇方法。

傳入與傳出檔案

二進位結果以 URL 傳遞,而不是直接回傳內容。請寫入 context.tempDir、回傳 context.fileUrl(path),呼叫端就能用手上既有的 Authorization 標頭抓取 <base><url>
下載與呼叫共用同一道驗證關卡,且只會解析到函式暫存根目錄之內 — 路徑穿越、目錄與無法解碼的路徑,都與檔案不存在無法區分 — 並會保留到約 24 小時後的暫存清理為止。 二進位輸入則走相反方向,而且只需一次請求。以 multipart/form-data 呼叫函式,每個檔案欄位都會暫存到該次呼叫的暫存目錄,並將伺服器本機路徑以欄位名稱注入輸入中:
函式會收到 input.file 作為路徑,可直接交給 ffmpeg,因此整段流程都能遠端完成,不需要存取檔案系統。若要傳入具型別的值,加上 -F input='{"model":"…"}';其他一般欄位會以字串傳入,檔案路徑在名稱衝突時優先,重複的檔案欄位會變成路徑陣列。?stream=1 也可以搭配 multipart 使用。 若想暫存一次檔案並在多次呼叫中重複使用,請單獨上傳,再把回傳的 path 放進 JSON 呼叫:
兩種路徑都會將用戶端檔名淨化為純檔名,暫存檔案與函式輸出共用同一道驗證關卡與 24 小時清理機制,而請求大小則受 [server] max_body_size(預設 50 MB)限制 — 處理大型媒體時請調高。

連線 agent

BRICKS CLIbricks buttress mcp-config 會產生伺服器 MCP 端點的 .mcp.json 項目。它會在區域網路上探索伺服器、簽發 workspace access token,並在不影響你其他 MCP 伺服器的前提下合併該項目:
--url 指定特定主機,未啟用驗證的伺服器則可省略 token:
寫入的項目內嵌了長效的 workspace access token。請將 .mcp.json 視為機密,不要納入版本控制。
探索流程不會為未回報你的 workspace 的主機簽發 token:未繫結或屬於其他 workspace 的伺服器都算不符,此時指令會直接拒絕,而不是把憑證交給任何回應探測的機器。若你確實要指定該伺服器,請改用 --url。完整選項參見 bricks buttress mcp-config

安全性

函式會在主機上執行程式碼並產生子處理程序,因此這個介面採預設拒絕,不像推論端點那樣沿用「未繫結即開放」的原則。
  • 未繫結的伺服器 — 每次呼叫都會以 403 FUNCTIONS_UNAUTHENTICATED_DISABLED 拒絕。
  • 已繫結的伺服器 — 與其他資料路徑一樣需要 workspace access token,參見 Workspace 繫結
  • 瀏覽器請求 — 只要被瀏覽器標記為跨站,就會以 403 FUNCTIONS_ORIGIN_BLOCKED 拒絕,除非其來源已列在 [functions] cors_allowed_origins 中。agent、MCP 用戶端與 curl 不受影響。
下載與上傳和呼叫共用同一道關卡。 瀏覽器檢查會讀取兩個標頭,因為單靠 Origin 無法涵蓋 GET 呼叫。CORS 請求會帶有 Origin,並比對允許清單。而 no-CORS 的子資源載入(<img src><script src>、預先擷取)完全不會送出 Origin,否則就會被當成非瀏覽器的呼叫端;瀏覽器會為這類請求標記 Sec-Fetch-Site,這是指令碼無法設定的禁止標頭,其中 cross-sitesame-site 正好涵蓋 Origin 遺漏的部分。沒有這個標頭仍然代表「不是瀏覽器」。
列出來源只對本身帶有來源的請求有用。no-CORS 載入沒有來源可比對,因此只有 cors_allowed_origins = "*" 能放行這類請求。
若要在未繫結 workspace 的伺服器上執行函式,必須明確選擇加入:
allow_unauthenticated = true 會讓任何能連到該連接埠的人執行所有函式。請只在受信任的網路中使用。
函式檔案是受信任的輸入,就跟設定檔本身一樣。它們在乾淨的全域環境中執行(沒有現成的 processrequire),但這是為了清楚,而非隔離:拿到 spawn 的函式能做的事,與伺服器處理程序完全相同。切勿將你未撰寫或未審閱的程式碼放進函式目錄。 每次呼叫都帶有期限,來自 meta.timeout[functions] default_timeout。期限到達時(或呼叫端中斷連線時),context.signal 會觸發,該次呼叫產生的所有處理程序都會被終止。同步阻塞事件迴圈的程式碼無法被中斷,因此請讓處理常式維持非同步。

自訂驗證

在函式目錄放入 _auth.ts(或 .js),即可在每個 /functions 端點前加上你自己的邏輯。它的形式與函式檔案相同,而 meta.mode 決定它與上述 workspace 關卡的組合方式:
  • both(預設)— workspace 驗證先執行且維持原樣,你的處理常式接在後面作為額外關卡。它只能收緊存取:逐函式允許清單、主體檢查、稽核記錄。
  • override — 由你的處理常式獨自決定,allow_unauthenticated 不再有作用。呼叫端提供的 workspace token 仍會被驗證並放入 request.workspaceAuth,因此你可以同時支援 workspace token 與其他憑證。
處理常式會收到 { method, path, name?, headers, query, token, workspaceAuth } — 只有 GET / POST /functions/<name> 才會帶 name,因為 MCP 的工具名稱位於關卡不會解析的 JSON-RPC body 中 — 以及精簡的 context:logfetchenvconfigdirlibs。沒有 spawn,也沒有 buttress 只有回傳 true{ ok: true } 才會放行。其他任何回傳值都會以 403 FUNCTIONS_AUTH_REJECTED 拒絕,或使用你回傳的 statuserror。驗證永遠不會在失敗時放行:只要 _auth 檔案存在卻無法載入,每次呼叫都會以 500 FUNCTIONS_AUTH_UNAVAILABLE 拒絕;處理常式拋出錯誤則以 500 FUNCTIONS_AUTH_ERROR 拒絕。瀏覽器跨站阻擋一律先執行,因此寬鬆的 _auth 也無法重新開啟它。 _auth.ts 與函式檔案一樣採延遲重新載入,刪除它就會回到單純的 workspace 驗證。
bricks buttress mcp-config 簽發的是 workspace token。若你的 override 模式 _auth 忽略 workspaceAuth,這些 token 就會失效 — 如果 agent 仍以此方式連線,請保留上面範例中處理 workspace token 的分支。

檢視執行狀況

你不需要伺服器日誌的存取權也能了解函式的行為。GET /buttress/status 會回傳 functions 區段,內含啟動以來的計數,以及呼叫(依 HTTP、SSE 或 MCP 分類,含耗時與失敗原因)、上傳、下載與驗證決策的近期記錄。同一份資料也會在伺服器的 /status 儀表板上呈現為 Local Functions 卡片。 記錄的只有中繼資料 — 名稱、路徑、大小、結果代碼、主體 id,絕不包含 token 或金鑰。 探索只公告存在與否,不公告內容:serverInfo.functions{ enabled, count }。工具清單本身不會被公告,因為整份 serverInfo 必須放得進一個 UDP 封包。參見區域網路自動探索

範例

伺服器套件在 config/function-samples/ 中提供可直接複製的範例。把其中一個複製到你的函式目錄再呼叫即可,不需要重新啟動。 _auth.ts 不是函式 — 複製它會改變每個 /functions 端點驗證呼叫端的方式。

後續步驟

設定

完整 TOML 參考,包含函式會呼叫的 generator。

Workspace 繫結

繫結伺服器,讓函式呼叫需要 workspace token。