Mastraをローカルにインストールする
Mastraを実行するには、LLMへのアクセスが必要です。通常、以下のようなLLMプロバイダーからAPIキーを取得することになります:
また、以下を使用してローカルLLMでMastraを実行することもできます:
- Ollama .
構築するもの
このガイドの終わりまでに、OpenAIのgpt-4o-mini とOpen-Meteoのforecast エンドポイントを使用して天気レポートを生成する天気エージェントを構築します。コマンドラインから直接実行したり、Mastraプレイグラウンドでテストしたりすることができます。天気エージェントを実行すると、次のような質問ができます:
ロンドンの天気はどうですか?
明日ベルリンで雨が降る場合の屋内での代替案を提案してください。
今日のサンフランシスコは風が強いですか?
前提条件
- Node.js
v20.0
以上 - サポートされている大規模言語モデル(LLM)へのアクセス
自動インストール
新しいプロジェクトを作成する
CLIを使用して新しいプロジェクトを作成する際には、2つのオプションがあります:
プロジェクトを段階的にスキャフォールディングするガイド付きのインタラクティブセットアップを使用して、新しいMastraプロジェクトを開始することをお勧めします。
インタラクティブ
プロジェクトを作成するには、以下を実行してください:
npx
npx create-mastra@latest
プロンプトの後、create-mastra
は以下を実行します:
- TypeScriptでプロジェクトディレクトリをセットアップ
- 依存関係をインストール
- 選択したコンポーネントとLLMプロバイダーを設定
- IDE内でMCPサーバーを設定(選択した場合)し、コーディング中にドキュメント、例、ヘルプへの即座のアクセスを提供
異なるIDEを使用している場合は、MCPサーバードキュメントの手順に従って、MCPサーバーを手動でインストールできます。また、MCPサーバーを有効化するためにCursorとWindsurfには追加の手順があることにご注意ください。
非インタラクティブ
必要なフラグをすべて渡すことで、Mastra CLIを完全に非インタラクティブモードで実行できます。例:
npx create-mastra@latest --project-name hello-mastra --example --components tools,agents,workflows --llm openai
利用可能なCLIオプションの完全なリストについては、mastra initドキュメントをご覧ください。
APIキーを設定する
プロジェクトのルートディレクトリに.env
ファイルを作成し、APIキーを追加してください:
OPENAI_API_KEY=<your-api-key>
your-api-key
をあなたのAPIキーに置き換えてください。
手動インストール
Mastraプロジェクトを手動でセットアップしたい場合は、以下の手順に従ってください:
新しいプロジェクトを作成する
新しいプロジェクトを作成してディレクトリを変更します:
mkdir hello-mastra
cd hello-mastra
@mastra/core
パッケージを含むTypeScriptプロジェクトを初期化します:
npm
npm init -y
npm install typescript tsx @types/node mastra@latest --save-dev
npm install @mastra/core@latest zod @ai-sdk/openai
package.json
にdev
とbuild
スクリプトを追加します:
{
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "mastra dev",
"build": "mastra build"
}
}
TypeScriptを初期化する
プロジェクトルートに以下の設定でtsconfig.json
ファイルを作成します:
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "bundler",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"outDir": "dist"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", ".mastra"]
}
このTypeScript設定はMastraプロジェクト用に最適化されており、モダンなモジュール解決と厳密な型チェックを使用しています。
APIキーを設定する
プロジェクトルートディレクトリに.env
ファイルを作成し、APIキーを追加します:
OPENAI_API_KEY=<your-api-key>
your-api-key
をあなたのAPIキーに置き換えてください。
ツールを作成する
weather-tool.ts
ファイルを作成します:
mkdir -p src/mastra/tools && touch src/mastra/tools/weather-tool.ts
以下のコードを追加します:
import { createTool } from "@mastra/core/tools";
import { z } from "zod";
interface WeatherResponse {
current: {
time: string;
temperature_2m: number;
apparent_temperature: number;
relative_humidity_2m: number;
wind_speed_10m: number;
wind_gusts_10m: number;
weather_code: number;
};
}
export const weatherTool = createTool({
id: "get-weather",
description: "Get current weather for a location",
inputSchema: z.object({
location: z.string().describe("City name"),
}),
outputSchema: z.object({
temperature: z.number(),
feelsLike: z.number(),
humidity: z.number(),
windSpeed: z.number(),
windGust: z.number(),
conditions: z.string(),
location: z.string(),
}),
execute: async ({ context }) => {
return await getWeather(context.location);
},
});
const getWeather = async (location: string) => {
const geocodingUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(location)}&count=1`;
const geocodingResponse = await fetch(geocodingUrl);
const geocodingData = await geocodingResponse.json();
if (!geocodingData.results?.[0]) {
throw new Error(`Location '${location}' not found`);
}
const { latitude, longitude, name } = geocodingData.results[0];
const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,apparent_temperature,relative_humidity_2m,wind_speed_10m,wind_gusts_10m,weather_code`;
const response = await fetch(weatherUrl);
const data: WeatherResponse = await response.json();
return {
temperature: data.current.temperature_2m,
feelsLike: data.current.apparent_temperature,
humidity: data.current.relative_humidity_2m,
windSpeed: data.current.wind_speed_10m,
windGust: data.current.wind_gusts_10m,
conditions: getWeatherCondition(data.current.weather_code),
location: name,
};
};
function getWeatherCondition(code: number): string {
const conditions: Record<number, string> = {
0: "Clear sky",
1: "Mainly clear",
2: "Partly cloudy",
3: "Overcast",
45: "Foggy",
48: "Depositing rime fog",
51: "Light drizzle",
53: "Moderate drizzle",
55: "Dense drizzle",
56: "Light freezing drizzle",
57: "Dense freezing drizzle",
61: "Slight rain",
63: "Moderate rain",
65: "Heavy rain",
66: "Light freezing rain",
67: "Heavy freezing rain",
71: "Slight snow fall",
73: "Moderate snow fall",
75: "Heavy snow fall",
77: "Snow grains",
80: "Slight rain showers",
81: "Moderate rain showers",
82: "Violent rain showers",
85: "Slight snow showers",
86: "Heavy snow showers",
95: "Thunderstorm",
96: "Thunderstorm with slight hail",
99: "Thunderstorm with heavy hail",
};
return conditions[code] || "Unknown";
}
エージェントを作成する
weather-agent.ts
ファイルを作成します:
mkdir -p src/mastra/agents && touch src/mastra/agents/weather-agent.ts
以下のコードを追加します:
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
import { weatherTool } from "../tools/weather-tool";
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
- Include relevant details like humidity, wind conditions, and precipitation
- Keep responses concise but informative
Use the weatherTool to fetch current weather data.`,
model: openai("gpt-4o-mini"),
tools: { weatherTool },
});
ワークフローを作成する
weather-workflow.ts
ファイルを作成します:
mkdir -p src/mastra/workflows && touch src/mastra/workflows/weather-workflow.ts
以下のコードを追加します:
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
import { createStep, createWorkflow } from "@mastra/core/workflows";
import { z } from "zod";
const llm = openai("gpt-4o-mini");
const agent = new Agent({
name: "Weather Agent",
model: llm,
instructions: `
あなたは天気に基づく計画立案に優れた地域活動・旅行の専門家です。天気データを分析し、実用的な活動の推奨事項を提供してください。
予報の各日について、以下の通りに正確に構造化して回答してください:
📅 [曜日、月 日、年]
═══════════════════════════
🌡️ 天気概要
• 状況:[簡潔な説明]
• 気温:[X°C/Y°F から A°C/B°F]
• 降水確率:[X%]
🌅 午前の活動
屋外:
• [活動名] - [具体的な場所/ルートを含む簡潔な説明]
最適な時間:[具体的な時間帯]
注意:[関連する天気の考慮事項]
🌞 午後の活動
屋外:
• [活動名] - [具体的な場所/ルートを含む簡潔な説明]
最適な時間:[具体的な時間帯]
注意:[関連する天気の考慮事項]
🏠 屋内の代替案
• [活動名] - [具体的な会場を含む簡潔な説明]
適している条件:[この代替案を選ぶきっかけとなる天気条件]
⚠️ 特別な考慮事項
• [関連する天気警報、UV指数、風の状況など]
ガイドライン:
- 1日あたり2-3の時間指定屋外活動を提案
- 1-2の屋内バックアップオプションを含める
- 降水確率が50%を超える場合は、屋内活動を優先
- すべての活動は場所に特化したものでなければならない
- 具体的な会場、トレイル、または場所を含める
- 気温に基づいて活動の強度を考慮
- 説明は簡潔だが情報豊富に保つ
一貫性のため、示されている絵文字とセクションヘッダーを使用して、この正確なフォーマットを維持してください。
`,
});
const forecastSchema = z.object({
date: z.string(),
maxTemp: z.number(),
minTemp: z.number(),
precipitationChance: z.number(),
condition: z.string(),
location: z.string(),
});
function getWeatherCondition(code: number): string {
const conditions: Record<number, string> = {
0: "Clear sky",
1: "Mainly clear",
2: "Partly cloudy",
3: "Overcast",
45: "Foggy",
48: "Depositing rime fog",
51: "Light drizzle",
53: "Moderate drizzle",
55: "Dense drizzle",
61: "Slight rain",
63: "Moderate rain",
65: "Heavy rain",
71: "Slight snow fall",
73: "Moderate snow fall",
75: "Heavy snow fall",
95: "Thunderstorm",
};
return conditions[code] || "Unknown";
}
const fetchWeather = createStep({
id: "fetch-weather",
description: "指定された都市の天気予報を取得します",
inputSchema: z.object({
city: z.string().describe("天気を取得する都市"),
}),
outputSchema: forecastSchema,
execute: async ({ inputData }) => {
if (!inputData) {
throw new Error("Input data not found");
}
const geocodingUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(inputData.city)}&count=1`;
const geocodingResponse = await fetch(geocodingUrl);
const geocodingData = (await geocodingResponse.json()) as {
results: { latitude: number; longitude: number; name: string }[];
};
if (!geocodingData.results?.[0]) {
throw new Error(`Location '${inputData.city}' not found`);
}
const { latitude, longitude, name } = geocodingData.results[0];
const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=precipitation,weathercode&timezone=auto,&hourly=precipitation_probability,temperature_2m`;
const response = await fetch(weatherUrl);
const data = (await response.json()) as {
current: {
time: string;
precipitation: number;
weathercode: number;
};
hourly: {
precipitation_probability: number[];
temperature_2m: number[];
};
};
const forecast = {
date: new Date().toISOString(),
maxTemp: Math.max(...data.hourly.temperature_2m),
minTemp: Math.min(...data.hourly.temperature_2m),
condition: getWeatherCondition(data.current.weathercode),
precipitationChance: data.hourly.precipitation_probability.reduce(
(acc, curr) => Math.max(acc, curr),
0,
),
location: inputData.city,
};
return forecast;
},
});
const planActivities = createStep({
id: "plan-activities",
description: "天気条件に基づいてアクティビティを提案します",
inputSchema: forecastSchema,
outputSchema: z.object({
activities: z.string(),
}),
execute: async ({ inputData }) => {
const forecast = inputData;
if (!forecast) {
throw new Error("Forecast data not found");
}
const prompt = `${forecast.location}の以下の天気予報に基づいて、適切なアクティビティを提案してください:
${JSON.stringify(forecast, null, 2)}
`;
const response = await agent.stream([
{
role: "user",
content: prompt,
},
]);
let activitiesText = "";
for await (const chunk of response.textStream) {
process.stdout.write(chunk);
activitiesText += chunk;
}
return {
activities: activitiesText,
};
},
});const weatherWorkflow = createWorkflow({
id: "weather-workflow",
inputSchema: z.object({
city: z.string().describe("天気を取得する都市"),
}),
outputSchema: z.object({
activities: z.string(),
}),
})
.then(fetchWeather)
.then(planActivities);
weatherWorkflow.commit();
export { weatherWorkflow };
エージェントを登録する
Mastraのエントリーポイントを作成し、エージェントを登録します:
touch src/mastra/index.ts
以下のコードを追加します:
import { Mastra } from "@mastra/core";
import { PinoLogger } from "@mastra/loggers";
import { LibSQLStore } from "@mastra/libsql";
import { weatherWorkflow } from "./workflows/weather-workflow";
import { weatherAgent } from "./agents/weather-agent";
export const mastra = new Mastra({
workflows: { weatherWorkflow },
agents: { weatherAgent },
storage: new LibSQLStore({
// stores telemetry, evals, ... into memory storage, if it needs to persist, change to file:../mastra.db
url: ":memory:",
}),
logger: new PinoLogger({
name: "Mastra",
level: "info",
}),
});
これにより、エージェントがMastraに登録され、
mastra dev
がエージェントを発見してサーブできるようになります。
Mastraサーバーの起動
MastraはREST エンドポイント経由でエージェントを提供するコマンドを提供します
開発サーバー
以下のコマンドを実行してMastraサーバーを起動します:
npm run dev
mastra CLIがインストールされている場合は、以下を実行します:
mastra dev
このコマンドは、以下のリンクで利用可能なエージェント用のREST APIエンドポイントを作成します:
- Playground: http://localhost:4111/
- Mastra API: http://localhost:4111/api
- OpenAPI Spec: http://localhost:4111/openapi.json
- Swagger UI – API explorer: http://localhost:4111/swagger-ui
エンドポイントのテスト
curl
またはfetch
を使用してエージェントのエンドポイントをテストすることもできます:
curl
curl -X POST http://localhost:4111/api/agents/weatherAgent/generate \
-H "Content-Type: application/json" \
-d '{"messages": ["What is the weather in London?"]}'
コマンドラインからの実行
コマンドラインから直接エージェントを呼び出したい場合は、エージェントを取得して呼び出すシンプルなスクリプトを作成します。
テストファイルを作成します:
touch src/test-agent.ts
環境変数(例:APIキー)を読み込むためにdotenv
をインストールします:
npm
bash copy npm install dotenv --save-dev
.env
ファイルを使用している場合は、以下のコードを追加します:
import "dotenv/config";
import { mastra } from "./mastra";
async function main() {
const agent = await mastra.getAgent("weatherAgent");
const result = await agent.generate("What is the weather in London?");
console.log("Agent response:", result.text);
}
main();
または、.env.development
ファイルを使用している場合は、以下のコードを追加します:
import { config } from "dotenv";
config({ path: ".env.development" });
import { mastra } from "./mastra";
async function main() {
const agent = await mastra.getAgent("weatherAgent");
const result = await agent.generate("What is the weather in London?");
console.log("Agent response:", result.text);
}
main();
スクリプトを実行してエージェントをテストします:
npx tsx src/test-agent.ts
以下のような出力が表示されるはずです:
Agent response: The current weather in London is as follows:
- **Temperature:** 12.9°C (Feels like 9.7°C)
- **Humidity:** 63%
- **Wind Speed:** 14.7 km/h
- **Wind Gusts:** 32.4 km/h
- **Conditions:** Overcast
Let me know if you need more information!
クライアントでMastraを使用する
フロントエンドアプリケーションでMastraを使用するには、タイプセーフなクライアントSDKを使用してMastra REST APIを介してエージェントを呼び出します。
既存プロジェクトへのインストール
既存のプロジェクトにMastraを追加するには、ローカル開発のドキュメントをご覧ください: