t28.dev

Mastra アプリを Cloudflare Workers にデプロイする

2025/5/9
Tech

Fairy (AI エージェント) を作るメモまとめ > Mastra アプリを Cloudflare Workers にデプロイする


npx create-mastra@latest で local で動く Mastra アプリは秒で作れた ので、これを Cloudflare Workers にデプロイしてインターネットからアクセス出来るようにする。

// こんな感じの mastra を Cloudflare Workers にデプロイしたいってわけ
export const mastra = new Mastra({
  workflows: { weatherWorkflow },
  agents: { fairy, weatherAgent },
  storage: new LibSQLStore({
    // stores telemetry, evals, ... into memory storage, if it needs to persist, change to file:../mastra.db
    url: ":memory:",
  }),
  logger: createLogger({
    name: "Mastra",
    level: "info",
  }),
});

具体的な作業内容は https://github.com/TatsuyaYamamoto/sicaco-quarter-third-street/pull/1 で見られる。

Mastra のバージョン

Mastra のバージョンはまだ 0.x なので、Breaking change が激しい…かもしれない。

例えば、2025/3/21 の記事では mastra deploy が紹介されているが、 v0.4.9 で deprecate されている

mastra build

https://mastra.ai/ja/reference/cli/build

mastra build を実行すると、Mastra の機能を Web API のエンドポイント経由で公開するための、HTTP Server の実装が出力される。 この HTTP Server に Hono が使われている

$ tree -L 1 .mastra/output
.mastra/output
├── index.mjs           # 👈️ mastra を呼び出す WebAPI を定義した Hono 製の HTTP Server がある
├── index2.mjs
├── instrumentation.mjs
├── mastra.mjs          # 👈️ この辺に `const mastra = new Mastra({})` がある
├── node_modules
├── package.json
├── pnpm-lock.yaml
├── telemetry-config.mjs
├── tools
└── tools.mjs

これを Cloudflare Workers で動かしたい。

Deployer

https://mastra.ai/ja/docs/deployment/deployment

Mastra には deployer という仕組みがあって、デプロイする環境に合わせて「いい感じのコード」を出力してくれる仕組みがある。 Cloudflare なら @mastra/deployer-cloudflare を使う。 使い方は Mastra で deployer を指定して mastra build を実行するだけ。

import { CloudflareDeployer } from "@mastra/deployer-cloudflare";

export const mastra = new Mastra({
  // ...
  deployer: new CloudflareDeployer({
    scope: "***",
    projectName: "sicaco-3rd",
    auth: {
      apiToken: "***",
    },
  }),
});

CloudflareDeployer の引数に従った wrangler.json.mastra/output/ に出力される。 ただし困ったことに CloudflareDeployer のオプションwrangler.json の仕様(お作法?)に従っておらず1、しかも追加の設定をするためにはビルド成果物を改造するスクリプトを自分で書く必要がある…。

// wrangler.json
{
  "compatibility_date": "2025-04-01",
  "compatibility_flags": [
    "nodejs_compat",
    "nodejs_compat_populate_process_env"
  ],
  "name": "sicaco-3rd",
  "main": "./index.mjs",
  "vars": {}
}

.mastra/output/index.mjs には fetch() ハンドラー が入る。 これによって Worker へのHTTPリクエストが Hono -> Mastra へと渡される。

// index.mjs
var _virtual__entry = {
  fetch: async (request, env, context) => {
    const app = await createHonoServer(mastra);
    return app.fetch(request, env, context);
  },
};

いい感じと言ったな?それは嘘だ。

嘘です。CloudflareDeployer 使えばすぐに Workers にデプロイ出来るかというと、出来ない。ローカル実行 (wrangler dev) も出来ない。 [email protected] の時点では 👇️ のようなスクリプトでビルド成果物を改造 (?!) する必要がある。というか deployer-cloudflare を作っている人、 Cloudflare 使ってないでしょ。

https://github.com/TatsuyaYamamoto/sicaco-quarter-third-street/blob/38b89fa6b0d3f37e50d08ba1f2a0fea280b8402e/scripts/postbuild.js

wrangler でデプロイする

Mastra のドキュメント に従って、以下の流れで Mastra アプリを Workers にデプロイする。Mastra の Deployer を使っているのに、デプロイは wrangler を使うのモヤるな。

  • CLIをインストール: npm install -g wrangler
  • 出力ディレクトリに移動: cd .mastra/output
  • Cloudflareアカウントにログイン: wrangler login
  • プレビュー環境にデプロイ: wrangler deploy
  • 本番環境へのデプロイ: wrangler deploy --env production 2

Middleware

Workers にデプロイ出来た 3 はいいけどこのままだと Mastra アプリがインターネットに丸出しになってしまので、認証機能を簡単に付けたい。 Cloudflare らしく作るなら Cloudflare Access を使うのでしょうが、Mastra の middleware を使って簡易的に実装する。

https://mastra.ai/ja/docs/deployment/middleware

Mastra は内部で Hono を使って HTTP サーバーを実行しているので、 Hono のドキュメントに従って middleware を作る。

/**
 * Check authorization header, when `/api/*` is called
 */
export const authMiddleware: Middleware = {
  path: "/api/*",
  handler: async (c, next): Promise<Response | void> => {
    const authorizationHeader = c.req.header("Authorization");
    const [prefix, token] = authorizationHeader?.split(" ") ?? [];

    // 👇️ トークンがあれば OK
    if (prefix === "Bearer" && token && token === TOKEN) {
      await next();
      return;
    }

    // 👇️ トークンがなければ、401
    return c.json({ message: "Unauthorized" }, { status: 401 });
  },
};
export const mastra = new Mastra({
  // ...
  server: {
    middleware: [authMiddleware],
  },
});

その他

  1. deployer "***" を指定しているのはブログ用に情報をぼかしているのではなく、その設定で良いから。これらの値が参照されるのは CloudflareDeployer#deploy() だけれど Workers へデプロイするまでに使わることがない…。
  2. この記事時点では LibSQLStore をコメントアウトしている。npx create-mastra@latest では ":memory:"を指定しいるが、これは Workers 環境ではURL_SCHEME_NOT_SUPPORTED エラーになる。 Cloudflare Workers KV を使うことになりそうだけれど、あとあと!

Footnotes

  1. 例えば dotenv で読み込んだ環境変数は secret としてではなく vars として扱ったりenv を指定しても、Environments ではなく vars として扱う。

  2. --env を使ってプレビュー・本番環境を切り替えるかどうかは Worker をどのように管理するかの問題なので、 Mastra アプリとしては関係がない。

  3. wrangler deploy だけじゃなくて、Worker の設定 (Worker 自体を作ったり環境変数設定したり) も必要だけれど、省略でいいよね。