Mastra でシンプルな自作サーバー ＋ シンプルな自作クライアントなどでサーバー経由でエージェントを使う（OpenAI との組み合わせ）

## はじめに

前から気になりつつも試したのはつい最近になってから、という感じになった「Mastra」について、その[ドキュメント](https://mastra.ai/ja/docs)を見ていて気になった、以下の Mastraサーバーの話です。

●Mastraサーバーの作成
 https://mastra.ai/ja/docs/deployment/server

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/66f22ec9-d6e0-4c00-8167-f7a7af0a9b72.png)


以下のお試しをした際に、Mastra関連の情報を探していた中でも Mastraサーバーの話を見かけていたので、あらためて上記を見かけて気になりました。

●Mastra でシンプルな MCPクライアント・MCPホストの機能を作って Node.js で実行（自作MCPサーバーと組み合わせる） - Qiita
 https://qiita.com/youtoy/items/062165c2918cfdbc5590



## サクッと試す

それではシンプルな内容・手順で試してみます。

### 「create-mastra」を使用した新規プロジェクト

まずは[公式おすすめの「create-mastra」を使用した新規プロジェクト作成](https://mastra.ai/ja/docs/getting-started/installation#%E6%96%B0%E3%81%97%E3%81%84%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)を少し試しました。

具体的には、以下のコマンドを使ったものです。

```javascript
npx create-mastra
```

#### インストール

コマンド実行後、以下のようにインストールが始まりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/4416f1d5-e378-4cce-b49f-f7373faeb625.png)


その後、以下のように進んでいきました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/6d853845-9ba3-486a-bcd6-1f89665b4d5c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/99eda3a7-8bdc-4a53-9187-a57e5ac7a4fc.png)

#### サーバーの起動

そして、上記のコマンドでサーバーを起動しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/a5873bbd-9d50-4780-a4ff-8c97e942ccde.png)


#### ブラウザでローカルサーバーにアクセスする

ブラウザで http://localhost:4111/agents にアクセスしたところ、以下のページが表示されたのが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/d2c9f3b1-119a-41aa-83f0-3e2cef9587f6.png)


#### 生成されていたコード

なお、 `./my-mastra-app/src/mastra/` に作られたコードは以下がありました。


```typescript:index.ts
import { Mastra } from '@mastra/core/mastra';
import { createLogger } from '@mastra/core/logger';
import { LibSQLStore } from '@mastra/libsql';

import { weatherAgent } from './agents';

export const mastra = new Mastra({
  agents: { 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',
  }),
});

```


```typescript:agents/index.ts
import { openai } from '@ai-sdk/openai';
import { Agent } from '@mastra/core/agent';
import { Memory } from '@mastra/memory';
import { LibSQLStore } from '@mastra/libsql';

export const weatherAgent = new Agent({
  name: 'Weather Agent',
  instructions: `
      You are a helpful weather assistant that provides accurate weather information.

      Your primary function is to help users get weather details for specific locations. When responding:
      - Always ask for a location if none is provided
      - If the location name isn’t in English, please translate it
      - If giving a location with multiple parts (e.g. "New York, NY"), use the most relevant part (e.g. "New York")
      - Include relevant details like humidity, wind conditions, and precipitation
      - Keep responses concise but informative

`,
  model: openai('gpt-4o'),

  memory: new Memory({
    storage: new LibSQLStore({
      url: 'file:../mastra.db', // path is relative to the .mastra/output directory
    }),
    options: {
      lastMessages: 10,
      semanticRecall: false,
      threads: {
        generateTitle: false,
      },
    },
  }),
});
```


### 自前でセットアップして進めてみる

この後、HTTPリクエストを使ってやりとりできるシンプルなサーバーを、自前でセットアップしてみるというのも試しました。


#### サーバーについての公式ドキュメント内の記載

サーバーの作成について、公式ドキュメントの中に以下のシンプルな内容が示されていました。

```javascript
import { Mastra } from "@mastra/core";
 
export const mastra = new Mastra({
  server: {
    port: 3000, // デフォルトは4111
    timeout: 10000, // デフォルトは30000（30秒）
  },
});
```

`@mastra/core` をインストールして、上記に少し機能を追加したものを用意すれば、シンプルなサーバーを立ち上げることができそうです。


### サーバーの準備

#### 下準備

