Skip to main content
ローカル関数は、BRICKS Buttress サーバーの指定ディレクトリに置く .ts / .js ファイルです。1 つのファイルが MCP ツールであり、同時に HTTP エンドポイントにもなります。これにより、エージェント(あるいは任意の HTTP クライアント)がサーバー上で処理を実行できます — ffmpeg の呼び出し、そのサーバー自身の LLM / 音声認識 / 音声合成 generator の利用、社内サービスへの接続など。書くのはファイル 1 つだけで、別途サービスを立てる必要はありません。
ローカル関数は実験的機能です。エンドポイント、関数ファイルの契約、context API、カスタム _auth[functions] 設定キーは、非推奨期間を挟まずにリリース間で変更される可能性があります。サーバーは起動時にこの注意を表示します。これを前提に開発する場合は bricks-buttress のバージョンを固定し、アップグレード後は本ページを読み直してください。
ローカル関数は Buttress の他の機能とは性質が異なります。他の部分では、BRICKS Foundation デバイスが本来自分で実行する generator を Buttress がオフロードします。ローカル関数はサーバー上で動き、サーバーの運用者が書き、アプリのランタイムではなくエージェントや HTTP クライアントから呼び出されます。

有効化

ローカル関数はデフォルトで無効です。サーバーの TOML に [functions] テーブルを追加して有効にします。
最初の 3 つのキーには環境変数の同等物があります: ENABLE_FUNCTIONS_ENDPOINT=1BUTTRESS_FUNCTIONS_DIR=<dir>BUTTRESS_FUNCTIONS_HOT_RELOAD=1allow_unauthenticated に対応するのは BUTTRESS_FUNCTIONS_ALLOW_UNAUTHENTICATED=1 です。
enabled = true でもディレクトリが未設定の場合、サーバーはパスを推測せず、警告をログに出してローカル関数を無効のままにします。

サーバーが生成するファイル

サーバーは起動のたびに、ディレクトリがなければ作成し、buttress-functions.d.ts を書き出します。ここには ButtressFunctionMetaButtressFunctionContextButtressAuth* などのアンビエント型が入っています。このファイルは毎回再生成されるため、常に動作中のサーバーと一致します。本ページと手元のサーバーが食い違う場合は、このファイルを正としてください。 ディレクトリにまだ関数が 1 つもない場合は、tsconfig.json とコメント付きの _example.ts も生成されます。どちらも一度編集すれば上書きされることはありません。

関数を書く

1 ファイルが 1 関数で、ファイル名がツール名になります — video-duration.tsvideo-duration ツールになります。
ルール:
  • デフォルトエクスポートは必ず関数で、(input, context) を受け取ります。
  • meta は任意です。meta.parameters は素の JSON Schema で、MCP クライアントにそのまま渡されます。入力の説明を 1 度書けば、すべての面で同じ内容になります。省略した場合、ツールは空の object スキーマを公開します。
  • JSON にシリアライズできる値を返してください。ファイルを返す場合は context.tempDir に書き出し、context.fileUrl(path) を返します — ファイルの入出力を参照。
  • 関数名は英数字で始まり、以降は英数字・-_ を使えます。