[前回の記事](https://qiita.com/youtoy/items/062165c2918cfdbc5590)と同様に、OpenAI の API を組み合わせた構成にしてみます。

そのために、以下のコマンドで 2つのパッケージをインストールしました。

```zsh
npm i @mastra/core @ai-sdk/openai
```

また、環境変数 OPENAI_API_KEY に OpenAI の APIキーをセットしました。


#### 作成したコード

自前で用意したコードは以下の通りで、これを `src/mastra` というフォルダに index.js というファイル名で置きました。


```javascript:index.js
import { Mastra } from "@mastra/core";
import { Agent } from "@mastra/core/agent";
import { openai } from "@ai-sdk/openai";

export const echoAgent = new Agent({
  name: "echoAgent",
  instructions: "ユーザーの入力をそのまま返すエージェントです。",
  model: openai("gpt-4o"),
  tools: {},
});

export const mastra = new Mastra({
  agents: { echoAgent },
  server: {
    port: 3000, // デフォルトは4111
    timeout: 10000, // デフォルトは30000（30秒）
  },
});
```

#### サーバーを起動

そして、以下のコマンドでサーバーを起動します。

```zsh
npx mastra dev
```

ちなみに、上記のサーバーのコードを `src/mastra` というフォルダに置いてない場合は、以下のメッセージが出ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/98793c10-b9d2-4de7-a88a-e3899a876fcd.png)


また以下が、サーバーを起動できた時の出力です（少し、追加で対応したほうが良さそうな内容も表示されていますが...）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/f87eb36f-d711-4937-b300-081d674c86ae.png)


#### サーバーにブラウザでアクセスする

それではサーバーにアクセスしてみます。 http://localhost:3000/agents にアクセスすると、以下のページが表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/e4c70d28-1181-4fab-bd23-482795e665f7.png)


さらに http://localhost:3000/agents/echoAgent/chat にアクセスしてみました。この画面では、以下のようにチャットができる UI が表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/c21df76d-53c0-49a7-94ec-3edaa1fd900d.png)


#### HTTPリクエスト（POSTリクエスト）でのやりとり

それでは、起動したサーバーと HTTPリクエスト（POSTリクエスト）でのやりとりしてみます。

まずは以下の curlコマンドを実行してみます。

```zsh
curl -X POST http://localhost:3000/api/agents/echoAgent/generate \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      { "role": "user", "content": "こんにちは！" }
    ]
  }'
```

その結果、返答とその他の色々な情報が混じったレスポンスが返ってきました。


次に、Node.js を使ってシンプルに返答のみを表示させるようにしてみます。具体的には以下のコードを実装して、nodeコマンドで実行しました。

```javascript
async function callEchoAgent() {
  try {
    const res = await fetch(
      "http://localhost:3000/api/agents/echoAgent/generate",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          messages: [{ role: "user", content: "あなたは誰？" }],
        }),
      }
    );
    if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
    const data = await res.json();
    console.log(data.text);
  } catch (err) {
    console.error(err);
  }
}

callEchoAgent();
```

その結果、以下のように返答のみを表示させることができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/eee23e79-b2ab-46ea-881d-742b2e0c599b.png)


#### HTTPリクエスト（POSTリクエスト）でのやりとり2

さらに、以下を使って実装したクライアントでのやりとりも、少し試してみます。

●@mastra/client-js - npm
　https://www.npmjs.com/package/@mastra/client-js


公式ドキュメントでは、以下に説明などが書かれているものです。

●MastraClient
 https://mastra.ai/ja/docs/deployment/client

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/03b644ad-e8cf-4c9e-afb5-2f75ee7fce3a.png)


これを使うために、以下でパッケージをインストールします。

```zsh
npm i @mastra/client-js
```

クライアントの実装は以下にしました。エージェント名は「echoAgent」を指定しています。

```javascript
import { MastraClient } from "@mastra/client-js";

const client = new MastraClient({
  baseUrl: "http://localhost:3000",
});

async function main() {
  const agent = client.getAgent("echoAgent");

  const response = await agent.generate({
    messages: [{ role: "user", content: "あなたは誰？" }],
  });

  console.log("Agent の応答:", response.text);
}

main().catch(console.error);
```


上記を実行したところ、以下のレスポンスを得られました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/2d619b16-d96e-42f2-85de-90e7eea22cc7.png)


#### mastra build を試す

それとサーバー側に関して、mastra build も試してみました。

以下のコマンドでパッケージのインストールとビルドを行います。

```zsh
npm i mastra
npx mastra build
```

上記の実行後、以下のメッセージなどが表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/081a4f4e-904a-4f52-b772-17c4063273c5.png)

ここに情報をもとに、以下のコマンドを実行してみます。

```zsh
node .mastra/output/index.mjs
```

そうすると以下が表示され、先ほどの HTTPリクエストベースでのやりとりを行える状態になっていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/3e5b0a90-8217-428a-a57c-2d348403b75e.png)



## おわりに

今回、Mastra を使った簡単なお試しをいくつかやってみました。Mastra でできることが色々ありそうなので、別途、他の機能も試していければと思います。


### 【追記】

[実験的機能の AgentNetwork](https://mastra.ai/ja/reference/networks/agent-network) を使った複数エージェントの利用と、MCPサーバーの組み合わせも試しました。

●Mastra の AgentNetwork を使って「複数エージェントと MCPサーバーの組み合わせ」を試す - Qiita
　https://qiita.com/youtoy/items/8a20d6c1a2af6d82826c