検出時には、_ で始まるファイル、ドットファイル、*.d.ts*.test.**.spec.*、およびサブディレクトリがスキップされます — サブディレクトリは import するヘルパーモジュール用です。_auth.ts はアンダースコア規則の唯一の例外で、有効なファイルとして扱われ、すべてのエンドポイントの認証方法を変更します。カスタム認証を参照してください。同名の .ts.js がある場合は .ts が優先されます。 mcpfilesupload は予約名です。/functions/mcp/functions/files/*/functions/upload がルートだからで、この名前のファイルはスキップされます。

Context

第 2 引数には、関数から使えるものがすべて入っています。

import

関数から import できるのは、Node の組み込みモジュール、関数ディレクトリ内の同階層ファイル、そして許可リストに載っている 2 つのパッケージ sqlite3sqlite-vec です。それ以外のパッケージは拒否されます — 同梱ヘルパーは context.libs から使ってください。
sqlite-vec は macOS と Linux の x64 / arm64、および Windows x64 向けの拡張を配布しています。Windows arm64 向けは存在しないため、そのプラットフォームのスタンドアロンビルドではどちらの SQLite import も利用できません。それ以外の機能はこのページのとおり動作します。

検索

tokenizeembedding、そして 2 つの SQLite import があれば、検索を 1 つの関数の中で完結できます。token 境界で分割し、各チャンクを埋め込み、ベクトルを sqlite-vec の仮想テーブルに保存して、最も近い結果を completion に渡します。 埋め込みには埋め込みモードで読み込んだモデルが必要で、chat モデルはそれに当たりません。埋め込みモデルには専用の [[generators]] ブロックを用意し、chat モデルは先頭の LLM のままにしてください。
embeddingtokenizedetokenize の各呼び出しではこの repo_idmodel として渡し、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 にされるのではなくそのまま渡されるので、ハンドラーは呼び出し元が実際に送った内容を受け取り、検証の責任は引き続きハンドラーにあります。 スキーマに関係なく正確な型を渡したいときは、オブジェクト全体を 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 時間後の掃除まで残ります。 バイナリの入力は逆方向で、しかも 1 リクエストで済みます。関数に multipart/form-data を POST すると、各ファイルフィールドがその呼び出しの作業ディレクトリに退避され、サーバー上のパスがフィールド名で入力に注入されます。
関数は input.file をパスとして受け取り、そのまま ffmpeg に渡せます。つまりファイルシステムへのアクセスなしに、この一連の流れをリモートから実行できます。型付きの値を渡すには -F input='{"model":"…"}' を追加します。それ以外の通常フィールドは文字列として届き、名前が衝突した場合はファイルパスが優先され、同じファイルフィールドを繰り返すとパスの配列になります。?stream=1 も multipart と併用できます。 ファイルを一度だけ退避して複数の呼び出しで使い回すには、先にアップロードして、返ってきた path を JSON の呼び出しに渡します。
どちらの経路でもクライアント側のファイル名は素のファイル名に正規化され、退避されたファイルは関数の出力と同じ認証ガードと 24 時間の掃除を共有します。リクエストサイズは [server] max_body_size(デフォルト 50 MB)で制限されるため、大きなメディアを扱うときは引き上げてください。

エージェントを接続する

BRICKS CLIbricks buttress mcp-config は、サーバーの MCP エンドポイント用の .mcp.json エントリを書き出します。LAN 上のサーバーを検出し、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 バインドを参照してください。
  • ブラウザーからのリクエスト — ブラウザーがクロスサイトと印を付けたリクエストは、そのオリジンが [functions] cors_allowed_origins に列挙されていない限り 403 FUNCTIONS_ORIGIN_BLOCKED で拒否されます。エージェント、MCP クライアント、curl は影響を受けません。
ダウンロードとアップロードも呼び出しと同じガードの後ろにあります。 ブラウザー判定は 2 つのヘッダーを見ます。Origin だけでは GET 呼び出しをカバーできないからです。CORS リクエストは Origin を持つので許可リストと照合されます。一方、no-CORS のサブリソース読み込み(<img src><script src>、プリフェッチ)は Origin をまったく送らないため、そのままではブラウザー以外の呼び出し元に見えてしまいます。これを塞ぐのが Sec-Fetch-Site です。スクリプトからは設定できない禁止ヘッダーで、cross-sitesame-siteOrigin の取りこぼす読み込みをちょうど言い当てます。このヘッダーがないことは、依然として「ブラウザーではない」を意味します。
オリジンを列挙しても効くのは、オリジンを持つリクエストだけです。no-CORS の読み込みには照合できるオリジンがないため、通せるのは cors_allowed_origins = "*" だけです。
workspace にバインドしていないサーバーで関数を動かすには、明示的にオプトインします。
allow_unauthenticated = true にすると、そのポートに到達できる誰もがすべての関数を実行できます。信頼できるネットワークでのみ使用してください。
関数ファイルは設定ファイルと同じく信頼された入力です。アンビエントな processrequire のないクリーンなグローバルで実行されますが、それは分かりやすさのためであって隔離のためではありません。spawn を渡された関数は、サーバープロセスにできることは何でもできます。自分で書いた(あるいはレビューした)コード以外を関数ディレクトリに置かないでください。 すべての呼び出しには meta.timeout、なければ [functions] default_timeout による期限があります。期限が切れたとき、または呼び出し元が切断したときに context.signal が発火し、その呼び出しが起動したプロセスはすべて終了させられます。イベントループを同期的にブロックするコードは中断できないため、ハンドラーは非同期のままにしてください。

カスタム認証

関数ディレクトリに _auth.ts(または .js)を置くと、すべての /functions エンドポイントの前に独自ロジックを挟めます。形は関数ファイルと同じで、上記の workspace ゲートとの組み合わせ方は meta.mode で決まります。
  • both(デフォルト)— workspace 認証がそのまま先に走り、そのあとに追加のゲートとしてハンドラーが実行されます。アクセスを狭めることしかできません(関数ごとの許可リスト、サブジェクトの検査、監査ログなど)。
  • override — ハンドラーだけが判断し、allow_unauthenticated は無関係になります。提示された workspace token は引き続き検証されて request.workspaceAuth に入るため、workspace token を受け付けたまま別の認証情報も併用できます。
ハンドラーは { method, path, name?, headers, query, token, workspaceAuth } を受け取ります(name が入るのは GET / POST /functions/<name> のときだけです。MCP のツール名は、このガードが解析しない JSON-RPC body の中にあります)。context は logfetchenvconfigdirlibs に絞られ、spawnbuttress もありません。 許可されるのは 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 です。workspaceAuth を無視する override モードの _auth を置くと、それらの token は使えなくなります — エージェントが引き続きその方法で接続するなら、上のサンプルにある workspace token の分岐を残してください。

実行状況を確認する

関数の挙動を知るのにサーバーログへのアクセスは必要ありません。GET /buttress/status には functions セクションがあり、起動以降のカウンターと、呼び出し(HTTP / SSE / MCP のどれか、所要時間と失敗理由付き)、アップロード、ダウンロード、認証判定の直近の履歴が含まれます。同じデータはサーバーの /status ダッシュボードにも Local Functions カードとして表示されます。 記録されるのはメタデータだけです — 名前、パス、サイズ、結果コード、サブジェクト ID。token や鍵が記録されることはありません。 検出が広告するのは存在の有無だけで、中身ではありません。serverInfo.functions{ enabled, count } です。serverInfo 全体が UDP データグラムに収まる必要があるため、ツール一覧そのものが広告されることはありません。LAN 自動検出を参照してください。

サンプル

サーバーパッケージには、そのままコピーして使えるサンプルが config/function-samples/ に同梱されています。関数ディレクトリにコピーして呼び出すだけで、再起動は不要です。 _auth.ts は関数ではありません — コピーすると、すべての /functions エンドポイントの認証方法が変わります。

次のステップ

設定

関数が呼び出す generator を含む TOML の完全リファレンス。

Workspace バインド

サーバーをバインドして、関数呼び出しに workspace token を必須にする。