From 8df056f9b5f37448d79b5a775706c27bba90e431 Mon Sep 17 00:00:00 2001 From: Mameta29 Date: Mon, 3 Nov 2025 13:23:51 +0900 Subject: [PATCH 01/10] Add AI-Agent-JPYC-ChatApp learning content foundation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新しい学習コンテンツ「AI-Agent-JPYC-ChatApp」の土台を追加 ## 追加内容 ### セクション0:プロジェクト概要 - プロジェクトの目的と目標 - 学習内容の説明 - 前提知識とプロジェクトの流れ ### セクション1:座学(完全実装) - lesson-1: JPYCについて - lesson-2: JPYC SDKについて - lesson-3: AI Agentについて - lesson-4: MCPについて - lesson-5: Mastraについて ### セクション2:セットアップ - lesson-1: プロジェクトのセットアップ ### セクション3:MCPの実装(プレースホルダー) - lesson-1: MCPサーバーの基礎実装 - lesson-2: JPYC残高確認ツール - lesson-3: JPYC送金ツール - lesson-4: トランザクション履歴ツール ### セクション4:MCPの組み込み(プレースホルダー) - lesson-1: Mastraエージェントの作成 - lesson-2: MCPサーバーの統合 - lesson-3: API Routeの実装 ### セクション5:フロントエンドの実装(プレースホルダー) - lesson-1: チャットインターフェース - lesson-2: メッセージ送信機能 - lesson-3: ストリーミングレスポンス - lesson-4: アプリケーション完成とテスト 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- docs/AI/AI-Agent-JPYC-ChatApp/index.md | 3 + .../section-0/lesson-1.md | 107 +++++ .../section-1/lesson-1.md | 109 +++++ .../section-1/lesson-2.md | 239 +++++++++++ .../section-1/lesson-3.md | 183 +++++++++ .../section-1/lesson-4.md | 299 ++++++++++++++ .../section-1/lesson-5.md | 381 ++++++++++++++++++ .../section-2/lesson-1.md | 142 +++++++ .../section-3/lesson-1.md | 28 ++ .../section-3/lesson-2.md | 24 ++ .../section-3/lesson-3.md | 24 ++ .../section-3/lesson-4.md | 24 ++ .../section-4/lesson-1.md | 28 ++ .../section-4/lesson-2.md | 24 ++ .../section-4/lesson-3.md | 24 ++ .../section-5/lesson-1.md | 28 ++ .../section-5/lesson-2.md | 24 ++ .../section-5/lesson-3.md | 24 ++ .../section-5/lesson-4.md | 61 +++ 19 files changed, 1776 insertions(+) create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/index.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-0/lesson-1.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-2.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-3.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-2/lesson-1.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-4.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-1.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-2.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-3.md create mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/index.md b/docs/AI/AI-Agent-JPYC-ChatApp/index.md new file mode 100644 index 00000000..5bc99d56 --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/index.md @@ -0,0 +1,3 @@ +# AI-Agent-JPYC-ChatApp + +![](/metadata/AI-Agent-JPYC-ChatApp/learn-banner.jpg) diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-0/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-0/lesson-1.md new file mode 100644 index 00000000..755efb3e --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-0/lesson-1.md @@ -0,0 +1,107 @@ +--- +title: プロジェクトの概要 +--- + +### 👋 AI Agent × JPYC チャットアプリへようこそ + +このプロジェクトでは、AI AgentとJPYC(日本円ステーブルコイン)を組み合わせた革新的なチャットアプリケーションを構築します。 + +AI Agentが自律的にJPYCを使った送金や残高確認などの操作を行える、次世代のWeb3アプリケーションを体験しましょう。 + +### 🎯 このプロジェクトで学べること + +このプロジェクトを通じて、以下のスキルを習得できます: + +1. **JPYC(日本円ステーブルコイン)の基礎知識** + - JPYCとは何か、どのように動作するか + - JPYC SDKの使い方 + +2. **AI Agentの実装方法** + - AI Agentの基本概念 + - Mastraフレームワークを使ったAgent開発 + +3. **MCP(Model Context Protocol)の理解と実装** + - MCPとは何か + - AI AgentにWeb3機能を追加する方法 + +4. **フルスタック開発スキル** + - バックエンド:TypeScript、Node.js + - フロントエンド:Next.js、React + - AI統合:Claude API、Mastra + +### 🛠 何を作るのか? + +このプロジェクトでは、以下の機能を持つチャットアプリケーションを構築します: + +- **AI Agentとの自然な対話**:ユーザーはAI Agentと自然言語でコミュニケーション +- **JPYC送金機能**:「〇〇さんに100 JPYC送って」とお願いすると、AI Agentが自動で送金処理 +- **残高確認機能**:「残高を教えて」と聞くと、AI Agentが現在のJPYC残高を確認 +- **トランザクション履歴**:過去の取引履歴をAI Agentが取得・表示 + +### 🌟 このプロジェクトの魅力 + +**Web3 × AI の融合** + +従来のWeb3アプリケーションでは、ユーザーが手動でウォレットを操作する必要がありました。しかし、AI Agentを組み合わせることで、自然言語での指示だけでブロックチェーン操作が可能になります。 + +**実用的なステーブルコイン体験** + +JPYCは日本円と1:1でペッグされたステーブルコインです。価格変動が少ないため、実際の決済や送金のユースケースに最適です。 + +**最新技術の習得** + +- **MCP(Model Context Protocol)**:Anthropic社が提唱する、AI Agentとツールをつなぐためのプロトコル +- **Mastra**:AI Agentを簡単に構築できるモダンなフレームワーク +- **JPYC SDK**:JPYCを扱うための専用SDK + +### 📚 前提知識 + +このプロジェクトを始める前に、以下の基礎知識があると理解がスムーズです: + +- JavaScriptまたはTypeScriptの基本文法 +- React.jsの基礎 +- ブロックチェーンとウォレットの基本概念 +- (必須ではないが望ましい)Next.jsの経験 + +### 🚀 プロジェクトの流れ + +このプロジェクトは、以下の5つのセクションで構成されています: + +**セクション1:座学** +JPYCやAI Agent、MCP、Mastraなどの基礎知識を学びます。 + +**セクション2:セットアップ** +開発環境を構築し、必要な依存関係をインストールします。 + +**セクション3:MCPの実装** +JPYC操作のためのMCPサーバーを実装します。 + +**セクション4:MCPの組み込み** +MastraフレームワークにMCPを統合し、AI Agentに機能を追加します。 + +**セクション5:フロントエンドの実装** +Next.jsでユーザーインターフェースを構築し、アプリケーションを完成させます。 + +### 🎓 このプロジェクトを終えると + +プロジェクト完了後、あなたは以下のことができるようになります: + +- AI AgentとWeb3を組み合わせたアプリケーションを開発できる +- MCPを使ってAI Agentに独自の機能を追加できる +- JPYCを使った実用的な決済アプリを構築できる +- Mastraフレームワークを活用したAI Agent開発ができる + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンに進んで、本格的な開発を始めましょう! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md new file mode 100644 index 00000000..9c420e7c --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md @@ -0,0 +1,109 @@ +--- +title: JPYCについて +--- + +### 💴 JPYC とは? + +JPYC(JPY Coin)は、日本円と1:1でペッグされた**ステーブルコイン**です。 + +ステーブルコインとは、法定通貨(この場合は日本円)の価値に連動するように設計された暗号資産のことを指します。 + +### 🔑 JPYC の特徴 + +**1. 価格の安定性** + +JPYCは常に1 JPYC = 1円の価値を維持するように設計されています。ビットコインやイーサリアムのような価格変動がないため、日常的な決済や送金に適しています。 + +**2. 高速かつ低コストな送金** + +従来の銀行振込と比較して、JPYCを使った送金は: +- 24時間365日いつでも送金可能 +- 数秒〜数分で着金 +- 低い手数料(ブロックチェーンの手数料のみ) + +**3. プログラマビリティ** + +スマートコントラクトと組み合わせることで、自動送金や条件付き決済などの複雑な処理を実装できます。 + +**4. 透明性とトレーサビリティ** + +すべての取引がブロックチェーン上に記録されるため、透明性が高く、取引履歴を追跡することができます。 + +### 🌐 JPYC の利用可能なチェーン + +JPYCは複数のブロックチェーンで発行されています: + +- **Ethereum**(イーサリアム) +- **Polygon**(ポリゴン) +- **Avalanche**(アバランチ) +- **Gnosis Chain**(ノーシスチェーン) +- その他 + +このプロジェクトでは、**Polygon**ネットワーク上のJPYCを使用します。Polygonは、低い手数料と高速な取引処理が特徴です。 + +### 🎯 JPYC のユースケース + +**決済・送金** +- ECサイトでの商品購入 +- 個人間の送金 +- 給与や報酬の支払い + +**DeFi(分散型金融)** +- レンディング(貸し借り) +- 流動性プール +- イールドファーミング + +**Web3アプリケーション** +- NFTマーケットプレイスでの取引 +- ゲーム内通貨 +- DAO(分散型自律組織)での運用 + +### 📖 JPYC の仕組み + +JPYCは**前払式支払手段**として発行されています。 + +1. ユーザーが日本円をJPYC発行事業者に預ける +2. 預けた金額と同額のJPYCが発行される +3. ユーザーはJPYCを自由に使用・送金できる +4. JPYCを日本円に戻したい場合、払い戻しを申請できる + +この仕組みにより、1 JPYC = 1円の価値が担保されています。 + +### 🔐 セキュリティと信頼性 + +**規制対応** + +JPYCは日本の法規制に準拠した形で運営されています。前払式支払手段として登録されており、安心して利用できます。 + +**監査** + +JPYCのスマートコントラクトは、第三者機関による監査を受けています。コードの安全性が確認されています。 + +**準備金の透明性** + +発行されているJPYCの総額に対して、同額以上の日本円が準備金として保管されています。準備金の状況は定期的に公開されています。 + +### 💡 このプロジェクトでの JPYC の役割 + +このプロジェクトでは、AI AgentがJPYCを使って以下の操作を行います: + +- **残高確認**:ユーザーのJPYC残高を取得 +- **送金処理**:指定されたアドレスにJPYCを送金 +- **取引履歴の取得**:過去のJPYC取引履歴を確認 + +AI Agentが自然言語での指示を理解し、これらの操作を自動的に実行することで、より直感的なWeb3体験を提供します。 + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンでは、JPYC SDKについて学びます! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-2.md new file mode 100644 index 00000000..6a0f326d --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-2.md @@ -0,0 +1,239 @@ +--- +title: JPYC SDKについて +--- + +### 🛠 JPYC SDK とは? + +JPYC SDKは、JPYCを簡単に操作するためのTypeScript/JavaScriptライブラリです。 + +ブロックチェーンの複雑な処理を抽象化し、開発者が簡単にJPYC機能を実装できるようにします。 + +### ✨ JPYC SDK の主な機能 + +**1. 残高照会** + +ユーザーのJPYC残高を取得します。 + +```typescript +const balance = await jpycClient.getBalance(address); +console.log(`残高: ${balance} JPYC`); +``` + +**2. 送金処理** + +指定したアドレスにJPYCを送金します。 + +```typescript +const tx = await jpycClient.transfer( + recipientAddress, + amount +); +console.log(`送金完了: ${tx.hash}`); +``` + +**3. トランザクション履歴の取得** + +過去の取引履歴を取得します。 + +```typescript +const transactions = await jpycClient.getTransactionHistory( + address +); +``` + +**4. 承認(Approve)処理** + +スマートコントラクトがJPYCを操作できるように承認します。 + +```typescript +const approveTx = await jpycClient.approve( + spenderAddress, + amount +); +``` + +### 📦 JPYC SDK のインストール + +JPYC SDKは、npmまたはyarnを使ってインストールできます: + +```bash +npm install @jpyc/sdk +``` + +または + +```bash +yarn add @jpyc/sdk +``` + +### 🔧 JPYC SDK の初期化 + +JPYC SDKを使用するには、まず初期化が必要です: + +```typescript +import { JPYCClient } from '@jpyc/sdk'; +import { ethers } from 'ethers'; + +// ウォレットプロバイダーを作成 +const provider = new ethers.JsonRpcProvider(RPC_URL); +const wallet = new ethers.Wallet(PRIVATE_KEY, provider); + +// JPYC クライアントを初期化 +const jpycClient = new JPYCClient({ + network: 'polygon', // 使用するネットワーク + signer: wallet, // 署名用のウォレット +}); +``` + +### 🌐 サポートするネットワーク + +JPYC SDKは、複数のブロックチェーンネットワークに対応しています: + +- `ethereum` - イーサリアムメインネット +- `polygon` - Polygon(旧Matic)ネットワーク +- `avalanche` - Avalanche C-Chain +- `gnosis` - Gnosis Chain + +このプロジェクトでは、**Polygonネットワーク**を使用します。 + +### 💰 残高確認の詳細 + +残高確認は、最も基本的な操作です: + +```typescript +// 残高を取得(Wei単位) +const balanceWei = await jpycClient.getBalance(userAddress); + +// 人間が読める形式に変換(JPYC単位) +const balanceJPYC = ethers.formatUnits(balanceWei, 18); + +console.log(`残高: ${balanceJPYC} JPYC`); +``` + +JPYCは18桁の小数点精度を持つため、`formatUnits`関数で変換します。 + +### 📤 送金処理の詳細 + +送金処理では、以下のパラメータを指定します: + +```typescript +const tx = await jpycClient.transfer( + recipientAddress, // 送金先アドレス + amount // 送金額(Wei単位) +); + +// トランザクションの完了を待つ +await tx.wait(); + +console.log(`送金完了: ${tx.hash}`); +``` + +**注意点**: +- `amount`はWei単位で指定する必要があります +- 送金には少額のMATIC(Polygonの手数料用トークン)が必要です + +### 📊 トランザクション履歴の取得 + +過去の取引履歴を取得し、分析することができます: + +```typescript +const transactions = await jpycClient.getTransactionHistory( + userAddress, + { + startBlock: 0, // 検索開始ブロック + endBlock: 'latest', // 検索終了ブロック + limit: 100 // 取得件数の上限 + } +); + +transactions.forEach(tx => { + console.log(` + 日時: ${new Date(tx.timestamp * 1000).toLocaleString()} + 送信元: ${tx.from} + 送信先: ${tx.to} + 金額: ${ethers.formatUnits(tx.value, 18)} JPYC + `); +}); +``` + +### 🔐 セキュリティのベストプラクティス + +**1. 秘密鍵の管理** + +秘密鍵は絶対に公開してはいけません: + +```typescript +// ❌ 悪い例:秘密鍵をハードコーディング +const PRIVATE_KEY = "0x1234..."; + +// ✅ 良い例:環境変数から読み込む +const PRIVATE_KEY = process.env.PRIVATE_KEY; +``` + +**2. 送金額の検証** + +送金前に金額を検証します: + +```typescript +// 残高を確認 +const balance = await jpycClient.getBalance(senderAddress); + +if (balance < amount) { + throw new Error('残高不足です'); +} + +// 送金処理 +await jpycClient.transfer(recipientAddress, amount); +``` + +**3. エラーハンドリング** + +ブロックチェーン操作は失敗する可能性があるため、適切なエラーハンドリングが重要です: + +```typescript +try { + const tx = await jpycClient.transfer(recipientAddress, amount); + await tx.wait(); + console.log('送金成功'); +} catch (error) { + console.error('送金失敗:', error.message); + // エラーに応じた適切な処理 +} +``` + +### 🧪 テストネット環境 + +開発中は、テストネット環境を使用することを推奨します: + +```typescript +// Polygon Mumbai テストネット +const jpycClient = new JPYCClient({ + network: 'polygon-mumbai', + signer: wallet, +}); +``` + +テストネットでは、実際の資産を使わずに開発・テストができます。 + +### 📚 このプロジェクトでの JPYC SDK の役割 + +このプロジェクトでは、JPYC SDKをMCP(Model Context Protocol)サーバーに統合します。 + +MCPサーバーがJPYC SDKを使用してブロックチェーン操作を行い、AI Agentがそれを自然言語で制御します。 + +具体的な統合方法は、セクション3とセクション4で詳しく学びます。 + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンでは、AI Agentについて学びます! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-3.md new file mode 100644 index 00000000..01e6048d --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-3.md @@ -0,0 +1,183 @@ +--- +title: AI Agentについて +--- + +### 🤖 AI Agent とは? + +AI Agentとは、**自律的にタスクを実行できる人工知能システム**のことです。 + +従来のチャットボットと異なり、AI Agentは以下のような特徴を持ちます: + +- 目標を理解し、それを達成するための計画を立てる +- 外部ツールやAPIを使用して情報を取得したり、アクションを実行する +- 状況に応じて柔軟に判断し、行動を調整する +- 複数のステップを経て、複雑なタスクを完遂する + +### 🆚 チャットボット vs AI Agent + +従来のチャットボットとAI Agentの違いを見てみましょう: + +**チャットボット** +- 事前に定義されたシナリオに沿って応答 +- 単純な質問応答のみ +- 外部システムとの連携が限定的 +- 能動的な行動ができない + +**AI Agent** +- 状況を理解し、自律的に判断 +- 複雑なタスクを計画・実行 +- 外部ツールを自由に使用 +- 目標達成のために能動的に行動 + +### 🧠 AI Agent のアーキテクチャ + +AI Agentは、一般的に以下のコンポーネントで構成されます: + +**1. 言語モデル(LLM)** + +AI Agentの「脳」にあたる部分です。ユーザーの意図を理解し、適切な行動を決定します。 + +このプロジェクトでは、**Claude API**(Anthropic社の大規模言語モデル)を使用します。 + +**2. ツール(Tools)** + +AI Agentが実行できる具体的な機能です。例: +- Web検索 +- データベースへのクエリ +- APIの呼び出し +- ファイル操作 + +このプロジェクトでは、JPYCの残高確認や送金などがツールになります。 + +**3. メモリ(Memory)** + +過去の会話やアクションを記憶する機能です。これにより、文脈を理解した応答が可能になります。 + +**4. プランナー(Planner)** + +複雑なタスクを小さなステップに分解し、実行順序を決定します。 + +### 🔄 AI Agent の動作フロー + +AI Agentは、以下のようなループで動作します: + +1. **入力の理解**:ユーザーからの指示を解析 +2. **計画の立案**:目標を達成するための手順を決定 +3. **ツールの実行**:必要なツールを呼び出す +4. **結果の評価**:実行結果を確認し、次のアクションを決定 +5. **応答の生成**:ユーザーに結果を報告 + +このサイクルを、目標が達成されるまで繰り返します。 + +### 💬 具体例:JPYC 送金の場合 + +ユーザーが「太郎さんに100 JPYC送って」と指示した場合: + +``` +1. 入力の理解 + → 「送金」というアクションが必要 + → 送金先:太郎さん + → 送金額:100 JPYC + +2. 計画の立案 + Step 1: 太郎さんのウォレットアドレスを取得 + Step 2: 現在の残高を確認 + Step 3: 送金を実行 + Step 4: 結果をユーザーに報告 + +3. ツールの実行 + - アドレス帳ツールで太郎さんのアドレスを検索 + - 残高確認ツールで残高をチェック + - 送金ツールで送金を実行 + +4. 結果の評価 + - 送金が成功したかを確認 + - エラーがあれば原因を特定 + +5. 応答の生成 + 「太郎さん(0x123...)に100 JPYCを送金しました。 + トランザクションID: 0xabc...」 +``` + +### 🎯 AI Agent のユースケース + +AI Agentは、様々な分野で活用されています: + +**Web3・ブロックチェーン** +- 自動取引(トレーディングBot) +- DAO運営の補助 +- NFTの自動管理 + +**業務自動化** +- カスタマーサポート +- データ分析とレポート作成 +- スケジュール管理 + +**パーソナルアシスタント** +- メール管理 +- 情報収集と要約 +- タスク管理 + +### 🔧 AI Agent 開発の課題 + +AI Agentを開発する際には、以下のような課題があります: + +**1. ツールの統合** + +様々なAPIやサービスをAI Agentに組み込むのは複雑です。 + +→ **解決策**:MCP(Model Context Protocol)のような標準化されたプロトコルを使用 + +**2. エラーハンドリング** + +外部ツールの実行は失敗する可能性があります。 + +→ **解決策**:適切なエラーハンドリングとリトライロジックの実装 + +**3. セキュリティ** + +AI Agentに強力な権限を与えると、悪用のリスクがあります。 + +→ **解決策**:権限の最小化、操作の承認フロー、監査ログの記録 + +**4. 信頼性** + +LLMの出力は常に正確とは限りません。 + +→ **解決策**:重要な操作には確認ステップを挟む、出力の検証 + +### 🌟 このプロジェクトでの AI Agent + +このプロジェクトでは、以下の機能を持つAI Agentを構築します: + +**理解できること** +- JPYC残高の確認依頼 +- JPYC送金の指示 +- 取引履歴の照会依頼 + +**実行できること** +- ウォレットの残高確認 +- 指定アドレスへのJPYC送金 +- トランザクション履歴の取得と表示 + +**判断できること** +- 送金が可能かどうか(残高チェック) +- アドレスの有効性 +- エラー時の適切な対応 + +次のレッスンでは、AI AgentとツールをつなぐMCP(Model Context Protocol)について学びます! + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンでは、MCPについて学びます! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md new file mode 100644 index 00000000..7d53ce13 --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md @@ -0,0 +1,299 @@ +--- +title: MCPについて +--- + +### 🔌 MCP(Model Context Protocol)とは? + +MCP(Model Context Protocol)は、**AI Agentとツールやデータソースをつなぐための標準化されたプロトコル**です。 + +Anthropic社によって開発され、AI Agentが外部のツールやサービスを簡単に利用できるようにします。 + +### 🤔 なぜ MCP が必要なのか? + +AI Agentを開発する際、以下のような課題がありました: + +**課題1:ツール統合の複雑さ** + +各ツールやAPIごとに異なる実装方法を学ぶ必要がありました。 + +```typescript +// それぞれのツールで異なる実装が必要 +await weatherAPI.getCurrentWeather(location); +await databaseClient.query(sql); +await blockchainRPC.sendTransaction(tx); +``` + +**課題2:再利用性の低さ** + +ツールを別のプロジェクトで使いたい場合、コードを大幅に書き直す必要がありました。 + +**課題3:標準化の欠如** + +AI Agentとツール間のインターフェースに統一性がなく、開発者ごとに異なる実装がされていました。 + +### ✨ MCP が解決すること + +MCPは、これらの課題を以下のように解決します: + +**1. 統一されたインターフェース** + +すべてのツールが同じプロトコルで通信します。 + +```typescript +// MCPを使えば、すべてのツールが同じ方法で使える +await mcpServer.callTool('get_weather', { location }); +await mcpServer.callTool('query_database', { sql }); +await mcpServer.callTool('send_jpyc', { to, amount }); +``` + +**2. プラグアンドプレイ** + +一度作成したMCPサーバーは、どのAI Agentフレームワークでも使用できます。 + +**3. セキュリティと制御** + +MCPは、ツールへのアクセス制御や権限管理を標準化します。 + +### 🏗 MCP のアーキテクチャ + +MCPは、以下のコンポーネントで構成されます: + +**MCPサーバー** + +ツールやデータソースをホストする側です。 + +```typescript +// MCPサーバーの例 +const server = new MCPServer({ + name: 'jpyc-tools', + version: '1.0.0', + tools: [ + { + name: 'get_balance', + description: 'JPYC残高を取得する', + inputSchema: { + type: 'object', + properties: { + address: { type: 'string' } + } + }, + handler: async ({ address }) => { + // 残高取得の実装 + } + } + ] +}); +``` + +**MCPクライアント** + +AI AgentがMCPサーバーと通信するための部分です。 + +```typescript +// MCPクライアントの使用例 +const client = new MCPClient({ + serverUrl: 'http://localhost:3000' +}); + +// ツールの呼び出し +const result = await client.callTool('get_balance', { + address: '0x123...' +}); +``` + +**プロトコル** + +サーバーとクライアント間の通信ルールです。JSON-RPCベースの標準化されたメッセージフォーマットを使用します。 + +### 📡 MCP の通信フロー + +MCPの典型的な通信フローは以下の通りです: + +``` +1. AI Agent: ユーザーから「残高を教えて」という指示を受ける + +2. AI Agent → MCP Client: 適切なツールを選択 + "get_balance ツールを使う" + +3. MCP Client → MCP Server: ツール呼び出しリクエスト + { + "tool": "get_balance", + "parameters": { + "address": "0x123..." + } + } + +4. MCP Server: ツールを実行 + - JPYC SDKを使って残高を取得 + - 結果をフォーマット + +5. MCP Server → MCP Client: 実行結果を返す + { + "success": true, + "data": { + "balance": "1000", + "symbol": "JPYC" + } + } + +6. MCP Client → AI Agent: 結果を渡す + +7. AI Agent → User: 結果を自然言語で報告 + "あなたの残高は1,000 JPYCです" +``` + +### 🛠 MCP サーバーの構造 + +MCPサーバーは、以下の要素を定義します: + +**1. ツール(Tools)** + +AI Agentが実行できる具体的な機能です。 + +```typescript +{ + name: 'send_jpyc', + description: 'JPYCを送金する', + inputSchema: { + type: 'object', + properties: { + to: { + type: 'string', + description: '送金先アドレス' + }, + amount: { + type: 'string', + description: '送金額' + } + }, + required: ['to', 'amount'] + }, + handler: async ({ to, amount }) => { + // 送金処理の実装 + } +} +``` + +**2. リソース(Resources)** + +AI Agentがアクセスできるデータです。 + +```typescript +{ + uri: 'jpyc://transactions/history', + name: 'Transaction History', + description: 'JPYC取引履歴', + mimeType: 'application/json' +} +``` + +**3. プロンプト(Prompts)** + +AI Agentに提供するコンテキスト情報です。 + +```typescript +{ + name: 'jpyc_context', + description: 'JPYC操作のためのコンテキスト', + arguments: [ + { + name: 'userAddress', + description: 'ユーザーのウォレットアドレス', + required: true + } + ] +} +``` + +### 🎯 MCP の利点 + +**開発者にとって** +- ツールの実装が簡単になる +- 既存のツールを再利用できる +- 標準化されたテストとデバッグが可能 + +**AI Agentにとって** +- 多様なツールに一貫した方法でアクセスできる +- ツールの機能を自動的に理解できる +- エラーハンドリングが統一される + +**ユーザーにとって** +- より多機能なAI Agentを利用できる +- 信頼性の高いサービスを受けられる + +### 🔐 MCP のセキュリティ + +MCPは、以下のセキュリティ機能を提供します: + +**認証と認可** +```typescript +const server = new MCPServer({ + auth: { + type: 'bearer', + token: process.env.MCP_AUTH_TOKEN + } +}); +``` + +**入力検証** +```typescript +inputSchema: { + type: 'object', + properties: { + amount: { + type: 'string', + pattern: '^[0-9]+(\.[0-9]+)?$', // 数値のみ許可 + maximum: '10000' // 最大値の制限 + } + } +} +``` + +**レート制限** +```typescript +const server = new MCPServer({ + rateLimit: { + windowMs: 60000, // 1分 + maxRequests: 10 // 最大10リクエスト + } +}); +``` + +### 🌐 MCP のエコシステム + +MCPは、様々なフレームワークやツールと統合できます: + +- **AI Agentフレームワーク**:LangChain、Mastra、AutoGPTなど +- **LLMプロバイダー**:Claude、GPT-4、Geminiなど +- **開発ツール**:VS Code拡張、デバッガーなど + +### 💡 このプロジェクトでの MCP の役割 + +このプロジェクトでは、以下のようにMCPを使用します: + +1. **MCPサーバーの実装**(セクション3) + - JPYC操作のためのツールを定義 + - JPYC SDKと連携する実装 + +2. **Mastraとの統合**(セクション4) + - MastraフレームワークにMCPサーバーを接続 + - AI AgentからJPYCツールを利用可能にする + +3. **フロントエンドからの利用**(セクション5) + - Next.jsアプリからMastra経由でMCPを呼び出し + - ユーザーインターフェースの実装 + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンでは、Mastraについて学びます! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md new file mode 100644 index 00000000..a48b8ce7 --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md @@ -0,0 +1,381 @@ +--- +title: Mastraについて +--- + +### 🎭 Mastra とは? + +Mastraは、**AI Agentを簡単に構築できるモダンなTypeScriptフレームワーク**です。 + +複雑なAI Agentのロジックを抽象化し、開発者が本質的な機能の実装に集中できるようにします。 + +### ✨ Mastra の特徴 + +**1. シンプルなAPI** + +Mastraは、直感的で使いやすいAPIを提供します。 + +```typescript +import { Mastra } from '@mastra/core'; + +const mastra = new Mastra({ + agents: [myAgent], + tools: [myTool], +}); +``` + +**2. TypeScript完全対応** + +型安全な開発が可能で、エディタの補完機能をフル活用できます。 + +**3. 柔軟な統合** + +様々なLLMプロバイダー(Claude、OpenAI、Geminiなど)をサポートします。 + +**4. MCP対応** + +MCPプロトコルをネイティブサポートし、外部ツールを簡単に統合できます。 + +### 🏗 Mastra のアーキテクチャ + +Mastraは、以下の主要コンポーネントで構成されます: + +**Agentモジュール** + +AI Agentの振る舞いを定義します。 + +```typescript +import { Agent } from '@mastra/core'; + +const jpycAgent = new Agent({ + name: 'JPYC Agent', + instructions: ` + あなたはJPYC操作を支援するAIアシスタントです。 + ユーザーの指示に従って、送金や残高確認を行います。 + `, + model: { + provider: 'anthropic', + name: 'claude-3-5-sonnet', + toolChoice: 'auto', + }, +}); +``` + +**Toolモジュール** + +AI Agentが使用できるツールを定義します。 + +```typescript +import { createTool } from '@mastra/core'; + +const getBalanceTool = createTool({ + id: 'get_balance', + description: 'JPYC残高を取得する', + inputSchema: z.object({ + address: z.string().describe('ウォレットアドレス'), + }), + execute: async ({ context }) => { + const { address } = context; + // 残高取得の実装 + }, +}); +``` + +**Workflowモジュール** + +複数のステップからなる複雑な処理を定義します。 + +```typescript +import { createWorkflow } from '@mastra/core'; + +const sendJPYCWorkflow = createWorkflow({ + name: 'send_jpyc', + triggerSchema: z.object({ + to: z.string(), + amount: z.string(), + }), +}) + .step('check_balance') + .step('validate_address') + .step('execute_transfer') + .commit(); +``` + +### 🤖 Agent の作成 + +Mastraでは、Agentを簡単に作成できます: + +```typescript +import { Agent } from '@mastra/core'; + +const agent = new Agent({ + name: 'JPYC Assistant', + instructions: ` + あなたはJPYC(日本円ステーブルコイン)の操作を + 支援するAIアシスタントです。 + + 以下の操作をサポートします: + - 残高確認 + - 送金処理 + - 取引履歴の表示 + + ユーザーに対して親切で分かりやすい説明を心がけてください。 + `, + model: { + provider: 'anthropic', + name: 'claude-3-5-sonnet', + toolChoice: 'auto', + }, + tools: { + getBalance, + sendJPYC, + getHistory, + }, +}); +``` + +### 🛠 Tool の作成 + +Toolは、AI Agentが実行できる具体的な機能です: + +```typescript +import { createTool } from '@mastra/core'; +import { z } from 'zod'; + +const sendJPYCTool = createTool({ + id: 'send_jpyc', + description: '指定したアドレスにJPYCを送金する', + inputSchema: z.object({ + to: z.string().describe('送金先のウォレットアドレス'), + amount: z.string().describe('送金額(JPYC単位)'), + }), + execute: async ({ context }) => { + const { to, amount } = context; + + try { + // JPYC送金処理 + const tx = await jpycClient.transfer(to, amount); + + return { + success: true, + message: `${amount} JPYCを${to}に送金しました`, + txHash: tx.hash, + }; + } catch (error) { + return { + success: false, + message: `送金に失敗しました: ${error.message}`, + }; + } + }, +}); +``` + +### 💬 Agent の実行 + +作成したAgentを実行するのは簡単です: + +```typescript +// テキスト入力で実行 +const response = await agent.generate('残高を教えて'); +console.log(response.text); + +// ストリーミング実行 +const stream = await agent.stream('100 JPYC送って'); +for await (const chunk of stream) { + console.log(chunk.text); +} +``` + +### 🔄 Workflow の活用 + +Workflowを使うと、複数のステップを順序立てて実行できます: + +```typescript +import { createWorkflow } from '@mastra/core'; +import { z } from 'zod'; + +const transferWorkflow = createWorkflow({ + name: 'jpyc_transfer', + triggerSchema: z.object({ + recipientAddress: z.string(), + amount: z.string(), + }), +}) + .step('validate_inputs', async ({ context }) => { + // 入力値の検証 + const { recipientAddress, amount } = context.machineContext; + + if (!ethers.isAddress(recipientAddress)) { + throw new Error('無効なアドレスです'); + } + + return { valid: true }; + }) + .step('check_balance', async ({ context }) => { + // 残高確認 + const balance = await jpycClient.getBalance(userAddress); + const required = ethers.parseUnits(context.machineContext.amount, 18); + + if (balance < required) { + throw new Error('残高不足です'); + } + + return { sufficient: true }; + }) + .step('execute_transfer', async ({ context }) => { + // 送金実行 + const { recipientAddress, amount } = context.machineContext; + const tx = await jpycClient.transfer(recipientAddress, amount); + + return { + txHash: tx.hash, + status: 'success', + }; + }) + .commit(); + +// Workflowの実行 +const result = await transferWorkflow.execute({ + triggerData: { + recipientAddress: '0x123...', + amount: '100', + }, +}); +``` + +### 🔌 MCP との統合 + +MastraはMCPをネイティブサポートしています: + +```typescript +import { Mastra } from '@mastra/core'; +import { MCPClient } from '@mastra/mcp'; + +// MCPクライアントを作成 +const mcpClient = new MCPClient({ + serverUrl: 'http://localhost:3000', +}); + +// Mastraインスタンスを作成 +const mastra = new Mastra({ + agents: [jpycAgent], + mcpServers: { + jpycServer: mcpClient, + }, +}); + +// MCPサーバーのツールが自動的にAgentで利用可能になる +``` + +### 📊 コンテキスト管理 + +Mastraは、会話のコンテキストを自動的に管理します: + +```typescript +// 会話の開始 +const thread = await agent.createThread(); + +// メッセージの送信(コンテキストを保持) +await agent.generate('私の残高は?', { threadId: thread.id }); +// → "1,000 JPYCです" + +await agent.generate('半分を太郎さんに送って', { threadId: thread.id }); +// → 太郎さんに500 JPYCを送金します(コンテキストから金額を推測) +``` + +### 🎨 カスタマイズ + +Mastraは、様々な側面でカスタマイズ可能です: + +**モデルのカスタマイズ** +```typescript +const agent = new Agent({ + model: { + provider: 'anthropic', + name: 'claude-3-5-sonnet', + toolChoice: 'auto', + temperature: 0.7, + maxTokens: 1000, + }, +}); +``` + +**エラーハンドリング** +```typescript +const agent = new Agent({ + onError: async (error, context) => { + console.error('Agent error:', error); + // カスタムエラー処理 + }, +}); +``` + +**ログ記録** +```typescript +const mastra = new Mastra({ + logger: { + level: 'debug', + transport: customLogger, + }, +}); +``` + +### 🚀 パフォーマンス最適化 + +Mastraは、以下のパフォーマンス最適化機能を提供します: + +**キャッシング** +```typescript +const agent = new Agent({ + cache: { + enabled: true, + ttl: 300, // 5分 + }, +}); +``` + +**並列実行** +```typescript +// 複数のツールを並列実行 +const results = await Promise.all([ + agent.executeTool('get_balance', { address: addr1 }), + agent.executeTool('get_balance', { address: addr2 }), + agent.executeTool('get_balance', { address: addr3 }), +]); +``` + +### 💡 このプロジェクトでの Mastra の役割 + +このプロジェクトでは、Mastraを以下のように活用します: + +1. **Agentの定義** + - JPYC操作を支援するAgentを作成 + - 適切な指示とモデル設定 + +2. **Toolの実装** + - JPYC残高確認ツール + - JPYC送金ツール + - 取引履歴取得ツール + +3. **MCPとの統合** + - セクション3で作成するMCPサーバーを接続 + - AI Agentから自動的にMCPツールを利用 + +4. **API提供** + - Next.jsのAPI Routeから利用 + - フロントエンドとのインターフェース + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +これでセクション1(座学)は完了です!次のセクションでは、実際に開発環境をセットアップしていきます。 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-2/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-2/lesson-1.md new file mode 100644 index 00000000..f93668ef --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-2/lesson-1.md @@ -0,0 +1,142 @@ +--- +title: プロジェクトのセットアップ +--- + +### 🛠 開発環境の準備 + +このレッスンでは、プロジェクトの開発環境をセットアップします。 + +### 📋 必要な環境 + +以下のツールがインストールされていることを確認してください: + +- **Node.js**:v18以上 +- **npm**または**yarn**:パッケージマネージャー +- **Git**:バージョン管理 + +### 🚀 プロジェクトの作成 + +まず、Next.jsプロジェクトを作成します。 + +```bash +npx create-next-app@latest ai-agent-jpyc-chat --typescript --tailwind --app +cd ai-agent-jpyc-chat +``` + +オプションの選択: +- TypeScript:Yes +- ESLint:Yes +- Tailwind CSS:Yes +- `src/` directory:Yes +- App Router:Yes +- Import alias:No(または@を使用) + +### 📦 依存関係のインストール + +必要なパッケージをインストールします: + +```bash +# Mastraフレームワーク +npm install @mastra/core @mastra/mcp + +# JPYC SDK +npm install @jpyc/sdk + +# Web3関連 +npm install ethers viem + +# Claude API +npm install @anthropic-ai/sdk + +# その他のユーティリティ +npm install zod dotenv +``` + +開発用の依存関係もインストールします: + +```bash +npm install -D @types/node typescript +``` + +### 📁 プロジェクト構造の作成 + +以下のディレクトリ構造を作成します: + +``` +ai-agent-jpyc-chat/ +├── src/ +│ ├── app/ +│ │ ├── api/ +│ │ │ └── chat/ +│ │ │ └── route.ts +│ │ ├── layout.tsx +│ │ └── page.tsx +│ ├── lib/ +│ │ ├── mastra/ +│ │ │ ├── agent.ts +│ │ │ └── tools.ts +│ │ └── mcp/ +│ │ └── server.ts +│ └── components/ +│ └── ChatInterface.tsx +├── .env.local +├── package.json +└── tsconfig.json +``` + +必要なディレクトリを作成します: + +```bash +mkdir -p src/lib/mastra +mkdir -p src/lib/mcp +mkdir -p src/app/api/chat +mkdir -p src/components +``` + +### 🔑 環境変数の設定 + +`.env.local`ファイルを作成し、必要な環境変数を設定します: + +```bash +# Claude API +ANTHROPIC_API_KEY=your_anthropic_api_key_here + +# JPYC設定 +JPYC_NETWORK=polygon +JPYC_RPC_URL=https://polygon-rpc.com + +# ウォレット設定(テスト用) +WALLET_PRIVATE_KEY=your_test_wallet_private_key_here + +# アプリケーション設定 +NEXT_PUBLIC_APP_URL=http://localhost:3000 +``` + +**重要**: +- `.env.local`は`.gitignore`に含まれていることを確認してください +- 本番環境では、秘密鍵を環境変数として安全に管理してください + +### 🧪 セットアップの確認 + +開発サーバーを起動して、セットアップが正しく完了したか確認します: + +```bash +npm run dev +``` + +ブラウザで`http://localhost:3000`を開き、Next.jsのデフォルトページが表示されることを確認してください。 + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンでは、MCPサーバーの実装を始めます! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md new file mode 100644 index 00000000..1eae2ec2 --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md @@ -0,0 +1,28 @@ +--- +title: MCPサーバーの基礎実装 +--- + +### 🔌 MCP サーバーの実装 + +このセクションでは、JPYC操作のためのMCPサーバーを実装します。 + +### 📝 MCPサーバーの骨組み作成 + +`src/lib/mcp/server.ts`ファイルを作成し、MCPサーバーの基本構造を実装します。 + +(実装内容はここに追加予定) + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンに進みましょう! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md new file mode 100644 index 00000000..b95ac29c --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md @@ -0,0 +1,24 @@ +--- +title: JPYC残高確認ツールの実装 +--- + +### 💰 残高確認ツールの実装 + +このレッスンでは、JPYC残高を確認するMCPツールを実装します。 + +(実装内容はここに追加予定) + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンに進みましょう! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md new file mode 100644 index 00000000..9429f982 --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md @@ -0,0 +1,24 @@ +--- +title: JPYC送金ツールの実装 +--- + +### 📤 送金ツールの実装 + +このレッスンでは、JPYCを送金するMCPツールを実装します。 + +(実装内容はここに追加予定) + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンに進みましょう! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-4.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-4.md new file mode 100644 index 00000000..b5efc100 --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-4.md @@ -0,0 +1,24 @@ +--- +title: トランザクション履歴ツールの実装 +--- + +### 📊 トランザクション履歴ツールの実装 + +このレッスンでは、JPYC取引履歴を取得するMCPツールを実装します。 + +(実装内容はここに追加予定) + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +これでセクション3は完了です!次のセクションでは、MCPをMastraに組み込みます。 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-1.md new file mode 100644 index 00000000..146dda59 --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-1.md @@ -0,0 +1,28 @@ +--- +title: Mastraエージェントの作成 +--- + +### 🤖 Mastra エージェントの作成 + +このセクションでは、MCPサーバーをMastraフレームワークに組み込み、AI Agentを完成させます。 + +### 📝 エージェントの定義 + +`src/lib/mastra/agent.ts`ファイルを作成し、JPYC操作を支援するAI Agentを定義します。 + +(実装内容はここに追加予定) + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンに進みましょう! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-2.md new file mode 100644 index 00000000..3e91a922 --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-2.md @@ -0,0 +1,24 @@ +--- +title: MCPサーバーの統合 +--- + +### 🔌 MCP サーバーの統合 + +このレッスンでは、作成したMCPサーバーをMastraエージェントに統合します。 + +(実装内容はここに追加予定) + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンに進みましょう! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md new file mode 100644 index 00000000..55c5053c --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md @@ -0,0 +1,24 @@ +--- +title: API Routeの実装 +--- + +### 🌐 API Route の実装 + +このレッスンでは、Next.js API Routeを実装し、フロントエンドからMastraエージェントを利用できるようにします。 + +(実装内容はここに追加予定) + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +これでセクション4は完了です!次のセクションでは、フロントエンドを実装します。 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md new file mode 100644 index 00000000..86931eb9 --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md @@ -0,0 +1,28 @@ +--- +title: チャットインターフェースの実装 +--- + +### 💬 チャットインターフェースの実装 + +このセクションでは、ユーザーがAI Agentと対話するためのチャットインターフェースを実装します。 + +### 🎨 UIコンポーネントの作成 + +`src/components/ChatInterface.tsx`ファイルを作成し、チャット画面を実装します。 + +(実装内容はここに追加予定) + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンに進みましょう! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md new file mode 100644 index 00000000..db3888eb --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md @@ -0,0 +1,24 @@ +--- +title: メッセージ送信機能の実装 +--- + +### 📨 メッセージ送信機能の実装 + +このレッスンでは、ユーザーのメッセージをAI Agentに送信する機能を実装します。 + +(実装内容はここに追加予定) + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンに進みましょう! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-3.md new file mode 100644 index 00000000..b5218501 --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-3.md @@ -0,0 +1,24 @@ +--- +title: ストリーミングレスポンスの実装 +--- + +### ⚡️ ストリーミングレスポンスの実装 + +このレッスンでは、AI Agentからのレスポンスをリアルタイムでストリーミング表示する機能を実装します。 + +(実装内容はここに追加予定) + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +次のレッスンに進みましょう! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md new file mode 100644 index 00000000..3b6217cb --- /dev/null +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md @@ -0,0 +1,61 @@ +--- +title: アプリケーションの完成とテスト +--- + +### 🎉 アプリケーションの完成とテスト + +このレッスンでは、アプリケーションを完成させ、動作確認を行います。 + +### ✅ 最終確認 + +以下の機能が正しく動作することを確認します: + +1. **残高確認**:「残高を教えて」と聞いてJPYC残高が表示される +2. **送金処理**:「〇〇に△△JPYC送って」と指示して送金が実行される +3. **取引履歴**:「取引履歴を表示して」と聞いて履歴が表示される + +(詳細なテスト手順はここに追加予定) + +### 🎊 プロジェクト完了 + +おめでとうございます!AI Agent × JPYC チャットアプリが完成しました。 + +このプロジェクトを通じて、以下のスキルを習得しました: + +- JPYCとステーブルコインの理解 +- AI Agentの実装方法 +- MCPプロトコルの活用 +- Mastraフレームワークの使い方 +- Web3とAIの統合 + +### 🌍 プロジェクトをアップグレードする + +[UNCHAIN](https://unchain.tech/)のプロジェクトは[UNCHAIN License](https://github.com/unchain-tech/UNCHAIN-projects/blob/main/LICENSE)により運用されています。 + +プロジェクトに参加していて、「こうすればもっと分かりやすいのに!」「これは間違っている!」と思ったら、ぜひ`pull request`を送ってください。 + +### 🚀 次のステップ + +このアプリケーションをさらに改善するアイデア: + +1. **複数ウォレット対応**:複数のウォレットを管理できるようにする +2. **トランザクション通知**:送金完了時にプッシュ通知を送る +3. **定期送金機能**:毎月自動で送金するスケジュール機能 +4. **マルチチェーン対応**:Polygon以外のチェーンもサポート +5. **音声入力**:音声でAI Agentに指示できる機能 +6. **グラフ表示**:残高や取引履歴をグラフで可視化 + +### 🙋‍♂️ 質問する + +ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 + +ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ + +1. 質問が関連しているセクション番号とレッスン番号 +2. 何をしようとしていたか +3. エラー文をコピー&ペースト +4. エラー画面のスクリーンショット + +--- + +プロジェクト完了おめでとうございます!次のプロジェクトもお楽しみに! From 088f3f4de7973f652d451781a8b8a5a3ae1a065f Mon Sep 17 00:00:00 2001 From: Mameta29 Date: Mon, 3 Nov 2025 16:50:59 +0900 Subject: [PATCH 02/10] update section0 --- .../AI-Agent-JPYC-ChatApp/section-0/lesson-1.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-0/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-0/lesson-1.md index 755efb3e..c5b57ba9 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-0/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-0/lesson-1.md @@ -4,9 +4,9 @@ title: プロジェクトの概要 ### 👋 AI Agent × JPYC チャットアプリへようこそ -このプロジェクトでは、AI AgentとJPYC(日本円ステーブルコイン)を組み合わせた革新的なチャットアプリケーションを構築します。 +このプロジェクトでは、AI AgentとJPYC(日本円ステーブルコイン)を組み合わせたインタラクティブなチャットアプリケーションを構築します。 -AI Agentが自律的にJPYCを使った送金や残高確認などの操作を行える、次世代のWeb3アプリケーションを体験しましょう。 +AI Agentが自律的にJPYCを使った送金や残高確認などの操作を行える、次世代のAI×Web3のアプリケーションを体験しましょう。 ### 🎯 このプロジェクトで学べること @@ -56,18 +56,17 @@ JPYCは日本円と1:1でペッグされたステーブルコインです。価 ### 📚 前提知識 -このプロジェクトを始める前に、以下の基礎知識があると理解がスムーズです: +このプロジェクトを始める前に、以下の基礎知識があると理解がスムーズですが、なくても開発できます!: - JavaScriptまたはTypeScriptの基本文法 -- React.jsの基礎 +- React.jsやNext.jsの基礎 - ブロックチェーンとウォレットの基本概念 -- (必須ではないが望ましい)Next.jsの経験 ### 🚀 プロジェクトの流れ このプロジェクトは、以下の5つのセクションで構成されています: -**セクション1:座学** +**セクション1:** JPYCやAI Agent、MCP、Mastraなどの基礎知識を学びます。 **セクション2:セットアップ** @@ -77,7 +76,7 @@ JPYCやAI Agent、MCP、Mastraなどの基礎知識を学びます。 JPYC操作のためのMCPサーバーを実装します。 **セクション4:MCPの組み込み** -MastraフレームワークにMCPを統合し、AI Agentに機能を追加します。 +MastraフレームワークにMCPを統合し、AI AgentにJPYC操作機能を追加します。 **セクション5:フロントエンドの実装** Next.jsでユーザーインターフェースを構築し、アプリケーションを完成させます。 @@ -93,7 +92,7 @@ Next.jsでユーザーインターフェースを構築し、アプリケーシ ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ From f2733d3de0be17ff362cf6c795103032f7baea57 Mon Sep 17 00:00:00 2001 From: Mameta29 Date: Tue, 4 Nov 2025 07:29:58 +0900 Subject: [PATCH 03/10] about JPYC --- .../section-1/lesson-1.md | 50 +++++++------------ 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md index 9c420e7c..bcf6116d 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md @@ -4,26 +4,30 @@ title: JPYCについて ### 💴 JPYC とは? -JPYC(JPY Coin)は、日本円と1:1でペッグされた**ステーブルコイン**です。 +JPYC(JPY Coin)は、日本円と1:1でペッグされた**日本円ステーブルコイン**です。 -ステーブルコインとは、法定通貨(この場合は日本円)の価値に連動するように設計された暗号資産のことを指します。 +2025年8月18日に、JPYC株式会社は資金決済法第37条に基づく**資金移動業者(第二種)**の登録を取得しました(関東財務局長 第00099号)。これは**国内初となる日本円建ステーブルコイン発行にかかるライセンス取得**であり、2025年10月27日より正式に発行が開始されています。 + +JPYCは法的に**電子決済手段**として認定されており、1 JPYC = 1円での償還が保証されています。ステーブルコインとは、法定通貨(この場合は日本円)の価値に連動するように設計された電子決済手段です。 + +詳細は[JPYC公式サイト](https://jpyc.co.jp/)をご覧ください。 ### 🔑 JPYC の特徴 -**1. 価格の安定性** +**1. 価格の安定性と償還保証** -JPYCは常に1 JPYC = 1円の価値を維持するように設計されています。ビットコインやイーサリアムのような価格変動がないため、日常的な決済や送金に適しています。 +JPYCは常に1 JPYC = 1円の価値を維持するように設計されています。電子決済手段として認定されたことで、1 JPYC = 1円での日本円への償還が保証されています。ビットコインやイーサリアムのような価格変動がないため、日常的な決済や送金に適しています。 **2. 高速かつ低コストな送金** -従来の銀行振込と比較して、JPYCを使った送金は: +従来の銀行振込と比較して、JPYCを使った送金は下記の特徴があります: - 24時間365日いつでも送金可能 - 数秒〜数分で着金 - 低い手数料(ブロックチェーンの手数料のみ) **3. プログラマビリティ** -スマートコントラクトと組み合わせることで、自動送金や条件付き決済などの複雑な処理を実装できます。 +JPYCはERC20規格(イーサリアム互換)のトークンの拡張として発行されており、スマートコントラクトと組み合わせることで、自動送金や条件付き決済などの複雑な処理を実装できます。 **4. 透明性とトレーサビリティ** @@ -36,12 +40,8 @@ JPYCは複数のブロックチェーンで発行されています: - **Ethereum**(イーサリアム) - **Polygon**(ポリゴン) - **Avalanche**(アバランチ) -- **Gnosis Chain**(ノーシスチェーン) -- その他 - -このプロジェクトでは、**Polygon**ネットワーク上のJPYCを使用します。Polygonは、低い手数料と高速な取引処理が特徴です。 -### 🎯 JPYC のユースケース +### 🎯 JPYC のユースケース例 **決済・送金** - ECサイトでの商品購入 @@ -53,45 +53,31 @@ JPYCは複数のブロックチェーンで発行されています: - 流動性プール - イールドファーミング -**Web3アプリケーション** +**web3アプリケーション** - NFTマーケットプレイスでの取引 - ゲーム内通貨 - DAO(分散型自律組織)での運用 ### 📖 JPYC の仕組み -JPYCは**前払式支払手段**として発行されています。 +JPYCは**電子決済手段**として発行されており、資金移動業者としてのライセンスに基づいて運営されています。 -1. ユーザーが日本円をJPYC発行事業者に預ける +1. ユーザーが日本円をJPYC株式会社に預ける 2. 預けた金額と同額のJPYCが発行される 3. ユーザーはJPYCを自由に使用・送金できる -4. JPYCを日本円に戻したい場合、払い戻しを申請できる - -この仕組みにより、1 JPYC = 1円の価値が担保されています。 - -### 🔐 セキュリティと信頼性 - -**規制対応** - -JPYCは日本の法規制に準拠した形で運営されています。前払式支払手段として登録されており、安心して利用できます。 - -**監査** - -JPYCのスマートコントラクトは、第三者機関による監査を受けています。コードの安全性が確認されています。 - -**準備金の透明性** +4. JPYCを日本円に戻したい場合、1 JPYC = 1円で償還を申請できる -発行されているJPYCの総額に対して、同額以上の日本円が準備金として保管されています。準備金の状況は定期的に公開されています。 +JPYCの発行と償還は、専用プラットフォーム「JPYC EX」を通じて行われます。 ### 💡 このプロジェクトでの JPYC の役割 このプロジェクトでは、AI AgentがJPYCを使って以下の操作を行います: +- **総供給量確認**:JPYCの流通額を取得 - **残高確認**:ユーザーのJPYC残高を取得 - **送金処理**:指定されたアドレスにJPYCを送金 -- **取引履歴の取得**:過去のJPYC取引履歴を確認 -AI Agentが自然言語での指示を理解し、これらの操作を自動的に実行することで、より直感的なWeb3体験を提供します。 +AI Agentが自然言語での指示を理解し、これらの操作を自動的に実行することで、より直感的なweb3体験を提供します。 ### 🙋‍♂️ 質問する From dfe9baf2e45a4cb6bf3e70f18ae17d754bdc645f Mon Sep 17 00:00:00 2001 From: Mameta29 Date: Tue, 4 Nov 2025 07:56:58 +0900 Subject: [PATCH 04/10] about JPYC SDK --- .../section-1/lesson-2.md | 229 +++++------------- 1 file changed, 61 insertions(+), 168 deletions(-) diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-2.md index 6a0f326d..534abe7e 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-2.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-2.md @@ -4,52 +4,40 @@ title: JPYC SDKについて ### 🛠 JPYC SDK とは? -JPYC SDKは、JPYCを簡単に操作するためのTypeScript/JavaScriptライブラリです。 +JPYC SDK(`@jpyc/sdk-core`)は、JPYCコントラクトと簡単にやり取りできるNodeJS向けのインタフェースです。 -ブロックチェーンの複雑な処理を抽象化し、開発者が簡単にJPYC機能を実装できるようにします。 +ブロックチェーンの複雑な処理を抽象化し、開発者が簡単にJPYC機能を実装できるようになっています。このSDKは[JPYC v2コントラクト](https://github.com/jcam1/JPYCv2)に対応しており、複数のブロックチェーンネットワークをサポートしています。 -### ✨ JPYC SDK の主な機能 +### ✨ JPYC SDK の今回のプロジェクトでの使用例 -**1. 残高照会** +**1. 総供給量取得** -ユーザーのJPYC残高を取得します。 +JPYCの総供給量を取得します。 ```typescript -const balance = await jpycClient.getBalance(address); -console.log(`残高: ${balance} JPYC`); +const totalSupply = await jpyc.totalSupply(); +console.log(`総供給量: ${totalSupply.toString()}`); ``` -**2. 送金処理** +**2. 残高取得** -指定したアドレスにJPYCを送金します。 - -```typescript -const tx = await jpycClient.transfer( - recipientAddress, - amount -); -console.log(`送金完了: ${tx.hash}`); -``` - -**3. トランザクション履歴の取得** - -過去の取引履歴を取得します。 +ユーザーのJPYC残高を取得します。 ```typescript -const transactions = await jpycClient.getTransactionHistory( - address -); +const balance = await jpyc.balanceOf(address); +console.log(`残高: ${balance} JPYC`); ``` -**4. 承認(Approve)処理** +**3. 送金処理** -スマートコントラクトがJPYCを操作できるように承認します。 +指定したアドレスにJPYCを送金します。 ```typescript -const approveTx = await jpycClient.approve( - spenderAddress, +const tx = await jpyc.transfer( + recipientAddress, amount ); +console.log(`送金完了: ${tx.hash}`); ``` ### 📦 JPYC SDK のインストール @@ -57,163 +45,62 @@ const approveTx = await jpycClient.approve( JPYC SDKは、npmまたはyarnを使ってインストールできます: ```bash -npm install @jpyc/sdk -``` +# npm +npm i @jpyc/sdk-core -または - -```bash -yarn add @jpyc/sdk +# または yarn +yarn add @jpyc/sdk-core ``` ### 🔧 JPYC SDK の初期化 -JPYC SDKを使用するには、まず初期化が必要です: +JPYC SDKを使用するには、以下の4ステップで初期化を行います: ```typescript -import { JPYCClient } from '@jpyc/sdk'; -import { ethers } from 'ethers'; - -// ウォレットプロバイダーを作成 -const provider = new ethers.JsonRpcProvider(RPC_URL); -const wallet = new ethers.Wallet(PRIVATE_KEY, provider); +import { JPYC, SdkClient } from '@jpyc/sdk-core'; -// JPYC クライアントを初期化 -const jpycClient = new JPYCClient({ - network: 'polygon', // 使用するネットワーク - signer: wallet, // 署名用のウォレット +// 1. SdkClientインスタンスを初期化 +const sdkClient = new SdkClient({ + chainId: 137, // Polygon PoS + rpcUrl: 'YOUR_RPC_ENDPOINT_URL', }); -``` - -### 🌐 サポートするネットワーク - -JPYC SDKは、複数のブロックチェーンネットワークに対応しています: - -- `ethereum` - イーサリアムメインネット -- `polygon` - Polygon(旧Matic)ネットワーク -- `avalanche` - Avalanche C-Chain -- `gnosis` - Gnosis Chain - -このプロジェクトでは、**Polygonネットワーク**を使用します。 - -### 💰 残高確認の詳細 - -残高確認は、最も基本的な操作です: - -```typescript -// 残高を取得(Wei単位) -const balanceWei = await jpycClient.getBalance(userAddress); - -// 人間が読める形式に変換(JPYC単位) -const balanceJPYC = ethers.formatUnits(balanceWei, 18); - -console.log(`残高: ${balanceJPYC} JPYC`); -``` - -JPYCは18桁の小数点精度を持つため、`formatUnits`関数で変換します。 - -### 📤 送金処理の詳細 - -送金処理では、以下のパラメータを指定します: -```typescript -const tx = await jpycClient.transfer( - recipientAddress, // 送金先アドレス - amount // 送金額(Wei単位) -); - -// トランザクションの完了を待つ -await tx.wait(); - -console.log(`送金完了: ${tx.hash}`); -``` - -**注意点**: -- `amount`はWei単位で指定する必要があります -- 送金には少額のMATIC(Polygonの手数料用トークン)が必要です - -### 📊 トランザクション履歴の取得 - -過去の取引履歴を取得し、分析することができます: - -```typescript -const transactions = await jpycClient.getTransactionHistory( - userAddress, - { - startBlock: 0, // 検索開始ブロック - endBlock: 'latest', // 検索終了ブロック - limit: 100 // 取得件数の上限 - } -); - -transactions.forEach(tx => { - console.log(` - 日時: ${new Date(tx.timestamp * 1000).toLocaleString()} - 送信元: ${tx.from} - 送信先: ${tx.to} - 金額: ${ethers.formatUnits(tx.value, 18)} JPYC - `); +// 2. 秘密鍵からEOA(外部所有アカウント)を設定 +const account = sdkClient.configurePrivateKeyAccount({ + privateKey: 'YOUR_PRIVATE_KEY', }); -``` - -### 🔐 セキュリティのベストプラクティス - -**1. 秘密鍵の管理** - -秘密鍵は絶対に公開してはいけません: - -```typescript -// ❌ 悪い例:秘密鍵をハードコーディング -const PRIVATE_KEY = "0x1234..."; -// ✅ 良い例:環境変数から読み込む -const PRIVATE_KEY = process.env.PRIVATE_KEY; -``` - -**2. 送金額の検証** - -送金前に金額を検証します: - -```typescript -// 残高を確認 -const balance = await jpycClient.getBalance(senderAddress); - -if (balance < amount) { - throw new Error('残高不足です'); -} +// 3. アカウントを使ってウォレットクライアントを設定 +const client = sdkClient.configureClient({ + account, +}); -// 送金処理 -await jpycClient.transfer(recipientAddress, amount); +// 4. クライアントを使ってJPYCインスタンスを初期化 +const jpyc = new JPYC({ + env: 'prod', // 'prod' または 'local' + contractType: 'jpyc', // 'jpyc' または 'jpycPrepaid' + localContractAddress: undefined, // ローカルネットワーク使用時のみ設定 + client, +}); ``` -**3. エラーハンドリング** - -ブロックチェーン操作は失敗する可能性があるため、適切なエラーハンドリングが重要です: +**重要なポイント**: -```typescript -try { - const tx = await jpycClient.transfer(recipientAddress, amount); - await tx.wait(); - console.log('送金成功'); -} catch (error) { - console.error('送金失敗:', error.message); - // エラーに応じた適切な処理 -} -``` +- SDKは環境変数を暗黙的に使用しません。秘密鍵などの機密データは安全にロードしてください +- `chainId`には後述のサポートされているチェーンIDを使用します +- 本番環境では`env: 'prod'`、ローカル開発では`env: 'local'`を指定します -### 🧪 テストネット環境 +### 🌐 サポートするネットワーク -開発中は、テストネット環境を使用することを推奨します: +JPYC SDKは、JPYCが発行されている3つのチェーンとテストネットでサポートされています。 +- Ethereum Mainnet +- Ethereum Sepolia Testnet +- Polygon PoS Mainnet +- Polygon Amoy Testnet +- Avalanche Mainnet +- Avalanche Fuji Testnet -```typescript -// Polygon Mumbai テストネット -const jpycClient = new JPYCClient({ - network: 'polygon-mumbai', - signer: wallet, -}); -``` - -テストネットでは、実際の資産を使わずに開発・テストができます。 +このプロジェクトでは、**各テストネット**を使用します。 ### 📚 このプロジェクトでの JPYC SDK の役割 @@ -221,11 +108,17 @@ const jpycClient = new JPYCClient({ MCPサーバーがJPYC SDKを使用してブロックチェーン操作を行い、AI Agentがそれを自然言語で制御します。 -具体的な統合方法は、セクション3とセクション4で詳しく学びます。 +それではAI AgentやMCPについて次のセクション以降で学んでいきましょう! + +### 📖 参考資料 + +- [JPYC SDK公式ドキュメント](https://jcam1.github.io/sdks/) +- [JPYC SDK GitHub リポジトリ](https://github.com/jcam1/sdks) +- [JPYC v2コントラクト](https://github.com/jcam1/JPYCv2) ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ From 32e172a1b0c33a25b18662c330c1766f61710b7c Mon Sep 17 00:00:00 2001 From: Mameta29 Date: Tue, 4 Nov 2025 08:24:55 +0900 Subject: [PATCH 05/10] =?UTF-8?q?=E3=83=81=E3=83=A3=E3=83=B3=E3=83=8D?= =?UTF-8?q?=E3=83=AB=E3=81=AE=E5=A4=89=E6=9B=B4=E3=81=A8AI=20agent?= =?UTF-8?q?=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../section-1/lesson-1.md | 2 +- .../section-1/lesson-3.md | 33 +++---------------- .../section-1/lesson-4.md | 8 ++--- .../section-1/lesson-5.md | 6 ++-- .../section-2/lesson-1.md | 2 +- .../section-3/lesson-1.md | 2 +- .../section-3/lesson-2.md | 2 +- .../section-3/lesson-3.md | 2 +- .../section-3/lesson-4.md | 4 +-- .../section-4/lesson-1.md | 2 +- .../section-4/lesson-2.md | 2 +- .../section-4/lesson-3.md | 4 +-- .../section-5/lesson-1.md | 8 ++--- .../section-5/lesson-2.md | 2 +- .../section-5/lesson-3.md | 2 +- .../section-5/lesson-4.md | 10 +++--- 16 files changed, 34 insertions(+), 57 deletions(-) diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md index bcf6116d..b6792ae6 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md @@ -81,7 +81,7 @@ AI Agentが自然言語での指示を理解し、これらの操作を自動的 ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-3.md index 01e6048d..e5daa2f9 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-3.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-3.md @@ -9,7 +9,7 @@ AI Agentとは、**自律的にタスクを実行できる人工知能システ 従来のチャットボットと異なり、AI Agentは以下のような特徴を持ちます: - 目標を理解し、それを達成するための計画を立てる -- 外部ツールやAPIを使用して情報を取得したり、アクションを実行する +- 外部ツール(今回ではJPYC SDKなど)やAPIを使用して情報を取得したり、アクションを実行する - 状況に応じて柔軟に判断し、行動を調整する - 複数のステップを経て、複雑なタスクを完遂する @@ -81,13 +81,11 @@ AI Agentは、以下のようなループで動作します: 2. 計画の立案 Step 1: 太郎さんのウォレットアドレスを取得 - Step 2: 現在の残高を確認 - Step 3: 送金を実行 - Step 4: 結果をユーザーに報告 + Step 2: 送金を実行 + Step 3: 結果をユーザーに報告 3. ツールの実行 - アドレス帳ツールで太郎さんのアドレスを検索 - - 残高確認ツールで残高をチェック - 送金ツールで送金を実行 4. 結果の評価 @@ -103,10 +101,8 @@ AI Agentは、以下のようなループで動作します: AI Agentは、様々な分野で活用されています: -**Web3・ブロックチェーン** +**web3・ブロックチェーン** - 自動取引(トレーディングBot) -- DAO運営の補助 -- NFTの自動管理 **業務自動化** - カスタマーサポート @@ -146,30 +142,11 @@ LLMの出力は常に正確とは限りません。 → **解決策**:重要な操作には確認ステップを挟む、出力の検証 -### 🌟 このプロジェクトでの AI Agent - -このプロジェクトでは、以下の機能を持つAI Agentを構築します: - -**理解できること** -- JPYC残高の確認依頼 -- JPYC送金の指示 -- 取引履歴の照会依頼 - -**実行できること** -- ウォレットの残高確認 -- 指定アドレスへのJPYC送金 -- トランザクション履歴の取得と表示 - -**判断できること** -- 送金が可能かどうか(残高チェック) -- アドレスの有効性 -- エラー時の適切な対応 - 次のレッスンでは、AI AgentとツールをつなぐMCP(Model Context Protocol)について学びます! ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md index 7d53ce13..e891426b 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md @@ -29,13 +29,13 @@ await blockchainRPC.sendTransaction(tx); **課題3:標準化の欠如** -AI Agentとツール間のインターフェースに統一性がなく、開発者ごとに異なる実装がされていました。 +AI Agentとツール間のインタフェースに統一性がなく、開発者ごとに異なる実装がされていました。 ### ✨ MCP が解決すること MCPは、これらの課題を以下のように解決します: -**1. 統一されたインターフェース** +**1. 統一されたインタフェース** すべてのツールが同じプロトコルで通信します。 @@ -281,11 +281,11 @@ MCPは、様々なフレームワークやツールと統合できます: 3. **フロントエンドからの利用**(セクション5) - Next.jsアプリからMastra経由でMCPを呼び出し - - ユーザーインターフェースの実装 + - ユーザーインタフェースの実装 ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md index a48b8ce7..837c8888 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md @@ -363,11 +363,11 @@ const results = await Promise.all([ 4. **API提供** - Next.jsのAPI Routeから利用 - - フロントエンドとのインターフェース + - フロントエンドとのインタフェース ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ @@ -378,4 +378,4 @@ const results = await Promise.all([ --- -これでセクション1(座学)は完了です!次のセクションでは、実際に開発環境をセットアップしていきます。 +これでセクション1(座学)は完了です! 次のセクションでは、実際に開発環境をセットアップしていきます。 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-2/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-2/lesson-1.md index f93668ef..4df81c10 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-2/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-2/lesson-1.md @@ -128,7 +128,7 @@ npm run dev ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md index 1eae2ec2..daaed7bb 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md @@ -14,7 +14,7 @@ title: MCPサーバーの基礎実装 ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md index b95ac29c..0f09f08d 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md @@ -10,7 +10,7 @@ title: JPYC残高確認ツールの実装 ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md index 9429f982..9ca69859 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md @@ -10,7 +10,7 @@ title: JPYC送金ツールの実装 ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-4.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-4.md index b5efc100..a772a10b 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-4.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-4.md @@ -10,7 +10,7 @@ title: トランザクション履歴ツールの実装 ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ @@ -21,4 +21,4 @@ title: トランザクション履歴ツールの実装 --- -これでセクション3は完了です!次のセクションでは、MCPをMastraに組み込みます。 +これでセクション3は完了です! 次のセクションでは、MCPをMastraに組み込みます。 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-1.md index 146dda59..c05be70a 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-1.md @@ -14,7 +14,7 @@ title: Mastraエージェントの作成 ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-2.md index 3e91a922..9f60cf7e 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-2.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-2.md @@ -10,7 +10,7 @@ title: MCPサーバーの統合 ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md index 55c5053c..8ef9fe9a 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md @@ -10,7 +10,7 @@ title: API Routeの実装 ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ @@ -21,4 +21,4 @@ title: API Routeの実装 --- -これでセクション4は完了です!次のセクションでは、フロントエンドを実装します。 +これでセクション4は完了です! 次のセクションでは、フロントエンドを実装します。 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md index 86931eb9..8b97e2eb 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md @@ -1,10 +1,10 @@ --- -title: チャットインターフェースの実装 +title: チャットインタフェースの実装 --- -### 💬 チャットインターフェースの実装 +### 💬 チャットインタフェースの実装 -このセクションでは、ユーザーがAI Agentと対話するためのチャットインターフェースを実装します。 +このセクションでは、ユーザーがAI Agentと対話するためのチャットインタフェースを実装します。 ### 🎨 UIコンポーネントの作成 @@ -14,7 +14,7 @@ title: チャットインターフェースの実装 ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md index db3888eb..ac62ede8 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md @@ -10,7 +10,7 @@ title: メッセージ送信機能の実装 ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-3.md index b5218501..adb2f8ce 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-3.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-3.md @@ -10,7 +10,7 @@ title: ストリーミングレスポンスの実装 ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md index 3b6217cb..ea9a8ec3 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md @@ -11,14 +11,14 @@ title: アプリケーションの完成とテスト 以下の機能が正しく動作することを確認します: 1. **残高確認**:「残高を教えて」と聞いてJPYC残高が表示される -2. **送金処理**:「〇〇に△△JPYC送って」と指示して送金が実行される +2. **送金処理**:「〇〇にXX JPYC送って」と指示して送金が実行される 3. **取引履歴**:「取引履歴を表示して」と聞いて履歴が表示される (詳細なテスト手順はここに追加予定) ### 🎊 プロジェクト完了 -おめでとうございます!AI Agent × JPYC チャットアプリが完成しました。 +おめでとうございます! AI Agent × JPYCチャットアプリが完成しました。 このプロジェクトを通じて、以下のスキルを習得しました: @@ -26,7 +26,7 @@ title: アプリケーションの完成とテスト - AI Agentの実装方法 - MCPプロトコルの活用 - Mastraフレームワークの使い方 -- Web3とAIの統合 +- web3とAIの統合 ### 🌍 プロジェクトをアップグレードする @@ -47,7 +47,7 @@ title: アプリケーションの完成とテスト ### 🙋‍♂️ 質問する -ここまでの作業で何かわからないことがある場合は、Discordの`#ai`で質問をしてください。 +ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ @@ -58,4 +58,4 @@ title: アプリケーションの完成とテスト --- -プロジェクト完了おめでとうございます!次のプロジェクトもお楽しみに! +プロジェクト完了おめでとうございます! 次のプロジェクトもお楽しみに! From 4d3c827ee56762516cd32a126656e813203dc59b Mon Sep 17 00:00:00 2001 From: Mameta29 Date: Tue, 4 Nov 2025 09:06:48 +0900 Subject: [PATCH 06/10] update MCP&Mastra MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../lesson-1.md => section-1/lesson-0.md} | 14 +- .../section-1/lesson-4.md | 280 ++++-------- .../section-1/lesson-5.md | 431 +++++++----------- 3 files changed, 256 insertions(+), 469 deletions(-) rename docs/AI/AI-Agent-JPYC-ChatApp/{section-0/lesson-1.md => section-1/lesson-0.md} (91%) diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-0/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-0.md similarity index 91% rename from docs/AI/AI-Agent-JPYC-ChatApp/section-0/lesson-1.md rename to docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-0.md index c5b57ba9..b77f9992 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-0/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-0.md @@ -6,7 +6,7 @@ title: プロジェクトの概要 このプロジェクトでは、AI AgentとJPYC(日本円ステーブルコイン)を組み合わせたインタラクティブなチャットアプリケーションを構築します。 -AI Agentが自律的にJPYCを使った送金や残高確認などの操作を行える、次世代のAI×Web3のアプリケーションを体験しましょう。 +AI Agentが自律的にJPYCを使った送金や残高確認などの操作を行える、次世代のAI×web3のアプリケーションを体験しましょう。 ### 🎯 このプロジェクトで学べること @@ -22,7 +22,7 @@ AI Agentが自律的にJPYCを使った送金や残高確認などの操作を 3. **MCP(Model Context Protocol)の理解と実装** - MCPとは何か - - AI AgentにWeb3機能を追加する方法 + - AI Agentにweb3機能を追加する方法 4. **フルスタック開発スキル** - バックエンド:TypeScript、Node.js @@ -40,9 +40,9 @@ AI Agentが自律的にJPYCを使った送金や残高確認などの操作を ### 🌟 このプロジェクトの魅力 -**Web3 × AI の融合** +**web3 × AI の融合** -従来のWeb3アプリケーションでは、ユーザーが手動でウォレットを操作する必要がありました。しかし、AI Agentを組み合わせることで、自然言語での指示だけでブロックチェーン操作が可能になります。 +従来のweb3アプリケーションでは、ユーザーが手動でウォレットを操作する必要がありました。しかし、AI Agentを組み合わせることで、自然言語での指示だけでブロックチェーン操作が可能になります。 **実用的なステーブルコイン体験** @@ -56,7 +56,7 @@ JPYCは日本円と1:1でペッグされたステーブルコインです。価 ### 📚 前提知識 -このプロジェクトを始める前に、以下の基礎知識があると理解がスムーズですが、なくても開発できます!: +このプロジェクトを始める前に、以下の基礎知識があると理解がスムーズですが、なくても開発できます! : - JavaScriptまたはTypeScriptの基本文法 - React.jsやNext.jsの基礎 @@ -79,13 +79,13 @@ JPYC操作のためのMCPサーバーを実装します。 MastraフレームワークにMCPを統合し、AI AgentにJPYC操作機能を追加します。 **セクション5:フロントエンドの実装** -Next.jsでユーザーインターフェースを構築し、アプリケーションを完成させます。 +Next.jsでユーザーインタフェースを構築し、アプリケーションを完成させます。 ### 🎓 このプロジェクトを終えると プロジェクト完了後、あなたは以下のことができるようになります: -- AI AgentとWeb3を組み合わせたアプリケーションを開発できる +- AI Agentとweb3を組み合わせたアプリケーションを開発できる - MCPを使ってAI Agentに独自の機能を追加できる - JPYCを使った実用的な決済アプリを構築できる - Mastraフレームワークを活用したAI Agent開発ができる diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md index e891426b..32896984 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md @@ -6,7 +6,7 @@ title: MCPについて MCP(Model Context Protocol)は、**AI Agentとツールやデータソースをつなぐための標準化されたプロトコル**です。 -Anthropic社によって開発され、AI Agentが外部のツールやサービスを簡単に利用できるようにします。 +Anthropic社によって開発され、AI Agentが外部のツールやサービスを統一的な方法で利用できるようにします。 ### 🤔 なぜ MCP が必要なのか? @@ -17,7 +17,7 @@ AI Agentを開発する際、以下のような課題がありました: 各ツールやAPIごとに異なる実装方法を学ぶ必要がありました。 ```typescript -// それぞれのツールで異なる実装が必要 +// それぞれのツールで異なる実装が必要だった await weatherAPI.getCurrentWeather(location); await databaseClient.query(sql); await blockchainRPC.sendTransaction(tx); @@ -33,187 +33,94 @@ AI Agentとツール間のインタフェースに統一性がなく、開発者 ### ✨ MCP が解決すること -MCPは、これらの課題を以下のように解決します: +MCPは**統一されたインタフェース**を提供し、すべてのツールが同じプロトコルで通信できるようにします。 -**1. 統一されたインタフェース** - -すべてのツールが同じプロトコルで通信します。 - -```typescript -// MCPを使えば、すべてのツールが同じ方法で使える -await mcpServer.callTool('get_weather', { location }); -await mcpServer.callTool('query_database', { sql }); -await mcpServer.callTool('send_jpyc', { to, amount }); -``` - -**2. プラグアンドプレイ** - -一度作成したMCPサーバーは、どのAI Agentフレームワークでも使用できます。 - -**3. セキュリティと制御** - -MCPは、ツールへのアクセス制御や権限管理を標準化します。 +これにより: +- 一度作成したツールを複数のAI Agentで再利用できる +- 新しいツールを追加する際の学習コストが低い +- AI Agentフレームワーク間でツールを共有できる ### 🏗 MCP のアーキテクチャ -MCPは、以下のコンポーネントで構成されます: +MCPは、**サーバー**と**クライアント**の2つのコンポーネントで構成されます: -**MCPサーバー** +#### MCPサーバー(Server) -ツールやデータソースをホストする側です。 +ツールやデータソースを提供する側です。 -```typescript -// MCPサーバーの例 -const server = new MCPServer({ - name: 'jpyc-tools', - version: '1.0.0', - tools: [ - { - name: 'get_balance', - description: 'JPYC残高を取得する', - inputSchema: { - type: 'object', - properties: { - address: { type: 'string' } - } - }, - handler: async ({ address }) => { - // 残高取得の実装 - } - } - ] -}); -``` +**役割:** +- ツールの定義と実装 +- ツールのメタデータ(名前、説明、パラメータ)の公開 +- ツールの実行と結果の返却 -**MCPクライアント** +#### MCPクライアント(Client) -AI AgentがMCPサーバーと通信するための部分です。 +AI Agentからツールを利用する側です。 -```typescript -// MCPクライアントの使用例 -const client = new MCPClient({ - serverUrl: 'http://localhost:3000' -}); - -// ツールの呼び出し -const result = await client.callTool('get_balance', { - address: '0x123...' -}); -``` - -**プロトコル** - -サーバーとクライアント間の通信ルールです。JSON-RPCベースの標準化されたメッセージフォーマットを使用します。 +**役割:** +- MCPサーバーへの接続 +- 利用可能なツールの取得 +- ツールの呼び出しリクエスト送信 +- 実行結果の受け取り ### 📡 MCP の通信フロー MCPの典型的な通信フローは以下の通りです: ``` -1. AI Agent: ユーザーから「残高を教えて」という指示を受ける +1. ユーザー → AI Agent + 「残高を教えて」 -2. AI Agent → MCP Client: 適切なツールを選択 - "get_balance ツールを使う" +2. AI Agent → MCP Client + 適切なツールを選択 -3. MCP Client → MCP Server: ツール呼び出しリクエスト +3. MCP Client → MCP Server + ツール呼び出しリクエスト { - "tool": "get_balance", - "parameters": { - "address": "0x123..." - } + "tool": "jpyc_balance", + "parameters": { "address": "0x123..." } } -4. MCP Server: ツールを実行 - - JPYC SDKを使って残高を取得 - - 結果をフォーマット - -5. MCP Server → MCP Client: 実行結果を返す +4. MCP Server + ツールを実行して結果を返す { - "success": true, - "data": { - "balance": "1000", - "symbol": "JPYC" - } + "balance": "1000", + "chainName": "Ethereum Sepolia" } -6. MCP Client → AI Agent: 結果を渡す - -7. AI Agent → User: 結果を自然言語で報告 - "あなたの残高は1,000 JPYCです" +5. AI Agent → ユーザー + 「Ethereum Sepoliaチェーンの残高は1,000 JPYCです」 ``` -### 🛠 MCP サーバーの構造 +### 🛠 ツールの構成要素 -MCPサーバーは、以下の要素を定義します: +MCPのツールは、以下の要素で構成されます: -**1. ツール(Tools)** +**1. 識別子(ID)** +- ツールを一意に識別する名前 +- 例:`jpyc_balance`、`jpyc_transfer` -AI Agentが実行できる具体的な機能です。 +**2. 説明(Description)** +- AI Agentがツールの用途を理解するための説明文 +- 例:「指定したアドレスのJPYC残高を照会します」 -```typescript -{ - name: 'send_jpyc', - description: 'JPYCを送金する', - inputSchema: { - type: 'object', - properties: { - to: { - type: 'string', - description: '送金先アドレス' - }, - amount: { - type: 'string', - description: '送金額' - } - }, - required: ['to', 'amount'] - }, - handler: async ({ to, amount }) => { - // 送金処理の実装 - } -} -``` +**3. 入力スキーマ(Input Schema)** +- ツールが受け取るパラメータの定義 +- データ型、必須/任意、説明などを含む -**2. リソース(Resources)** +**4. 実行ロジック(Execute)** +- 実際の処理を行う関数 +- パラメータを受け取り、結果を返す -AI Agentがアクセスできるデータです。 - -```typescript -{ - uri: 'jpyc://transactions/history', - name: 'Transaction History', - description: 'JPYC取引履歴', - mimeType: 'application/json' -} -``` - -**3. プロンプト(Prompts)** - -AI Agentに提供するコンテキスト情報です。 - -```typescript -{ - name: 'jpyc_context', - description: 'JPYC操作のためのコンテキスト', - arguments: [ - { - name: 'userAddress', - description: 'ユーザーのウォレットアドレス', - required: true - } - ] -} -``` - -### 🎯 MCP の利点 +### 💡 MCP の利点 **開発者にとって** -- ツールの実装が簡単になる -- 既存のツールを再利用できる -- 標準化されたテストとデバッグが可能 +- ツールを一度実装すれば、複数のプロジェクトで再利用できる +- 標準化されたインタフェースで開発が容易 +- テストとデバッグがしやすい **AI Agentにとって** -- 多様なツールに一貫した方法でアクセスできる +- 多様なツールに統一的な方法でアクセスできる - ツールの機能を自動的に理解できる - エラーハンドリングが統一される @@ -221,67 +128,38 @@ AI Agentに提供するコンテキスト情報です。 - より多機能なAI Agentを利用できる - 信頼性の高いサービスを受けられる -### 🔐 MCP のセキュリティ - -MCPは、以下のセキュリティ機能を提供します: - -**認証と認可** -```typescript -const server = new MCPServer({ - auth: { - type: 'bearer', - token: process.env.MCP_AUTH_TOKEN - } -}); -``` - -**入力検証** -```typescript -inputSchema: { - type: 'object', - properties: { - amount: { - type: 'string', - pattern: '^[0-9]+(\.[0-9]+)?$', // 数値のみ許可 - maximum: '10000' // 最大値の制限 - } - } -} -``` - -**レート制限** -```typescript -const server = new MCPServer({ - rateLimit: { - windowMs: 60000, // 1分 - maxRequests: 10 // 最大10リクエスト - } -}); -``` - ### 🌐 MCP のエコシステム -MCPは、様々なフレームワークやツールと統合できます: +MCPは、様々なAI Agentフレームワークで利用できます: -- **AI Agentフレームワーク**:LangChain、Mastra、AutoGPTなど -- **LLMプロバイダー**:Claude、GPT-4、Geminiなど -- **開発ツール**:VS Code拡張、デバッガーなど +- **Mastra**: TypeScriptベースのモダンなフレームワーク +- **LangChain**: Python/TypeScriptの人気フレームワーク +- **AutoGPT**: 自律型Agentフレームワーク -### 💡 このプロジェクトでの MCP の役割 +また、様々なLLMプロバイダーと組み合わせて使用できます: +- Claude(Anthropic) +- GPT-4(OpenAI) +- Gemini(Google) -このプロジェクトでは、以下のようにMCPを使用します: +### 📝 このプロジェクトでの MCP -1. **MCPサーバーの実装**(セクション3) - - JPYC操作のためのツールを定義 - - JPYC SDKと連携する実装 +このプロジェクトでは、以下のような構成でMCPを活用します: -2. **Mastraとの統合**(セクション4) - - MastraフレームワークにMCPサーバーを接続 - - AI AgentからJPYCツールを利用可能にする - -3. **フロントエンドからの利用**(セクション5) - - Next.jsアプリからMastra経由でMCPを呼び出し - - ユーザーインタフェースの実装 +**MCPサーバー** +- JPYC操作のためのツールを提供 +- HTTP/SSEで通信 +- ポート3001で起動 + +**MCPクライアント**(Mastraのレッスンで実装) +- Mastraフレームワーク経由でMCPサーバーに接続 +- AI Agentにツールを提供 + +**提供するツール:** +1. `jpyc_balance` - 残高照会 +2. `jpyc_transfer` - 送金 +3. `jpyc_switch_chain` - チェーン切り替え +4. `jpyc_get_current_chain` - 現在のチェーン取得 +5. `jpyc_total_supply` - 総供給量照会 ### 🙋‍♂️ 質問する diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md index 837c8888..349ee89a 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md @@ -4,367 +4,276 @@ title: Mastraについて ### 🎭 Mastra とは? -Mastraは、**AI Agentを簡単に構築できるモダンなTypeScriptフレームワーク**です。 +Mastraは、**AI Agentを簡単に構築できるTypeScriptフレームワーク**です。 -複雑なAI Agentのロジックを抽象化し、開発者が本質的な機能の実装に集中できるようにします。 +前のレッスンで学んだMCPプロトコルをネイティブサポートし、開発者が本質的な機能の実装に集中できるようにします。 ### ✨ Mastra の特徴 **1. シンプルなAPI** -Mastraは、直感的で使いやすいAPIを提供します。 - -```typescript -import { Mastra } from '@mastra/core'; - -const mastra = new Mastra({ - agents: [myAgent], - tools: [myTool], -}); -``` +直感的で使いやすいAPIでAI Agentを作成できます。 **2. TypeScript完全対応** 型安全な開発が可能で、エディタの補完機能をフル活用できます。 -**3. 柔軟な統合** +**3. MCP統合** -様々なLLMプロバイダー(Claude、OpenAI、Geminiなど)をサポートします。 +前のレッスンで学んだMCPサーバーと簡単に接続できます。 -**4. MCP対応** +**4. 複数のLLMに対応** -MCPプロトコルをネイティブサポートし、外部ツールを簡単に統合できます。 +Claude、OpenAI、Geminiなど、様々なLLMプロバイダーをサポートします。 -### 🏗 Mastra のアーキテクチャ +### 🔌 MCP との関係 -Mastraは、以下の主要コンポーネントで構成されます: +Mastraは、MCPプロトコルを実装する**AI Agentフレームワーク**です: -**Agentモジュール** +``` +[ユーザー] + ↓ +[Mastra Agent] ← AI Agentフレームワーク + ↓ +[Mastra MCP Client] ← MCPクライアントの実装 + ↓ +[MCP Server] ← 前のレッスンで学んだMCPサーバー + ↓ +[JPYC SDK] +``` + +### 🤖 Agent の作成 -AI Agentの振る舞いを定義します。 +Mastraでは、`Agent`クラスを使ってAI Agentを作成します: ```typescript -import { Agent } from '@mastra/core'; +import { Agent } from '@mastra/core/agent'; const jpycAgent = new Agent({ - name: 'JPYC Agent', + name: 'JPYC Assistant', + model: gpt4oMiniModel, + tools: async () => { + // MCPサーバーからツールを取得 + const tools = await jpycMCPClient.getTools(); + return tools; + }, instructions: ` - あなたはJPYC操作を支援するAIアシスタントです。 - ユーザーの指示に従って、送金や残高確認を行います。 + あなたはJPYC操作をサポートするAIアシスタントです。 + ... `, - model: { - provider: 'anthropic', - name: 'claude-3-5-sonnet', - toolChoice: 'auto', - }, }); ``` -**Toolモジュール** +**主要な設定項目:** + +- `name`: Agentの名前 +- `model`: 使用するLLMモデル +- `tools`: 利用可能なツール(関数で動的に取得) +- `instructions`: Agentへのシステムプロンプト -AI Agentが使用できるツールを定義します。 +### 📝 Instructions の役割 + +`instructions`は、AI Agentの振る舞いを定義する重要な要素です: ```typescript -import { createTool } from '@mastra/core'; - -const getBalanceTool = createTool({ - id: 'get_balance', - description: 'JPYC残高を取得する', - inputSchema: z.object({ - address: z.string().describe('ウォレットアドレス'), - }), - execute: async ({ context }) => { - const { address } = context; - // 残高取得の実装 - }, -}); -``` +instructions: ` + あなたはJPYC操作をサポートするAIアシスタントです。 -**Workflowモジュール** + 対応テストネット: Ethereum Sepolia, Avalanche Fuji -複数のステップからなる複雑な処理を定義します。 + 以下の操作が可能です: + - 残高照会 + - 送金処理 + - チェーン切り替え -```typescript -import { createWorkflow } from '@mastra/core'; - -const sendJPYCWorkflow = createWorkflow({ - name: 'send_jpyc', - triggerSchema: z.object({ - to: z.string(), - amount: z.string(), - }), -}) - .step('check_balance') - .step('validate_address') - .step('execute_transfer') - .commit(); + ## 回答スタイル: + - カジュアルで親しみやすい会話調 + - 絵文字は使わない +` ``` -### 🤖 Agent の作成 +### 🔗 MCP クライアントの作成 -Mastraでは、Agentを簡単に作成できます: +MastraでMCPサーバーに接続するには、`MCPClient`を使用します: ```typescript -import { Agent } from '@mastra/core'; - -const agent = new Agent({ - name: 'JPYC Assistant', - instructions: ` - あなたはJPYC(日本円ステーブルコイン)の操作を - 支援するAIアシスタントです。 - - 以下の操作をサポートします: - - 残高確認 - - 送金処理 - - 取引履歴の表示 +import { MCPClient } from '@mastra/mcp'; - ユーザーに対して親切で分かりやすい説明を心がけてください。 - `, - model: { - provider: 'anthropic', - name: 'claude-3-5-sonnet', - toolChoice: 'auto', - }, - tools: { - getBalance, - sendJPYC, - getHistory, - }, +// MCPサーバーに接続 +const jpycMCPClient = new MCPClient({ + name: 'jpyc-sdk', + url: 'http://localhost:3001', // MCPサーバーのURL }); + +// ツールを取得 +const tools = await jpycMCPClient.getTools(); ``` -### 🛠 Tool の作成 +### 🔄 動的ツール取得 -Toolは、AI Agentが実行できる具体的な機能です: +Agentにツールを提供する際、**関数形式**で動的に取得します: ```typescript -import { createTool } from '@mastra/core'; -import { z } from 'zod'; - -const sendJPYCTool = createTool({ - id: 'send_jpyc', - description: '指定したアドレスにJPYCを送金する', - inputSchema: z.object({ - to: z.string().describe('送金先のウォレットアドレス'), - amount: z.string().describe('送金額(JPYC単位)'), - }), - execute: async ({ context }) => { - const { to, amount } = context; - - try { - // JPYC送金処理 - const tx = await jpycClient.transfer(to, amount); - - return { - success: true, - message: `${amount} JPYCを${to}に送金しました`, - txHash: tx.hash, - }; - } catch (error) { - return { - success: false, - message: `送金に失敗しました: ${error.message}`, - }; - } +const jpycAgent = new Agent({ + name: 'JPYC Assistant', + model: gpt4oMiniModel, + + // ツールを動的に取得する関数 + tools: async () => { + const { jpycMCPClient } = await import('@/lib/mastra/mcp/client'); + const tools = await jpycMCPClient.getTools(); + return tools; }, }); ``` ### 💬 Agent の実行 -作成したAgentを実行するのは簡単です: +#### 通常実行(generate) ```typescript -// テキスト入力で実行 -const response = await agent.generate('残高を教えて'); +const response = await jpycAgent.generate( + '残高を教えて', + { threadId: 'unique-thread-id' } +); + console.log(response.text); +// → "Ethereum Sepoliaチェーンの残高は1,000 JPYCです" +``` + +#### ストリーミング実行(stream) + +```typescript +const stream = await jpycAgent.stream( + '太郎に100JPYC送って', + { threadId: 'unique-thread-id' } +); -// ストリーミング実行 -const stream = await agent.stream('100 JPYC送って'); for await (const chunk of stream) { - console.log(chunk.text); + if (chunk.type === 'text') { + process.stdout.write(chunk.text); + } } ``` -### 🔄 Workflow の活用 +### 🔄 このプロジェクトでの処理フロー -Workflowを使うと、複数のステップを順序立てて実行できます: +実際のアプリケーションでの全体的な流れ: -```typescript -import { createWorkflow } from '@mastra/core'; -import { z } from 'zod'; - -const transferWorkflow = createWorkflow({ - name: 'jpyc_transfer', - triggerSchema: z.object({ - recipientAddress: z.string(), - amount: z.string(), - }), -}) - .step('validate_inputs', async ({ context }) => { - // 入力値の検証 - const { recipientAddress, amount } = context.machineContext; - - if (!ethers.isAddress(recipientAddress)) { - throw new Error('無効なアドレスです'); - } - - return { valid: true }; - }) - .step('check_balance', async ({ context }) => { - // 残高確認 - const balance = await jpycClient.getBalance(userAddress); - const required = ethers.parseUnits(context.machineContext.amount, 18); - - if (balance < required) { - throw new Error('残高不足です'); - } - - return { sufficient: true }; - }) - .step('execute_transfer', async ({ context }) => { - // 送金実行 - const { recipientAddress, amount } = context.machineContext; - const tx = await jpycClient.transfer(recipientAddress, amount); - - return { - txHash: tx.hash, - status: 'success', - }; - }) - .commit(); - -// Workflowの実行 -const result = await transferWorkflow.execute({ - triggerData: { - recipientAddress: '0x123...', - amount: '100', - }, -}); +``` +1. ユーザー入力 + ↓ +2. Next.js API Route (/api/chat) + ↓ +3. Mastra Agent (jpycAgent.stream()) + ↓ +4. Mastra MCP Client (getTools()) + ↓ +5. MCP Server (http://localhost:3001) + ↓ +6. JPYC SDK → Blockchain + ↓ +7. 結果を逆順で返す + ↓ +8. フロントエンドに表示 ``` -### 🔌 MCP との統合 - -MastraはMCPをネイティブサポートしています: +**API Route の実装例:** ```typescript -import { Mastra } from '@mastra/core'; -import { MCPClient } from '@mastra/mcp'; +// src/app/api/chat/route.ts +import { jpycAgent } from '@/lib/mastra/agent'; -// MCPクライアントを作成 -const mcpClient = new MCPClient({ - serverUrl: 'http://localhost:3000', -}); +export async function POST(req: Request) { + const { message, threadId } = await req.json(); -// Mastraインスタンスを作成 -const mastra = new Mastra({ - agents: [jpycAgent], - mcpServers: { - jpycServer: mcpClient, - }, -}); + // Agentをストリーミングモードで実行 + const stream = await jpycAgent.stream(message, { threadId }); -// MCPサーバーのツールが自動的にAgentで利用可能になる + return new Response(stream, { + headers: { 'Content-Type': 'text/event-stream' }, + }); +} ``` -### 📊 コンテキスト管理 +### 📊 スレッド管理 -Mastraは、会話のコンテキストを自動的に管理します: +Mastraは会話のコンテキストを「スレッド」として管理します: ```typescript -// 会話の開始 -const thread = await agent.createThread(); +// 新しいスレッドを作成 +const threadId = crypto.randomUUID(); -// メッセージの送信(コンテキストを保持) -await agent.generate('私の残高は?', { threadId: thread.id }); +// 最初のメッセージ +await jpycAgent.generate('私の残高は?', { threadId }); // → "1,000 JPYCです" -await agent.generate('半分を太郎さんに送って', { threadId: thread.id }); -// → 太郎さんに500 JPYCを送金します(コンテキストから金額を推測) +// 同じスレッドで続けて会話(コンテキストを保持) +await jpycAgent.generate('半分を太郎さんに送って', { threadId }); +// → コンテキストから「500 JPYC」と推測して送金 ``` -### 🎨 カスタマイズ +### 🎯 モデルの設定 -Mastraは、様々な側面でカスタマイズ可能です: +Mastraは複数のLLMプロバイダーをサポートします: -**モデルのカスタマイズ** ```typescript -const agent = new Agent({ - model: { - provider: 'anthropic', - name: 'claude-3-5-sonnet', - toolChoice: 'auto', - temperature: 0.7, - maxTokens: 1000, - }, +// OpenAI GPT-4o-mini +import { createOpenAI } from '@ai-sdk/openai'; + +const openai = createOpenAI({ + apiKey: process.env.OPENAI_API_KEY, }); + +export const gpt4oMiniModel = openai('gpt-4o-mini'); ``` -**エラーハンドリング** ```typescript -const agent = new Agent({ - onError: async (error, context) => { - console.error('Agent error:', error); - // カスタムエラー処理 - }, +// Anthropic Claude +import { createAnthropic } from '@ai-sdk/anthropic'; + +const anthropic = createAnthropic({ + apiKey: process.env.ANTHROPIC_API_KEY, }); + +export const claude = anthropic('claude-3-5-sonnet-20241022'); ``` -**ログ記録** +### 🚀 このプロジェクトでの構成 + +**1. MCPクライアント**(`src/lib/mastra/mcp/client.ts`) ```typescript -const mastra = new Mastra({ - logger: { - level: 'debug', - transport: customLogger, - }, +import { MCPClient } from '@mastra/mcp'; + +export const jpycMCPClient = new MCPClient({ + name: 'jpyc-sdk', + url: 'http://localhost:3001', }); ``` -### 🚀 パフォーマンス最適化 - -Mastraは、以下のパフォーマンス最適化機能を提供します: - -**キャッシング** +**2. Agent**(`src/lib/mastra/agent.ts`) ```typescript -const agent = new Agent({ - cache: { - enabled: true, - ttl: 300, // 5分 +import { Agent } from '@mastra/core/agent'; + +export const jpycAgent = new Agent({ + name: 'JPYC Assistant', + model: gpt4oMiniModel, + tools: async () => { + const tools = await jpycMCPClient.getTools(); + return tools; }, + instructions: '...', }); ``` -**並列実行** +**3. API Route**(`src/app/api/chat/route.ts`) ```typescript -// 複数のツールを並列実行 -const results = await Promise.all([ - agent.executeTool('get_balance', { address: addr1 }), - agent.executeTool('get_balance', { address: addr2 }), - agent.executeTool('get_balance', { address: addr3 }), -]); +export async function POST(req: Request) { + const stream = await jpycAgent.stream(message, { threadId }); + return new Response(stream); +} ``` -### 💡 このプロジェクトでの Mastra の役割 - -このプロジェクトでは、Mastraを以下のように活用します: - -1. **Agentの定義** - - JPYC操作を支援するAgentを作成 - - 適切な指示とモデル設定 - -2. **Toolの実装** - - JPYC残高確認ツール - - JPYC送金ツール - - 取引履歴取得ツール - -3. **MCPとの統合** - - セクション3で作成するMCPサーバーを接続 - - AI Agentから自動的にMCPツールを利用 - -4. **API提供** - - Next.jsのAPI Routeから利用 - - フロントエンドとのインタフェース - ### 🙋‍♂️ 質問する ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 From 68ee430fd44cc6edb487647bea540ca8c1c11e88 Mon Sep 17 00:00:00 2001 From: Mameta29 Date: Tue, 4 Nov 2025 11:23:51 +0900 Subject: [PATCH 07/10] =?UTF-8?q?section3-5=E4=BD=9C=E6=88=90=20MCP?= =?UTF-8?q?=E3=83=84=E3=83=BC=E3=83=AB,=20MCP=E3=82=B5=E3=83=BC=E3=83=90?= =?UTF-8?q?=E3=83=BC,=20=E3=83=95=E3=83=AD=E3=83=B3=E3=83=88=E3=82=A8?= =?UTF-8?q?=E3=83=B3=E3=83=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../section-3/lesson-1.md | 328 +++++++++- .../section-3/lesson-2.md | 379 ++++++++++- .../section-3/lesson-3.md | 277 +++++++- .../section-3/lesson-4.md | 24 - .../section-4/lesson-1.md | 107 +++- .../section-4/lesson-2.md | 128 +++- .../section-4/lesson-3.md | 233 ++++++- .../section-5/lesson-1.md | 264 +++++++- .../section-5/lesson-2.md | 333 +++++++++- .../section-5/lesson-3.md | 450 ++++++++++++- .../section-5/lesson-4.md | 591 +++++++++++++++++- 11 files changed, 3011 insertions(+), 103 deletions(-) delete mode 100644 docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-4.md diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md index daaed7bb..460c1ce4 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md @@ -1,16 +1,330 @@ --- -title: MCPサーバーの基礎実装 +title: JPYC SDK Wrapperの実装 --- -### 🔌 MCP サーバーの実装 +### 🔧 JPYC SDK Wrapper の実装 -このセクションでは、JPYC操作のためのMCPサーバーを実装します。 +このレッスンでは、JPYC SDKをMCPサーバーから利用しやすくするためのWrapperを実装します。 -### 📝 MCPサーバーの骨組み作成 +このWrapperは、JPYC SDK v2.0.0を使用してマルチチェーン対応(Ethereum Sepolia、Polygon Amoy、Avalanche Fuji)のJPYC操作を提供します。 -`src/lib/mcp/server.ts`ファイルを作成し、MCPサーバーの基本構造を実装します。 +### 📝 実装するファイル -(実装内容はここに追加予定) +`external/mcp/src/jpyc/sdk.ts`ファイルを作成し、以下のコードを記述します。 + +```typescript +import { JPYC, type IJPYC, SdkClient, type ISdkClient } from "@jpyc/sdk-core"; +import type { Hex } from "viem"; +import type { PrivateKeyAccount } from "viem/accounts"; + +// サポートするチェーン +export type SupportedChain = "sepolia" | "amoy" | "fuji"; + +// JPYC SDKで使用するチェーンIDのマッピング +const CHAIN_ID_MAP: Record = { + sepolia: 11155111, // Ethereum Sepolia + amoy: 80002, // Polygon Amoy + fuji: 43113, // Avalanche Fuji +}; + +const CHAIN_NAMES: Record = { + sepolia: "Ethereum Sepolia", + amoy: "Polygon Amoy", + fuji: "Avalanche Fuji", +}; + +// チェーンごとのRPC URL +const RPC_URLS: Record = { + sepolia: "https://ethereum-sepolia-rpc.publicnode.com", + amoy: "https://rpc-amoy.polygon.technology", + fuji: "https://api.avax-test.network/ext/bc/C/rpc", +}; + +// 現在選択されているチェーン(デフォルトはSepolia) +let _currentChain: SupportedChain = "sepolia"; +let _jpycInstance: IJPYC | null = null; +let _account: PrivateKeyAccount | null = null; + +/** + * JPYC SDKインスタンスを生成するメソッド + * @param chain + */ +function createJpycInstance(chain: SupportedChain) { + // 環境変数の検証 + if (!process.env.PRIVATE_KEY) { + throw new Error("PRIVATE_KEY environment variable is required"); + } + + const chainId = CHAIN_ID_MAP[chain]; + + // SdkClientの初期化 + const sdkClient: ISdkClient = new SdkClient({ + chainId, + rpcUrl: RPC_URLS[chain], + }); + + // アカウントの作成 + _account = sdkClient.configurePrivateKeyAccount({ + privateKey: process.env.PRIVATE_KEY as Hex, + }); + + // Clientの生成 + const client = sdkClient.configureClient({ + account: _account, + }); + + // JPYC SDKインスタンスの作成 + _jpycInstance = new JPYC({ + env: "prod", + contractType: "jpycPrepaid", + localContractAddress: undefined, + client, + }); +} + +/** + * JPYC SDKインスタンスを取得するメソッド + * @returns + */ +function getJpycInstance(): IJPYC { + if (!_jpycInstance) { + createJpycInstance(_currentChain); + } + return _jpycInstance!; +} + +/** + * チェーンを切り替える関数 + * @param chain + */ +export function switchChain(chain: SupportedChain): void { + if (!CHAIN_ID_MAP[chain]) { + throw new Error( + `Unsupported chain: ${chain}. Supported chains: sepolia, amoy, fuji`, + ); + } + _currentChain = chain; + // JPYC SDKインスタンスを再作成 + createJpycInstance(chain); +} + +/** + * 現在のチェーンを取得する関数 + * @returns + */ +export function getCurrentChain(): SupportedChain { + return _currentChain; +} + +/** + * チェーンの表示名を取得する関数 + * @param chain + * @returns + */ +export function getChainName(chain?: SupportedChain): string { + const targetChain = chain || _currentChain; + return CHAIN_NAMES[targetChain] || "Ethereum Sepolia"; +} + +/** + * 現在のアカウントアドレスを取得する関数 + * @returns + */ +export function getCurrentAddress(): Hex { + if (!_account) { + // アカウントが未初期化の場合、JPYC SDKインスタンスを初期化 + getJpycInstance(); + } + return _account!.address; +} + +/** + * JPYC操作インターフェース(JPYC SDKを使用) + */ +export const jpyc = { + /** + * 総供給量を取得するメソッド + * @returns + */ + async totalSupply(): Promise { + try { + const jpycInstance = getJpycInstance(); + // JPYC SDKのtotalSupply関数を呼び出す + const result = await jpycInstance.totalSupply(); + // numberをstringに変換して返す + return result.toString(); + } catch (error: any) { + console.error("[jpyc.totalSupply] Error:", error); + + // コントラクトが存在しない場合のエラーハンドリング + if ( + error.message?.includes("returned no data") || + error.message?.includes("0x") + ) { + const chainName = getChainName(_currentChain); + throw new Error( + `JPYCコントラクトが${chainName}にデプロイされていないか、アドレスが正しくありません。` + + `Ethereum Sepoliaでお試しください。`, + ); + } + + throw new Error(`Failed to get total supply: ${error.message}`); + } + }, + + /** + * JPYCの残高を取得するメソッド + * @param params + * @returns + */ + async balanceOf(params: { account: Hex }): Promise { + try { + const jpycInstance = getJpycInstance(); + // JPYC SDKのbalanceOf関数を呼び出す + const result = await jpycInstance.balanceOf({ account: params.account }); + // numberをstringに変換して返す + return result.toString(); + } catch (error: any) { + console.error("[jpyc.balanceOf] Error:", error); + + // コントラクトが存在しない場合のエラーハンドリング + if ( + error.message?.includes("returned no data") || + error.message?.includes("0x") + ) { + const chainName = getChainName(_currentChain); + throw new Error( + `JPYCコントラクトが${chainName}にデプロイされていないか、アドレスが正しくありません。` + + `現在のチェーンを確認してください。`, + ); + } + + throw new Error(`Failed to get balance: ${error.message}`); + } + }, + + /** + * JPYCを送金するメソッド + * @param params + * @returns + */ + async transfer(params: { to: Hex; value: number }): Promise { + try { + const jpycInstance = getJpycInstance(); + // JPYC SDKのtransfer関数を呼び出す + // SDKはnumberを受け取り、内部で適切に変換する + const hash = await jpycInstance.transfer({ + to: params.to, + value: params.value, + }); + + return hash; + } catch (error: any) { + console.error("[jpyc.transfer] Error:", error); + throw new Error(`Failed to transfer: ${error.message}`); + } + }, +}; +``` + +### 💡 コードの解説 + +このファイルは、JPYC SDK v2.0.0を使いやすくするためのラッパーです。主要なポイントを見ていきましょう。 + +#### 1. マルチチェーン対応 + +```typescript +const CHAIN_ID_MAP: Record = { + sepolia: 11155111, // Ethereum Sepolia + amoy: 80002, // Polygon Amoy + fuji: 43113, // Avalanche Fuji +}; +``` + +3つのテストネット(Ethereum Sepolia、Polygon Amoy、Avalanche Fuji)に対応しています。各チェーンのIDとRPC URLをマッピングすることで、簡単にチェーンを切り替えられます。 + +#### 2. モジュールレベルでの状態管理 + +```typescript +let _currentChain: SupportedChain = "sepolia"; +let _jpycInstance: IJPYC | null = null; +let _account: PrivateKeyAccount | null = null; +``` + +現在のチェーン、JPYCインスタンス、アカウント情報をモジュールレベルの変数で管理しています。これにより、同じMCPサーバープロセス内で状態を保持できます。 + +#### 3. JPYC SDK v2.0.0のAPI使用 + +```typescript +// SdkClientの初期化 +const sdkClient: ISdkClient = new SdkClient({ + chainId, + rpcUrl: RPC_URLS[chain], +}); + +// アカウントの作成 +_account = sdkClient.configurePrivateKeyAccount({ + privateKey: process.env.PRIVATE_KEY as Hex, +}); + +// Clientの生成 +const client = sdkClient.configureClient({ + account: _account, +}); + +// JPYC SDKインスタンスの作成 +_jpycInstance = new JPYC({ + env: "prod", + contractType: "jpycPrepaid", + localContractAddress: undefined, + client, +}); +``` + +JPYC SDK v2.0.0では、`SdkClient`を使ってチェーン接続を初期化します。その後、`configurePrivateKeyAccount()`でアカウントを作成し、`configureClient()`でクライアントを生成します。 + +このクライアントを使って`JPYC`インスタンスを作成することで、JPYCトークンの操作が可能になります。 + +#### 4. チェーン切り替え機能 + +```typescript +export function switchChain(chain: SupportedChain): void { + if (!CHAIN_ID_MAP[chain]) { + throw new Error( + `Unsupported chain: ${chain}. Supported chains: sepolia, amoy, fuji`, + ); + } + _currentChain = chain; + // JPYC SDKインスタンスを再作成 + createJpycInstance(chain); +} +``` + +`switchChain()`を呼び出すと、指定したチェーンに切り替わります。JPYC SDKインスタンスを再作成することで、新しいチェーンに接続できます。 + +#### 5. JPYC操作のインタフェース + +```typescript +export const jpyc = { + async totalSupply(): Promise { ... }, + async balanceOf(params: { account: Hex }): Promise { ... }, + async transfer(params: { to: Hex; value: number }): Promise { ... }, +}; +``` + +今回のプロジェクトでは3つの主要な操作を提供します: + +- **totalSupply()**: JPYCの総供給量を取得 +- **balanceOf()**: 指定したアドレスの残高を取得 +- **transfer()**: JPYCを送金 + +これらのメソッドは、内部でJPYC SDKを呼び出し、結果を適切な形式で返します。 + +### 🧪 動作確認 + +この段階では、まだMCPサーバーが完成していないため、動作確認はできません。 + +次のレッスンでMCPツールを実装し、その後MCPサーバーを起動することで、このWrapperが動作することを確認できます。 ### 🙋‍♂️ 質問する @@ -25,4 +339,4 @@ title: MCPサーバーの基礎実装 --- -次のレッスンに進みましょう! +次のレッスンでは、このWrapperを使用してMCPツールを実装します! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md index 0f09f08d..f69bd0f8 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md @@ -1,12 +1,381 @@ --- -title: JPYC残高確認ツールの実装 +title: MCPツールの実装 --- -### 💰 残高確認ツールの実装 +### 🛠 MCP ツールの実装 -このレッスンでは、JPYC残高を確認するMCPツールを実装します。 +このレッスンでは、前のレッスンで作成したJPYC SDK Wrapperを使用して、5つのMCPツールを実装します。 -(実装内容はここに追加予定) +MCPツールは、AI Agentが実行できる「関数」として機能します。各ツールは、AI Agentに対して「何ができるか」を説明し、パラメータを検証し、実際の処理を実行します。 + +### 📝 実装するファイル + +`external/mcp/src/tools.ts`ファイルを作成し、以下のコードを記述します。 + +```typescript +/** + * JPYC Tools for Mastra + * + * JPYC SDKの機能をMastraツールとして提供 + */ + +import { createTool } from "@mastra/core/tools"; +import { z } from "zod"; +import { + getChainName, + getCurrentAddress, + getCurrentChain, + jpyc, + type SupportedChain, + switchChain, +} from "./jpyc/sdk"; + +// エクスプローラーURLマッピング +const EXPLORER_URLS: Record = { + sepolia: "https://sepolia.etherscan.io/tx/", + amoy: "https://amoy.polygonscan.com/tx/", + fuji: "https://testnet.snowtrace.io/tx/", +}; + +/** + * JPYC残高照会ツール + * 指定したアドレスのJPYC残高を照会します(現在選択されているテストネット) + */ +export const jpycBalanceTool = createTool({ + id: "jpyc_balance", + description: + "指定したアドレスのJPYC残高を照会します(現在選択されているテストネット)。アドレスが指定されていない場合は、現在のウォレットアドレスの残高を返します。", + inputSchema: z.object({ + address: z + .string() + .optional() + .describe( + "残高を照会するEthereumアドレス(省略時は現在のウォレットアドレス)", + ), + }), + execute: async ({ context }) => { + try { + const { address } = context; + // 現在接続中のチェーン情報を取得 + const currentChain = getCurrentChain(); + const chainName = getChainName(currentChain); + + // アドレスが指定されていない場合は、現在のアカウントアドレスを使用 + const targetAddress = address || getCurrentAddress(); + const balanceString = await jpyc.balanceOf({ + account: targetAddress as `0x${string}`, + }); + + console.log( + `jpyc_balance: address=${targetAddress}, balance=${balanceString} JPYC`, + ); + + return { + success: true, + address: targetAddress, + balance: `${balanceString} JPYC`, + balanceRaw: balanceString, + chain: currentChain, + chainName: chainName, + }; + } catch (error: unknown) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + }, +}); + +/** + * JPYC送金ツール + * JPYCトークンを指定したアドレスに送金します(現在選択されているテストネット) + */ +export const jpycTransferTool = createTool({ + id: "jpyc_transfer", + description: + "JPYCトークンを指定したアドレスに送金します(現在選択されているテストネット)。例: 10 JPYCを0x123...に送る", + inputSchema: z.object({ + to: z.string().describe("送信先のEthereumアドレス (0xから始まる42文字)"), + amount: z.number().describe("送金額(JPYC単位、例: 10)"), + }), + execute: async ({ context }) => { + try { + const { to, amount } = context; + // 現在接続中のチェーン情報を取得 + const currentChain = getCurrentChain(); + const chainName = getChainName(currentChain); + + // SDKのtransferメソッドを呼び出してJPYCを送金する + const txHash = await jpyc.transfer({ + to: to as `0x${string}`, + value: amount, + }); + + const explorerUrl = EXPLORER_URLS[currentChain]; + + return { + success: true, + message: `✅ ${amount} JPYCを ${to} に送金しました(${chainName})`, + transactionHash: txHash, + explorerUrl: `${explorerUrl}${txHash}`, + chain: currentChain, + chainName: chainName, + }; + } catch (error: unknown) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + }, +}); + +/** + * チェーン切り替えツール + * JPYCを操作するテストネットを切り替えます + */ +export const jpycSwitchChainTool = createTool({ + id: "jpyc_switch_chain", + description: + "JPYCを操作するテストネットを切り替えます。対応チェーン: sepolia (Ethereum), amoy (Polygon), fuji (Avalanche)。ユーザーが「Sepoliaで」「Amoyに切り替えて」「Avalancheで実行」などと言った場合に使用します。", + inputSchema: z.object({ + chain: z + .enum(["sepolia", "amoy", "fuji"]) + .describe( + "切り替え先のチェーン: sepolia (Ethereum Sepolia), amoy (Polygon Amoy), fuji (Avalanche Fuji)", + ), + }), + execute: async ({ context }) => { + try { + const { chain } = context; + // 接続前のチェーンを取得 + const previousChain = getCurrentChain(); + // チェーンを切り替え + await switchChain(chain as SupportedChain); + + const newChainName = getChainName(chain as SupportedChain); + const previousChainName = getChainName(previousChain); + + return { + success: true, + message: `✅ チェーンを ${previousChainName} から ${newChainName} に切り替えました`, + previousChain: previousChain, + newChain: chain, + chainName: newChainName, + }; + } catch (error: unknown) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + }, +}); + +/** + * 現在のチェーン取得ツール + * 現在選択されているテストネットを取得します + */ +export const jpycGetCurrentChainTool = createTool({ + id: "jpyc_get_current_chain", + description: + "現在選択されているテストネットを取得します。ユーザーが「今どのチェーン?」「現在のネットワークは?」などと聞いた場合に使用します。", + inputSchema: z.object({}), + execute: async () => { + try { + // 現在接続中のチェーン情報を取得 + const currentChain = getCurrentChain(); + const chainName = getChainName(currentChain); + + return { + success: true, + chain: currentChain, + chainName: chainName, + address: getCurrentAddress(), + }; + } catch (error: unknown) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + }, +}); + +/** + * 総供給量照会ツール + * 現在選択されているテストネットでのJPYCの総供給量を照会します + */ +export const jpycTotalSupplyTool = createTool({ + id: "jpyc_total_supply", + description: + "現在選択されているテストネットでのJPYCの総供給量を照会します。ユーザーが「総供給量は?」「流通量を教えて」などと聞いた場合に使用します。", + inputSchema: z.object({}), + execute: async () => { + try { + // 現在接続中のチェーン情報を取得 + const currentChain = getCurrentChain(); + const chainName = getChainName(currentChain); + // SDKのtotalSupplyメソッドを呼び出して総供給量を取得する + const totalSupply = await jpyc.totalSupply(); + + return { + success: true, + totalSupply: `${totalSupply} JPYC`, + totalSupplyRaw: totalSupply, + chain: currentChain, + chainName: chainName, + }; + } catch (error: unknown) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + }, +}); + +/** + * すべてのJPYCツールをエクスポートする + */ +export const jpycTools = { + jpyc_balance: jpycBalanceTool, + jpyc_transfer: jpycTransferTool, + jpyc_switch_chain: jpycSwitchChainTool, + jpyc_get_current_chain: jpycGetCurrentChainTool, + jpyc_total_supply: jpycTotalSupplyTool, +}; +``` + +### 💡 コードの解説 + +このファイルでは、5つのMCPツールを定義しています。各ツールの構造と役割を見ていきましょう。 + +#### 1. MCPツールの基本構造 + +MCPツールは、Mastraの`createTool()`を使用して作成します。各ツールは以下の要素で構成されます: + +```typescript +createTool({ + id: "jpyc_balance", // ツールの一意な識別子 + description: "...", // AI Agentがツールの用途を理解するための説明 + inputSchema: z.object({...}), // パラメータの型定義(Zodスキーマ) + execute: async ({ context }) => {...} // 実際の処理を行う関数 +}) +``` + +#### 2. Zodスキーマによるパラメータ検証 + +```typescript +inputSchema: z.object({ + to: z.string().describe("送信先のEthereumアドレス (0xから始まる42文字)"), + amount: z.number().describe("送金額(JPYC単位、例: 10)"), +}), +``` + +Zodは、TypeScriptの型検証ライブラリです。`inputSchema`で定義したスキーマにより、ツールが受け取るパラメータの型が保証されます。 + +`describe()`メソッドは、AI Agentがパラメータの意味を理解するための説明を追加します。これにより、AIは自然言語の指示から適切なパラメータを抽出できます。 + +#### 3. descriptionの重要性 + +```typescript +description: + "JPYCトークンを指定したアドレスに送金します(現在選択されているテストネット)。例: 10 JPYCを0x123...に送る", +``` + +`description`は、AI Agentがこのツールをいつ使うべきかを判断するための重要な情報です。 + +例えば、ユーザーが「太郎に100JPYC送って」と言った場合、AIは: +1. この`description`を読んで「送金する」ツールであることを理解 +2. `inputSchema`を参照して、`to`(送信先)と`amount`(金額)が必要だと認識 +3. 適切なパラメータを抽出して`execute`を呼び出す + +という流れで動作します。 + +#### 4. 5つのツールの役割 + +**jpyc_balance(残高照会)** +```typescript +const targetAddress = address || getCurrentAddress(); +const balanceString = await jpyc.balanceOf({ + account: targetAddress as `0x${string}`, +}); +``` + +アドレスが指定されていない場合は、自分のアドレスの残高を返します。前のレッスンで作成したWrapperの`jpyc.balanceOf()`を呼び出します。 + +**jpyc_transfer(送金)** +```typescript +const txHash = await jpyc.transfer({ + to: to as `0x${string}`, + value: amount, +}); +``` + +JPYCを送金し、トランザクションハッシュを返します。ブロックチェーンエクスプローラーのURLも生成して返すことで、ユーザーがトランザクションを確認できるようにします。 + +**jpyc_switch_chain(チェーン切り替え)** +```typescript +await switchChain(chain as SupportedChain); +``` + +ユーザーが「Avalancheで実行して」と言った場合などに、チェーンを切り替えます。 + +**jpyc_get_current_chain(現在のチェーン取得)** +```typescript +const currentChain = getCurrentChain(); +const chainName = getChainName(currentChain); +``` + +「今どのチェーン?」という質問に答えるためのツールです。 + +**jpyc_total_supply(総供給量照会)** +```typescript +const totalSupply = await jpyc.totalSupply(); +``` + +JPYCの総供給量を取得します。 + +#### 5. エラーハンドリング + +```typescript +try { + // 処理 + return { + success: true, + // ...結果 + }; +} catch (error: unknown) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; +} +``` + +すべてのツールは、エラーが発生した場合に`success: false`を返します。これにより、AI Agentはエラーを適切にユーザーに伝えることができます。 + +#### 6. エクスポート + +```typescript +export const jpycTools = { + jpyc_balance: jpycBalanceTool, + jpyc_transfer: jpycTransferTool, + jpyc_switch_chain: jpycSwitchChainTool, + jpyc_get_current_chain: jpycGetCurrentChainTool, + jpyc_total_supply: jpycTotalSupplyTool, +}; +``` + +最後に、すべてのツールを1つのオブジェクトとしてエクスポートします。これにより、次のレッスンでMCPサーバーに簡単に登録できます。 + +### 🧪 動作確認 + +この段階では、まだMCPサーバーが起動していないため、動作確認はできません。 + +次のレッスンでMCPサーバーを実装・起動することで、これらのツールが動作することを確認できます。 ### 🙋‍♂️ 質問する @@ -21,4 +390,4 @@ title: JPYC残高確認ツールの実装 --- -次のレッスンに進みましょう! +次のレッスンでは、これらのツールを公開するMCPサーバーを実装します! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md index 9ca69859..5afaea1b 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md @@ -1,12 +1,279 @@ --- -title: JPYC送金ツールの実装 +title: MCPサーバーの起動 --- -### 📤 送金ツールの実装 +### 🚀 MCP サーバーの起動 -このレッスンでは、JPYCを送金するMCPツールを実装します。 +このレッスンでは、前の2つのレッスンで作成したJPYC SDK WrapperとMCPツールを公開するMCPサーバーを実装します。 -(実装内容はここに追加予定) +MCPサーバーは、HTTP/SSE(Server-Sent Events)プロトコルを使用して、AI Agentと通信します。 + +### 📝 実装するファイル + +`external/mcp/src/index.ts`ファイルを作成し、以下のコードを記述します。 + +```typescript +/** + * JPYC MCP Server - Standalone MCP Server + * + * このサーバーはJPYC SDKの機能をMCPプロトコル経由で公開します。 + * HTTP/SSEを使用して、MCPClientから接続できるようにします。 + * + * 学習用ポイント: + * 1. MCPServerを独立したプロセスとして実行 + * 2. HTTP/SSE経由でMCPClientと通信 + * 3. 実際のMCPプロトコルの使い方を学習 + */ + +import "dotenv/config"; +import { MCPServer } from "@mastra/mcp"; +import http from "node:http"; +import { jpycTools } from "./tools"; + +const PORT = process.env.MCP_PORT || 3001; + +/** + * JPYC MCP Server インスタンス + */ +const server = new MCPServer({ + name: "jpyc-sdk", + version: "1.0.0", + tools: jpycTools, +}); + +/** + * HTTPサーバーを作成してMCPServerを統合 + */ +const httpServer = http.createServer(async (req, res) => { + console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`); + + // CORSヘッダーを設定(Next.jsアプリからのアクセスを許可) + res.setHeader("Access-Control-Allow-Origin", "*"); + res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + res.setHeader("Access-Control-Allow-Headers", "Content-Type"); + + if (req.method === "OPTIONS") { + res.writeHead(200); + res.end(); + return; + } + + // ヘルスチェックエンドポイント + if (req.url === "/health" && req.method === "GET") { + res.writeHead(200, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ status: "ok", server: "jpyc-mcp-server" })); + return; + } + + // MCP SSEエンドポイント + try { + await server.startSSE({ + url: new URL(req.url || "", `http://localhost:${PORT}`), + ssePath: "/sse", + messagePath: "/message", + req, + res, + }); + } catch (error) { + console.error("MCP Server error:", error); + if (!res.headersSent) { + res.writeHead(500, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ error: "Internal server error" })); + } + } +}); + +// サーバー起動 +httpServer.listen(PORT, () => { + console.log(` +╔════════════════════════════════════════════════════════════╗ +║ ║ +║ 🚀 JPYC MCP Server is running! ║ +║ ║ +║ SSE Endpoint: http://localhost:${PORT}/sse ║ +║ Message Endpoint: http://localhost:${PORT}/message ║ +║ Health Check: http://localhost:${PORT}/health ║ +║ ║ +║ Available Tools: ║ +║ - jpyc_balance (残高照会) ║ +║ - jpyc_transfer (送金) ║ +║ - jpyc_switch_chain (チェーン切り替え) ║ +║ - jpyc_get_current_chain (現在のチェーン取得) ║ +║ - jpyc_total_supply (総供給量照会) ║ +║ ║ +╚════════════════════════════════════════════════════════════╝ + `); +}); + +// エラーハンドリング +httpServer.on("error", (error) => { + console.error("HTTP Server error:", error); + process.exit(1); +}); + +// graceful shutdown +process.on("SIGTERM", () => { + console.log("SIGTERM signal received: closing HTTP server"); + httpServer.close(() => { + console.log("HTTP server closed"); + process.exit(0); + }); +}); + +process.on("SIGINT", () => { + console.log("\nSIGINT signal received: closing HTTP server"); + httpServer.close(() => { + console.log("HTTP server closed"); + process.exit(0); + }); +}); +``` + +### 💡 コードの解説 + +このファイルは、MCPサーバーのエントリーポイントです。主要なポイントを見ていきましょう。 + +#### 1. 環境変数の読み込み + +```typescript +import "dotenv/config"; +``` + +最初に`dotenv/config`をインポートすることで、`.env`ファイルから環境変数を読み込みます。これにより、`PRIVATE_KEY`などの機密情報を安全に管理できます。 + +#### 2. MCPServerインスタンスの作成 + +```typescript +const server = new MCPServer({ + name: "jpyc-sdk", + version: "1.0.0", + tools: jpycTools, +}); +``` + +MastraのMCPServerを作成します。前のレッスンで作成した`jpycTools`をツールとして登録することで、AI Agentがこれらのツールを使用できるようになります。 + +#### 3. HTTPサーバーの作成 + +```typescript +const httpServer = http.createServer(async (req, res) => { + // リクエスト処理 +}); +``` + +Node.jsの標準モジュール`http`を使って、HTTPサーバーを作成します。MCPサーバーは、このHTTPサーバーを通じてクライアントと通信します。 + +#### 4. CORSヘッダーの設定 + +```typescript +res.setHeader("Access-Control-Allow-Origin", "*"); +res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); +res.setHeader("Access-Control-Allow-Headers", "Content-Type"); +``` + +CORS(Cross-Origin Resource Sharing)ヘッダーを設定することで、Next.jsアプリケーション(別のポートで動作)からMCPサーバーにアクセスできるようにします。 + +#### 5. ヘルスチェックエンドポイント + +```typescript +if (req.url === "/health" && req.method === "GET") { + res.writeHead(200, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ status: "ok", server: "jpyc-mcp-server" })); + return; +} +``` + +`/health`エンドポイントは、サーバーが正常に動作しているかを確認するために使用します。ブラウザで`http://localhost:3001/health`にアクセスすると、サーバーの状態を確認できます。 + +#### 6. SSE(Server-Sent Events)エンドポイント + +```typescript +await server.startSSE({ + url: new URL(req.url || "", `http://localhost:${PORT}`), + ssePath: "/sse", + messagePath: "/message", + req, + res, +}); +``` + +MCPプロトコルは、SSE(Server-Sent Events)を使用してリアルタイム通信を行います。 + +- **/sse**: クライアントがサーバーからのイベントを受信するエンドポイント +- **/message**: クライアントがサーバーにメッセージを送信するエンドポイント + +#### 7. Graceful Shutdown + +```typescript +process.on("SIGTERM", () => { + console.log("SIGTERM signal received: closing HTTP server"); + httpServer.close(() => { + console.log("HTTP server closed"); + process.exit(0); + }); +}); +``` + +`SIGTERM`や`SIGINT`(Ctrl+C)シグナルを受信したとき、サーバーを適切に終了します。これにより、リクエスト処理中にサーバーが強制終了されることを防ぎます。 + +### 🧪 動作確認 + +MCPサーバーを起動して、動作を確認しましょう。 + +#### 1. MCPサーバーの起動 + +ターミナルで以下のコマンドを実行します: + +```bash +pnpm mcp:dev +``` + +以下のような出力が表示されれば、MCPサーバーが正常に起動しています: + +``` +╔════════════════════════════════════════════════════════════╗ +║ ║ +║ 🚀 JPYC MCP Server is running! ║ +║ ║ +║ SSE Endpoint: http://localhost:3001/sse ║ +║ Message Endpoint: http://localhost:3001/message ║ +║ Health Check: http://localhost:3001/health ║ +║ ║ +║ Available Tools: ║ +║ - jpyc_balance (残高照会) ║ +║ - jpyc_transfer (送金) ║ +║ - jpyc_switch_chain (チェーン切り替え) ║ +║ - jpyc_get_current_chain (現在のチェーン取得) ║ +║ - jpyc_total_supply (総供給量照会) ║ +║ ║ +╚════════════════════════════════════════════════════════════╝ +``` + +#### 2. ヘルスチェック + +ブラウザで`http://localhost:3001/health`にアクセスします。 + +以下のJSONレスポンスが表示されれば、サーバーが正常に動作しています: + +```json +{ + "status": "ok", + "server": "jpyc-mcp-server" +} +``` + +#### 3. サーバーの停止 + +MCPサーバーを停止するには、ターミナルで`Ctrl+C`を押します。 + +``` +SIGINT signal received: closing HTTP server +HTTP server closed +``` + +これで、Section 3(MCPサーバーの実装)が完了しました! + +次のセクションでは、このMCPサーバーと通信するMastra Agentを実装していきます。 ### 🙋‍♂️ 質問する @@ -21,4 +288,4 @@ title: JPYC送金ツールの実装 --- -次のレッスンに進みましょう! +次のセクションでは、Mastra Agentを実装します! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-4.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-4.md deleted file mode 100644 index a772a10b..00000000 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-4.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: トランザクション履歴ツールの実装 ---- - -### 📊 トランザクション履歴ツールの実装 - -このレッスンでは、JPYC取引履歴を取得するMCPツールを実装します。 - -(実装内容はここに追加予定) - -### 🙋‍♂️ 質問する - -ここまでの作業で何かわからないことがある場合は、Discordの`#jpyc`で質問をしてください。 - -ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨ - -1. 質問が関連しているセクション番号とレッスン番号 -2. 何をしようとしていたか -3. エラー文をコピー&ペースト -4. エラー画面のスクリーンショット - ---- - -これでセクション3は完了です! 次のセクションでは、MCPをMastraに組み込みます。 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-1.md index c05be70a..dde4a944 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-1.md @@ -1,16 +1,109 @@ --- -title: Mastraエージェントの作成 +title: LLMモデルの設定 --- -### 🤖 Mastra エージェントの作成 +### 🤖 LLM モデルの設定 -このセクションでは、MCPサーバーをMastraフレームワークに組み込み、AI Agentを完成させます。 +このレッスンでは、AI Agentが使用するLLM(大規模言語モデル)を設定します。 -### 📝 エージェントの定義 +このプロジェクトでは、Claude、OpenAI、Geminiの3つのLLMプロバイダーをサポートします。環境変数に応じて、いずれかのモデルを選択できるようになっています。 -`src/lib/mastra/agent.ts`ファイルを作成し、JPYC操作を支援するAI Agentを定義します。 +### 📝 実装するファイル -(実装内容はここに追加予定) +`src/lib/mastra/model/index.ts`ファイルを作成し、以下のコードを記述します。 + +```typescript +import { anthropic } from "@ai-sdk/anthropic"; +import { google } from "@ai-sdk/google"; +import { createOpenAI } from "@ai-sdk/openai"; + +// Claude 3.5 Sonnetモデルを使用 +const claude = anthropic("claude-sonnet-4-0"); + +// Mastra用のOpenAIプロバイダーを作成 +const openai = createOpenAI({ + apiKey: process.env.OPENAI_API_KEY, +}); + +// gpt-4o-miniモデルを使用(安価で高速、推論トークンなし) +const gpt4oMiniModel = openai("gpt-4o-mini"); +const gemini = google("gemini-2.5-pro"); + +export { claude, gemini, gpt4oMiniModel }; +``` + +### 💡 コードの解説 + +このファイルは、AI Agentが使用するLLMモデルを設定します。主要なポイントを見ていきましょう。 + +#### 1. ai-sdkパッケージ + +```typescript +import { anthropic } from "@ai-sdk/anthropic"; +import { google } from "@ai-sdk/google"; +import { createOpenAI } from "@ai-sdk/openai"; +``` + +`ai-sdk`は、Vercel社が開発した統一LLM APIライブラリです。複数のLLMプロバイダー(Claude、OpenAI、Geminiなど)を同じインタフェースで扱えるようにします。 + +Mastraは、内部で`ai-sdk`を使用してLLMと通信します。 + +#### 2. Anthropic Claude + +```typescript +const claude = anthropic("claude-sonnet-4-0"); +``` + +Anthropic社のClaude 3.5 Sonnetモデルを使用します。このプロジェクトでは、Claudeを推奨モデルとして設定しています。 + +#### 3. OpenAI GPT-4o-mini + +```typescript +const openai = createOpenAI({ + apiKey: process.env.OPENAI_API_KEY, +}); + +const gpt4oMiniModel = openai("gpt-4o-mini"); +``` + +OpenAI社のGPT-4o-miniモデルを使用します。 + +#### 4. Google Gemini + +```typescript +const gemini = google("gemini-2.5-pro"); +``` + +Google社のGemini 2.5 Proモデルを使用します。 + +#### 5. エクスポート + +```typescript +export { claude, gemini, gpt4oMiniModel }; +``` + +3つのモデルをエクスポートすることで、次のレッスンでAI Agentを作成する際に、好きなモデルを選択できるようにします。 + +### 🔑 環境変数の設定 + +各LLMモデルを使用するには、対応するAPIキーを`.env.local`ファイルに設定する必要があります。 + +```.env +# 環境変数の例 +ANTHROPIC_API_KEY=sk-ant-... +OPENAI_API_KEY=sk-proj-... +GOOGLE_GENERATIVE_AI_API_KEY=... +``` + +**重要:** 環境変数は、Next.jsアプリケーションの起動時に読み込まれます。環境変数を変更した場合は、アプリケーションを再起動してください。 + +このプロジェクトでは、次のレッスンでAI Agentを作成する際に、`claude`を使用します。 + +### 🧪 動作確認 + +この段階では、まだAI Agentが完成していないため、動作確認はできません。 + +次のレッスンでMCPクライアントを作成し、その後AI Agentを実装することで、LLMモデルが動作することを確認できます。 ### 🙋‍♂️ 質問する @@ -25,4 +118,4 @@ title: Mastraエージェントの作成 --- -次のレッスンに進みましょう! +次のレッスンでは、MCPサーバーと通信するためのMCPクライアントを作成します! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-2.md index 9f60cf7e..d677bccc 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-2.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-2.md @@ -1,12 +1,130 @@ --- -title: MCPサーバーの統合 +title: MCPクライアントの作成 --- -### 🔌 MCP サーバーの統合 +### 🔗 MCP クライアントの作成 -このレッスンでは、作成したMCPサーバーをMastraエージェントに統合します。 +このレッスンでは、Section 3で作成したMCPサーバーと通信するためのMCPクライアントを実装します。 -(実装内容はここに追加予定) +MCPクライアントは、AI AgentからMCPサーバーに接続し、ツールのリストを取得する役割を担います。 + +### 📝 実装するファイル + +`src/lib/mastra/mcp/client.ts`ファイルを作成し、以下のコードを記述します。 + +```typescript +import { MCPClient } from "@mastra/mcp"; + +/** + * JPYC MCPサーバーを呼び出すためのMCPクライアント + */ +export const jpycMCPClient = new MCPClient({ + servers: { + // JPYC MCPサーバーのURLを設定する(MCPサーバー事前に起動しておくこと) + "jpyc:mcp-server": { + url: new URL( + process.env.JPYC_MCP_SERVER_URL || "http://localhost:3001/sse", + ), + }, + }, +}); +``` + +### 💡 コードの解説 + +このファイルは非常にシンプルですが、重要な役割を果たします。主要なポイントを見ていきましょう。 + +#### 1. MCPClientのインポート + +```typescript +import { MCPClient } from "@mastra/mcp"; +``` + +MastraのMCPクライアントをインポートします。このクライアントは、MCPプロトコルを使用してサーバーと通信します。 + +#### 2. MCPClientインスタンスの作成 + +```typescript +export const jpycMCPClient = new MCPClient({ + servers: { + "jpyc:mcp-server": { + url: new URL( + process.env.JPYC_MCP_SERVER_URL || "http://localhost:3001/sse", + ), + }, + }, +}); +``` + +`MCPClient`は、複数のMCPサーバーに接続できるように設計されています。`servers`オブジェクトで、各サーバーの名前とURLを定義します。 + +**主要なパラメータ:** + +- **サーバー名**: `"jpyc:mcp-server"` - MCPサーバーを識別するための名前 +- **url**: MCPサーバーのSSEエンドポイントURL + +#### 3. 環境変数の使用 + +```typescript +process.env.JPYC_MCP_SERVER_URL || "http://localhost:3001/sse" +``` + +環境変数`JPYC_MCP_SERVER_URL`が設定されている場合はそれを使用し、設定されていない場合はデフォルトの`http://localhost:3001/sse`を使用します。 + +これにより、本番環境と開発環境で異なるMCPサーバーURLを使い分けることができます。 + +#### 4. SSEエンドポイント + +```typescript +"http://localhost:3001/sse" +``` + +Section 3で作成したMCPサーバーのSSEエンドポイントに接続します。このエンドポイントは、サーバーからクライアントへのイベント送信に使用されます。 + +### 🔄 MCPクライアントの動作 + +MCPクライアントは、AI Agentから以下のような流れで使用されます: + +``` +1. AI Agent起動 + ↓ +2. jpycMCPClient.getTools() 呼び出し + ↓ +3. MCPサーバー (http://localhost:3001/sse) に接続 + ↓ +4. サーバーからツールリストを取得 + ↓ +5. ツール(jpyc_balance, jpyc_transfer, etc.)をAI Agentに登録 + ↓ +6. ユーザーの指示に応じてツールを実行 +``` + +次のレッスンでAI Agentを実装する際、このクライアントを使ってツールを動的に取得します。 + +### 🌐 複数サーバーへの対応 + +MCPClientは、複数のMCPサーバーに同時に接続できます。例えば、JPYC操作用のサーバーと、天気情報用のサーバーを同時に使用する場合: + +```typescript +export const multiServerClient = new MCPClient({ + servers: { + "jpyc:mcp-server": { + url: new URL("http://localhost:3001/sse"), + }, + "weather:mcp-server": { + url: new URL("http://localhost:3002/sse"), + }, + }, +}); +``` + +このようにすることで、AI Agentは両方のサーバーのツールを使用できるようになります。 + +### 🧪 動作確認 + +この段階では、まだAI Agentが完成していないため、動作確認はできません。 + +次のレッスンでAI Agentを実装することで、MCPクライアントが正しくサーバーに接続し、ツールを取得できることを確認できます。 ### 🙋‍♂️ 質問する @@ -21,4 +139,4 @@ title: MCPサーバーの統合 --- -次のレッスンに進みましょう! +次のレッスンでは、いよいよAI Agentを実装します! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md index 8ef9fe9a..548da391 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md @@ -1,12 +1,235 @@ --- -title: API Routeの実装 +title: AI Agentの実装 --- -### 🌐 API Route の実装 +### 🤖 AI Agent の実装 -このレッスンでは、Next.js API Routeを実装し、フロントエンドからMastraエージェントを利用できるようにします。 +このレッスンでは、前の2つのレッスンで作成したLLMモデルとMCPクライアントを統合して、AI Agentを実装します。 -(実装内容はここに追加予定) +AI Agentは、ユーザーの自然言語の指示を理解し、適切なMCPツールを呼び出してJPYC操作を実行します。 + +### 📝 実装するファイル + +`src/lib/mastra/agent.ts`ファイルを作成し、以下のコードを記述します。 + +```typescript +import { Agent } from "@mastra/core/agent"; +import { claude } from "./model"; + +/** + * JPYC エージェント + * + * MCP経由でJPYC SDKツールを使用するエージェント + * + * 学習用ポイント: + * - tools は動的関数として定義 + * - MCPClientから getTools() でツールを取得 + * - 循環参照を避けるため、動的インポートを使用 + */ +export const jpycAgent = new Agent({ + name: "JPYC Assistant", + description: + "JPYCトークンの操作をサポートするAIアシスタント(マルチチェーン対応)", + model: claude, + // MCPClient経由でツールを動的に取得 + tools: async () => { + const { jpycMCPClient } = await import("@/lib/mastra/mcp/client"); + const tools = await jpycMCPClient.getTools(); + // biome-ignore lint/suspicious/noExplicitAny: MCPツールの型とMastraツールの型の互換性の問題 + return tools as any; + }, + instructions: ` +あなたはJPYC(日本円ステーブルコイン)の操作をサポートするAIアシスタントです。 + +対応テストネット: Ethereum Sepolia, Avalanche Fuji +デフォルトチェーン: Ethereum Sepolia + +以下の操作が可能です: +1. **チェーン切り替え**: テストネットを変更 +2. **送金**: 指定したアドレスにJPYCを送金(現在選択中のチェーン) +3. **残高照会**: アドレスのJPYC残高を確認(現在選択中のチェーン、アドレス省略時は自分の残高) +4. **総供給量照会**: JPYCの総供給量を確認(現在選択中のチェーン) + +ユーザーの自然言語の指示を解釈し、適切なツールを呼び出してください。 + +## 名前を使った操作について: +メッセージの最後に[ユーザー情報]として、ユーザーの名前と友達リストが含まれている場合があります。 +- 「太郎に100JPYC送って」のような名前を使った送金指示の場合、友達リストから該当する名前のアドレスを探してjpyc_transferを実行してください +- 「太郎の残高教えて」のような場合、友達リストから該当する名前のアドレスを探してjpyc_balanceを実行してください +- 「残高教えて」や「私の残高」のような場合は、自分のアドレスを使用してjpyc_balanceを実行してください +- 友達リストに該当する名前がない場合は、「{名前}さんは友達リストに登録されていません」と返答してください + +例: +- "Sepoliaに切り替えて" → jpyc_switch_chain (chain: "sepolia") +- "Amoyで実行して" → jpyc_switch_chain (chain: "amoy") +- "Avalancheに変更" → jpyc_switch_chain (chain: "fuji") +- "現在のチェーンは?" → jpyc_get_current_chain +- "0x123...に10JPYC送って" → jpyc_transfer +- "太郎に100JPYC送って" → 友達リストから太郎のアドレスを探してjpyc_transfer +- "私の残高を教えて" または "残高教えて" → jpyc_balance (addressなし、または自分のアドレス) +- "太郎の残高教えて" → 友達リストから太郎のアドレスを探してjpyc_balance +- "0x123...の残高を教えて" → jpyc_balance (address: "0x123...") +- "JPYCの総供給量は?" または "流通量教えて" → jpyc_total_supply +- "Amoyで0x123...に10JPYC送って" → まずjpyc_switch_chain、次にjpyc_transfer + +## 重要な回答スタイル: +- **カジュアルで親しみやすい会話調で返答してください** +- **ユーザーの名前が登録されている場合、適宜名前を使って親しみやすく返答してください** +- 絵文字(💰、📊、✅など)は使わないでください +- 引用符(""")やマークダウンの太字(**)は最小限にしてください +- チャットアプリのような自然な会話を心がけてください + +## 回答例: +- **送金成功時**: + 「{to} に {amount} JPYC送りました!トランザクションは[こちらで確認]({explorerUrl})できます({chainName})」 + 名前を使った場合: 「{friendName}さんに {amount} JPYC送りました!トランザクションは[こちらで確認]({explorerUrl})できます({chainName})」 + +- **残高照会時**: + 「{chainName}チェーンの残高は {balance} JPYC です」 + 自分の名前がある場合: 「{userName}さんの{chainName}チェーンの残高は {balance} JPYC です」 + 友達の残高の場合: 「{friendName}さんの{chainName}チェーンの残高は {balance} JPYC です」 + +- **総供給量照会時**: + 「現在の{chainName}での総供給量は {totalSupply} JPYC です」 + +- **チェーン切り替え時**: + 「{newChain} に切り替えました」 + +- **エラー時**: + 「エラーが発生しました: {errorMessage}」 + +重要: +- リンクは必ずマークダウン形式で表示してください(例: [こちらで確認](https://sepolia.etherscan.io/tx/0x...)) +- 数値は読みやすいように適宜カンマ区切りにしてください + `.trim(), +}); +``` + +### 💡 コードの解説 + +このファイルでは、Mastraの`Agent`クラスを使ってAI Agentを作成します。主要なポイントを見ていきましょう。 + +#### 1. Agentクラスのインポート + +```typescript +import { Agent } from "@mastra/core/agent"; +import { claude } from "./model"; +``` + +Mastraの`Agent`クラスと、前のレッスンで作成したClaudeモデルをインポートします。 + +#### 2. Agentインスタンスの作成 + +```typescript +export const jpycAgent = new Agent({ + name: "JPYC Assistant", + description: "JPYCトークンの操作をサポートするAIアシスタント(マルチチェーン対応)", + model: claude, + tools: async () => { ... }, + instructions: `...`, +}); +``` + +`Agent`は以下の主要なパラメータで構成されます: + +- **name**: Agentの名前 +- **description**: Agentの説明 +- **model**: 使用するLLMモデル(前のレッスンで作成したClaude) +- **tools**: 利用可能なツール(動的に取得) +- **instructions**: Agentへのシステムプロンプト + +#### 3. 動的ツール読み込み + +```typescript +tools: async () => { + const { jpycMCPClient } = await import("@/lib/mastra/mcp/client"); + const tools = await jpycMCPClient.getTools(); + return tools as any; +}, +``` + +`tools`を関数として定義することで、Agent起動時に動的にMCPサーバーからツールを取得します。 + +**なぜ動的インポートを使うのか?** + +```typescript +const { jpycMCPClient } = await import("@/lib/mastra/mcp/client"); +``` + +通常のインポート(`import { jpycMCPClient } from "..."`)ではなく、動的インポートを使用する理由は**循環参照を避けるため**です。 + +もし通常のインポートを使うと: +1. `agent.ts`が`client.ts`をインポート +2. `client.ts`がMCPサーバーに接続しようとする +3. MCPサーバーがまだ起動していない可能性がある + +動的インポートにすることで、Agentが実際に使用されるタイミング(チャットAPIが呼ばれたとき)にツールを取得します。 + +#### 4. instructionsの重要性 + +```typescript +instructions: ` +あなたはJPYC(日本円ステーブルコイン)の操作をサポートするAIアシスタントです。 +... +`, +``` + +`instructions`は、AI Agentの振る舞いを定義する**システムプロンプト**です。ここでは以下を指定しています: + +**Agentの役割** +- JPYC操作のサポート +- 対応チェーンの情報 +- 可能な操作のリスト + +**ツール使用の指針** +- どのような指示でどのツールを使うか +- パラメータの抽出方法 +- 複数ステップの操作(チェーン切り替え→送金) + +**名前ベース操作** +- 友達リストからアドレスを検索 +- 該当しない場合のエラーメッセージ + +**回答スタイル** +- カジュアルで親しみやすい会話調 +- 絵文字を使わない +- マークダウンリンクの使用 +- 数値のカンマ区切り + +#### 5. 効果的なinstructionsの書き方 + +良い`instructions`は、AI Agentが正確に動作するために重要です: + +**具体的な例を含める** +``` +例: +- "Sepoliaに切り替えて" → jpyc_switch_chain (chain: "sepolia") +``` + +これにより、AIは自然言語をツール呼び出しに正確に変換できます。 + +**回答フォーマットを指定** +``` +- **送金成功時**: + 「{to} に {amount} JPYC送りました!トランザクションは[こちらで確認]({explorerUrl})できます({chainName})」 +``` + +これにより、一貫性のあるユーザー体験を提供できます。 + +**制約を明示** +``` +- 絵文字(💰、📊、✅など)は使わないでください +``` + +これにより、望ましくない出力を防げます。 + +### 🧪 動作確認 + +この段階では、まだフロントエンドとAPIが完成していないため、完全な動作確認はできません。 + +ただし、MCPサーバーが起動していれば、Agentがツールを正しく取得できることを確認できます。 + +次のSection 5では、このAI Agentを呼び出すAPI Routeとフロントエンドを実装します。 ### 🙋‍♂️ 質問する @@ -21,4 +244,4 @@ title: API Routeの実装 --- -これでセクション4は完了です! 次のセクションでは、フロントエンドを実装します。 +これでSection 4(Mastraエージェントの実装)が完了しました! 次のセクションでは、フロントエンドを実装します。 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md index 8b97e2eb..68e29529 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md @@ -1,16 +1,266 @@ --- -title: チャットインタフェースの実装 +title: チャットAPIの実装 --- -### 💬 チャットインタフェースの実装 +### 🌐 チャット API の実装 -このセクションでは、ユーザーがAI Agentと対話するためのチャットインタフェースを実装します。 +このレッスンでは、フロントエンドからAI Agentを呼び出すためのAPIエンドポイントを実装します。 -### 🎨 UIコンポーネントの作成 +このAPIは、ユーザーのメッセージを受け取り、Section 4で作成したAI Agentに渡し、レスポンスを返します。 -`src/components/ChatInterface.tsx`ファイルを作成し、チャット画面を実装します。 +### 📝 実装するファイル -(実装内容はここに追加予定) +`src/app/api/chat/route.ts`ファイルを作成し、以下のコードを記述します。 + +```typescript +import { jpycAgent } from "@/lib/mastra/agent"; +import type { NextRequest } from "next/server"; + +/** + * AI AgentのAPIを呼び出すエンドポイント + * @param req + * @returns + */ +export async function POST(req: NextRequest) { + try { + // リクエストパラメータからメッセージ、会話ID、プロフィール、友達リストを取得 + const { message, conversationId, profile, friends } = await req.json(); + + if (!message) { + return new Response( + JSON.stringify({ success: false, error: "Message is required" }), + { + status: 400, + headers: { "Content-Type": "application/json" }, + }, + ); + } + + // プロフィールと友達リストをコンテキストとして追加 + let contextMessage = message; + if (profile || (friends && friends.length > 0)) { + let context = "\n\n[ユーザー情報]\n"; + + if (profile) { + context += `- 自分の名前: ${profile.name}\n`; + context += `- 自分のアドレス: ${profile.address}\n`; + } + + if (friends && friends.length > 0) { + context += "\n[友達リスト]\n"; + for (const friend of friends) { + context += `- ${friend.name}: ${friend.address}\n`; + } + } + + contextMessage = message + context; + } + + // Mastraで定義したJPYC AI Agentの機能を呼び出す + const response = await jpycAgent.generate(contextMessage, { + ...(conversationId && { conversationId }), + }); + + console.log("Full generate response:", JSON.stringify(response, null, 2)); + console.log("Generate response summary:", { + text: response.text, + textLength: response.text?.length, + object: response.object, + steps: response.steps?.length, + toolResults: response.toolResults?.length, + }); + + // レスポンステキストを返す + return new Response( + response.text || "エージェントからの応答がありませんでした", + { + headers: { + "Content-Type": "text/plain; charset=utf-8", + }, + }, + ); + } catch (error) { + console.error("Chat API Error:", error); + return new Response( + JSON.stringify({ + success: false, + error: + error instanceof Error + ? error.message + : "An error occurred while processing your request", + }), + { + status: 500, + headers: { "Content-Type": "application/json" }, + }, + ); + } +} +``` + +### 💡 コードの解説 + +このファイルは、Next.js 15のApp Router API Routeとして実装されています。主要なポイントを見ていきましょう。 + +#### 1. POSTメソッドの定義 + +```typescript +export async function POST(req: NextRequest) { + // 処理 +} +``` + +Next.js 15のApp Routerでは、APIルートを`route.ts`ファイルで定義し、HTTPメソッドごとに関数をエクスポートします。 + +#### 2. リクエストパラメータの取得 + +```typescript +const { message, conversationId, profile, friends } = await req.json(); +``` + +クライアントから送信されたJSONデータを取得します: + +- **message**: ユーザーのメッセージ +- **conversationId**: 会話を識別するID(会話の文脈を保持するため) +- **profile**: ユーザーのプロフィール(名前、アドレス) +- **friends**: 友達リスト(名前とアドレスのペア) + +#### 3. パラメータ検証 + +```typescript +if (!message) { + return new Response( + JSON.stringify({ success: false, error: "Message is required" }), + { status: 400, headers: { "Content-Type": "application/json" } }, + ); +} +``` + +必須パラメータ(`message`)が存在しない場合は、400エラーを返します。 + +#### 4. コンテキスト情報の追加 + +```typescript +let contextMessage = message; +if (profile || (friends && friends.length > 0)) { + let context = "\n\n[ユーザー情報]\n"; + + if (profile) { + context += `- 自分の名前: ${profile.name}\n`; + context += `- 自分のアドレス: ${profile.address}\n`; + } + + if (friends && friends.length > 0) { + context += "\n[友達リスト]\n"; + for (const friend of friends) { + context += `- ${friend.name}: ${friend.address}\n`; + } + } + + contextMessage = message + context; +} +``` + +ユーザーのプロフィールと友達リストを、メッセージの末尾にコンテキストとして追加します。 + +これにより、AI Agentは以下のようなメッセージを受け取ります: + +``` +残高教えて + +[ユーザー情報] +- 自分の名前: 太郎 +- 自分のアドレス: 0x1234... + +[友達リスト] +- 花子: 0x5678... +- 次郎: 0x9abc... +``` + +AI Agentは、Section 4で定義した`instructions`に従って、このコンテキストを解釈し、適切なツールを呼び出します。 + +#### 5. AI Agentの呼び出し + +```typescript +const response = await jpycAgent.generate(contextMessage, { + ...(conversationId && { conversationId }), +}); +``` + +Section 4で作成した`jpycAgent`の`generate()`メソッドを呼び出します。 + +**パラメータ:** +- **contextMessage**: ユーザーのメッセージ(コンテキスト付き) +- **conversationId**: 会話IDがある場合は渡す + +`conversationId`を渡すことで、Mastraは同じ会話の文脈を保持し、前のメッセージを参照できるようになります。 + +#### 6. レスポンスの返却 + +```typescript +return new Response( + response.text || "エージェントからの応答がありませんでした", + { + headers: { + "Content-Type": "text/plain; charset=utf-8", + }, + }, +); +``` + +AI Agentのレスポンステキストをプレーンテキストとして返します。 + +#### 7. エラーハンドリング + +```typescript +catch (error) { + console.error("Chat API Error:", error); + return new Response( + JSON.stringify({ + success: false, + error: error instanceof Error ? error.message : "An error occurred while processing your request", + }), + { status: 500, headers: { "Content-Type": "application/json" } }, + ); +} +``` + +エラーが発生した場合は、500エラーとエラーメッセージを返します。 + +### 🔄 API の動作フロー + +このAPIの典型的な動作フローは以下の通りです: + +``` +1. フロントエンドから POST /api/chat にリクエスト + { + "message": "太郎に100JPYC送って", + "conversationId": "uuid-1234", + "profile": { "name": "花子", "address": "0x..." }, + "friends": [{ "name": "太郎", "address": "0x..." }] + } + ↓ +2. コンテキスト情報を追加 + "太郎に100JPYC送って\n\n[ユーザー情報]\n- 自分の名前: 花子\n..." + ↓ +3. jpycAgent.generate() 呼び出し + ↓ +4. AI Agentがinstructionsを読み、友達リストから太郎のアドレスを特定 + ↓ +5. jpyc_transfer ツールを呼び出し + { to: "0x...", amount: 100 } + ↓ +6. MCPサーバー経由でJPYC SDKが送金実行 + ↓ +7. トランザクションハッシュを取得 + ↓ +8. AI Agentが自然言語で回答を生成 + 「太郎さんに 100 JPYC送りました!トランザクションは[こちらで確認](https://...)できます」 + ↓ +9. レスポンスをフロントエンドに返す +``` + +次のレッスンでは、ユーザーのプロフィールと友達リストを管理するローカルストレージの実装を行います。 ### 🙋‍♂️ 質問する @@ -25,4 +275,4 @@ title: チャットインタフェースの実装 --- -次のレッスンに進みましょう! +次のレッスンでは、ローカルストレージの実装を行います! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md index ac62ede8..31ff7dae 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md @@ -1,12 +1,335 @@ --- -title: メッセージ送信機能の実装 +title: ローカルストレージの実装 --- -### 📨 メッセージ送信機能の実装 +### 💾 ローカルストレージの実装 -このレッスンでは、ユーザーのメッセージをAI Agentに送信する機能を実装します。 +このレッスンでは、ユーザーのプロフィールと友達リストをブラウザのlocalStorageに保存する機能を実装します。 -(実装内容はここに追加予定) +これにより、ユーザーは名前とアドレスを登録し、友達の名前を使ってJPYC送金ができるようになります。 + +### 📝 実装するファイル + +まず、型定義ファイル`src/lib/storage/types.ts`を作成します: + +```typescript +import type { Hex } from "viem"; + +export type UserProfile = { + name: string; + address: Hex; + updatedAt: string; +}; + +export type Friend = { + id: string; + name: string; + address: Hex; + createdAt: string; +}; + +export type StorageData = { + profile: UserProfile | null; + friends: Friend[]; +}; +``` + +次に、`src/lib/storage/localStorage.ts`ファイルを作成し、以下のコードを記述します: + +```typescript +import type { Friend, UserProfile, StorageData } from "./types"; +import { type Hex } from "viem"; + +export type { Friend, UserProfile } from "./types"; + +const STORAGE_KEY = "jpyc-ai-agent-data"; + +function getStorageData(): StorageData { + if (typeof window === "undefined") { + return { profile: null, friends: [] }; + } + + const data = localStorage.getItem(STORAGE_KEY); + if (!data) { + return { profile: null, friends: [] }; + } + + try { + return JSON.parse(data); + } catch { + return { profile: null, friends: [] }; + } +} + +function setStorageData(data: StorageData): void { + if (typeof window === "undefined") return; + localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); +} + +// Profile管理 +export function getProfile(): UserProfile | null { + return getStorageData().profile; +} + +export function setProfile(name: string, address: Hex): UserProfile { + const data = getStorageData(); + const profile: UserProfile = { + name, + address, + updatedAt: new Date().toISOString(), + }; + data.profile = profile; + setStorageData(data); + return profile; +} + +export function deleteProfile(): void { + const data = getStorageData(); + data.profile = null; + setStorageData(data); +} + +// Friends管理 +export function getFriends(): Friend[] { + return getStorageData().friends; +} + +export function getFriendByName(name: string): Friend | undefined { + const friends = getFriends(); + return friends.find((f) => f.name.toLowerCase() === name.toLowerCase()); +} + +export function getFriendById(id: string): Friend | undefined { + const friends = getFriends(); + return friends.find((f) => f.id === id); +} + +export function addFriend(name: string, address: Hex): Friend { + const data = getStorageData(); + + // 同じ名前が既に存在するかチェック + const existingFriend = data.friends.find( + (f) => f.name.toLowerCase() === name.toLowerCase(), + ); + if (existingFriend) { + throw new Error(`友達リストに「${name}」は既に登録されています`); + } + + const friend: Friend = { + id: crypto.randomUUID(), + name, + address, + createdAt: new Date().toISOString(), + }; + + data.friends.push(friend); + setStorageData(data); + return friend; +} + +export function updateFriend(id: string, name: string, address: Hex): Friend { + const data = getStorageData(); + const index = data.friends.findIndex((f) => f.id === id); + + if (index === -1) { + throw new Error("友達が見つかりません"); + } + + // 他の友達と名前が重複しないかチェック + const duplicateFriend = data.friends.find( + (f, i) => i !== index && f.name.toLowerCase() === name.toLowerCase(), + ); + if (duplicateFriend) { + throw new Error(`友達リストに「${name}」は既に登録されています`); + } + + const friend: Friend = { + ...data.friends[index], + name, + address, + }; + + data.friends[index] = friend; + setStorageData(data); + return friend; +} + +export function deleteFriend(id: string): void { + const data = getStorageData(); + data.friends = data.friends.filter((f) => f.id !== id); + setStorageData(data); +} +``` + +### 💡 コードの解説 + +このファイルでは、ブラウザのlocalStorageを使って、ユーザーデータを永続化します。主要なポイントを見ていきましょう。 + +#### 1. ストレージキー + +```typescript +const STORAGE_KEY = "jpyc-ai-agent-data"; +``` + +localStorageに保存する際のキー名を定義します。このキーで、プロフィールと友達リストの両方を1つのオブジェクトとして保存します。 + +#### 2. SSRへの対応 + +```typescript +if (typeof window === "undefined") { + return { profile: null, friends: [] }; +} +``` + +Next.jsはサーバーサイドレンダリング(SSR)を行うため、`window`オブジェクトが存在しない場合があります。この条件分岐により、サーバーサイドでの実行時にエラーが発生しないようにします。 + +#### 3. データの読み込み + +```typescript +function getStorageData(): StorageData { + const data = localStorage.getItem(STORAGE_KEY); + if (!data) { + return { profile: null, friends: [] }; + } + + try { + return JSON.parse(data); + } catch { + return { profile: null, friends: [] }; + } +} +``` + +localStorageからデータを取得し、JSONとしてパースします。データが存在しない場合やパースに失敗した場合は、空のデータを返します。 + +#### 4. プロフィール管理 + +**プロフィールの取得** +```typescript +export function getProfile(): UserProfile | null { + return getStorageData().profile; +} +``` + +現在のプロフィールを取得します。未設定の場合は`null`を返します。 + +**プロフィールの設定** +```typescript +export function setProfile(name: string, address: Hex): UserProfile { + const data = getStorageData(); + const profile: UserProfile = { + name, + address, + updatedAt: new Date().toISOString(), + }; + data.profile = profile; + setStorageData(data); + return profile; +} +``` + +プロフィールを設定します。`updatedAt`に現在時刻を記録します。 + +**プロフィールの削除** +```typescript +export function deleteProfile(): void { + const data = getStorageData(); + data.profile = null; + setStorageData(data); +} +``` + +プロフィールを削除します。 + +#### 5. 友達リスト管理 + +**友達の追加** +```typescript +export function addFriend(name: string, address: Hex): Friend { + const data = getStorageData(); + + // 同じ名前が既に存在するかチェック + const existingFriend = data.friends.find( + (f) => f.name.toLowerCase() === name.toLowerCase(), + ); + if (existingFriend) { + throw new Error(`友達リストに「${name}」は既に登録されています`); + } + + const friend: Friend = { + id: crypto.randomUUID(), + name, + address, + createdAt: new Date().toISOString(), + }; + + data.friends.push(friend); + setStorageData(data); + return friend; +} +``` + +友達を追加します。重複チェックを行い、既に同じ名前が存在する場合はエラーを投げます。 + +**友達の検索** +```typescript +export function getFriendByName(name: string): Friend | undefined { + const friends = getFriends(); + return friends.find((f) => f.name.toLowerCase() === name.toLowerCase()); +} +``` + +名前で友達を検索します。大文字小文字を区別しないため、`toLowerCase()`で正規化します。 + +**友達の更新** +```typescript +export function updateFriend(id: string, name: string, address: Hex): Friend { + // 重複チェック + const duplicateFriend = data.friends.find( + (f, i) => i !== index && f.name.toLowerCase() === name.toLowerCase(), + ); + if (duplicateFriend) { + throw new Error(`友達リストに「${name}」は既に登録されています`); + } + // 更新処理 +} +``` + +友達の情報を更新します。他の友達と名前が重複しないかチェックします。 + +**友達の削除** +```typescript +export function deleteFriend(id: string): void { + const data = getStorageData(); + data.friends = data.friends.filter((f) => f.id !== id); + setStorageData(data); +} +``` + +指定したIDの友達を削除します。 + +### 🔄 AI Agentとの連携 + +このローカルストレージは、前のレッスンで作成したチャットAPIと連携します: + +``` +1. ユーザーが「太郎に100JPYC送って」と入力 + ↓ +2. フロントエンドがgetFriends()で友達リストを取得 + ↓ +3. APIリクエストに友達リストを含めて送信 + { + "message": "太郎に100JPYC送って", + "profile": { "name": "花子", "address": "0x..." }, + "friends": [{ "name": "太郎", "address": "0x..." }] + } + ↓ +4. AI Agentが友達リストから太郎のアドレスを検索 + ↓ +5. jpyc_transferツールで送金実行 +``` + +次のレッスンでは、これらの関数を使用するチャットインタフェースを実装します。 ### 🙋‍♂️ 質問する @@ -21,4 +344,4 @@ title: メッセージ送信機能の実装 --- -次のレッスンに進みましょう! +次のレッスンでは、チャットインタフェースの前半を実装します! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-3.md index adb2f8ce..933e8315 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-3.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-3.md @@ -1,12 +1,452 @@ --- -title: ストリーミングレスポンスの実装 +title: チャットインターフェース(前半) --- -### ⚡️ ストリーミングレスポンスの実装 +### 💬 チャットインタフェース(前半) -このレッスンでは、AI Agentからのレスポンスをリアルタイムでストリーミング表示する機能を実装します。 +このレッスンでは、ユーザーとAI Agentが対話するためのチャットインタフェースの前半部分を実装します。 -(実装内容はここに追加予定) +前半では、状態管理、メッセージ表示、API連携を実装します。後半のレッスンでは、設定画面と友達リスト管理UIを実装します。 + +### 📝 実装するファイル(前半部分) + +`src/components/ChatInterface.tsx`ファイルを作成し、以下のコードを記述します: + +```typescript +"use client"; + +import { + addFriend, + deleteFriend, + deleteProfile, + type Friend, + getFriends, + getProfile, + setProfile, + type UserProfile, +} from "@/lib/storage/localStorage"; +import { useEffect, useRef, useState } from "react"; +import ReactMarkdown from "react-markdown"; + +type Message = { + role: "user" | "assistant"; + content: string; + timestamp: Date; +}; + +/** + * ChatInterfaceコンポーネント + * @returns + */ +export default function ChatInterface() { + // 状態管理 + const [messages, setMessages] = useState([]); + const [input, setInput] = useState(""); + const [loading, setLoading] = useState(false); + const [conversationId, setConversationId] = useState(null); + const [currentChainName, setCurrentChainName] = useState("Loading..."); + const [profile, setProfileState] = useState(null); + const [friends, setFriendsState] = useState([]); + const [showSettings, setShowSettings] = useState(false); + const [profileName, setProfileName] = useState(""); + const [friendName, setFriendName] = useState(""); + const [friendAddress, setFriendAddress] = useState(""); + const messagesEndRef = useRef(null); + + // メッセージが更新されたら自動スクロール + useEffect(() => { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); + }, [messages, loading]); + + // プロフィールと友達リストを読み込む + useEffect(() => { + setProfileState(getProfile()); + setFriendsState(getFriends()); + }, []); + + // 現在のチェーンを取得 + useEffect(() => { + const fetchCurrentChain = async () => { + try { + const response = await fetch("/api/chain"); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data = await response.json(); + if (data.success) { + setCurrentChainName(data.chainName); + } else { + throw new Error(data.error || "Unknown error"); + } + } catch (error) { + console.error("Failed to fetch current chain:", error); + setCurrentChainName("Ethereum Sepolia"); + } + }; + + fetchCurrentChain(); + const interval = setInterval(fetchCurrentChain, 3000); + return () => clearInterval(interval); + }, [messages]); + + // メッセージ送信処理 + const sendMessage = async () => { + if (!input.trim()) return; + + const userMessage: Message = { + role: "user", + content: input, + timestamp: new Date(), + }; + + setMessages((prev) => [...prev, userMessage]); + setInput(""); + setLoading(true); + + try { + const response = await fetch("/api/chat", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + message: input, + conversationId, + profile, + friends, + }), + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + // ストリーミングレスポンスを処理 + const reader = response.body?.getReader(); + const decoder = new TextDecoder(); + let assistantMessage = ""; + + // アシスタントメッセージの枠を追加 + setMessages((prev) => [ + ...prev, + { + role: "assistant", + content: "", + timestamp: new Date(), + }, + ]); + + if (reader) { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + const chunk = decoder.decode(value); + assistantMessage += chunk; + + // メッセージを更新 + setMessages((prev) => { + const newMessages = [...prev]; + newMessages[newMessages.length - 1] = { + role: "assistant", + content: assistantMessage, + timestamp: new Date(), + }; + return newMessages; + }); + } + } + } catch (error) { + setMessages((prev) => [ + ...prev, + { + role: "assistant", + content: `❌ エラー: ${error instanceof Error ? error.message : "不明なエラー"}`, + timestamp: new Date(), + }, + ]); + } finally { + setLoading(false); + } + }; + + // UIレンダリング(次のレッスンで実装) + return ( +
+ {/* ヘッダー */} +
+
+

JPYC AI Agent

+

Current Chain: {currentChainName}

+
+ +
+ + {/* メッセージリスト */} +
+ {messages.map((message, index) => ( +
+
+ {message.content} +
+
+ ))} + {loading && ( +
+
+

...

+
+
+ )} +
+
+ + {/* 入力フォーム */} +
+
+ setInput(e.target.value)} + onKeyPress={(e) => e.key === "Enter" && sendMessage()} + placeholder="メッセージを入力..." + className="flex-1 px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" + disabled={loading} + /> + +
+
+
+ ); +} +``` + +### 💡 コードの解説 + +このファイルでは、Reactの状態管理とAPI連携を実装しています。主要なポイントを見ていきましょう。 + +#### 1. 状態管理 + +```typescript +const [messages, setMessages] = useState([]); +const [input, setInput] = useState(""); +const [loading, setLoading] = useState(false); +const [conversationId, setConversationId] = useState(null); +const [currentChainName, setCurrentChainName] = useState("Loading..."); +const [profile, setProfileState] = useState(null); +const [friends, setFriendsState] = useState([]); +``` + +**主要な状態:** + +- **messages**: チャットメッセージの配列 +- **input**: 入力フィールドの値 +- **loading**: API呼び出し中かどうか +- **conversationId**: 会話を識別するID +- **currentChainName**: 現在のブロックチェーン名 +- **profile**: ユーザーのプロフィール +- **friends**: 友達リスト + +#### 2. 自動スクロール + +```typescript +const messagesEndRef = useRef(null); + +useEffect(() => { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); +}, [messages, loading]); +``` + +新しいメッセージが追加されたとき、自動的に最新のメッセージまでスクロールします。 + +#### 3. データの読み込み + +```typescript +useEffect(() => { + setProfileState(getProfile()); + setFriendsState(getFriends()); +}, []); +``` + +コンポーネントのマウント時に、localStorageからプロフィールと友達リストを読み込みます。 + +#### 4. チェーン情報の定期取得 + +```typescript +useEffect(() => { + const fetchCurrentChain = async () => { + const response = await fetch("/api/chain"); + const data = await response.json(); + if (data.success) { + setCurrentChainName(data.chainName); + } + }; + + fetchCurrentChain(); + const interval = setInterval(fetchCurrentChain, 3000); + return () => clearInterval(interval); +}, [messages]); +``` + +現在のチェーン名を3秒ごとに取得します。ユーザーが「Avalancheに切り替えて」と言った場合、UIに反映されます。 + +#### 5. メッセージ送信処理 + +```typescript +const sendMessage = async () => { + if (!input.trim()) return; + + const userMessage: Message = { + role: "user", + content: input, + timestamp: new Date(), + }; + + setMessages((prev) => [...prev, userMessage]); + setInput(""); + setLoading(true); + + // API呼び出し +} +``` + +**処理の流れ:** + +1. 入力が空でないことを確認 +2. ユーザーメッセージを作成してメッセージリストに追加 +3. 入力フィールドをクリア +4. ローディング状態を有効化 +5. APIを呼び出す + +#### 6. ストリーミングレスポンスの処理 + +```typescript +const reader = response.body?.getReader(); +const decoder = new TextDecoder(); +let assistantMessage = ""; + +// 空のアシスタントメッセージを追加 +setMessages((prev) => [ + ...prev, + { + role: "assistant", + content: "", + timestamp: new Date(), + }, +]); + +if (reader) { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + const chunk = decoder.decode(value); + assistantMessage += chunk; + + // メッセージを更新 + setMessages((prev) => { + const newMessages = [...prev]; + newMessages[newMessages.length - 1] = { + role: "assistant", + content: assistantMessage, + timestamp: new Date(), + }; + return newMessages; + }); + } +} +``` + +**ストリーミングの仕組み:** + +1. レスポンスボディから`ReadableStream`を取得 +2. 空のアシスタントメッセージを追加 +3. チャンクを受信するたびにメッセージを更新 +4. ユーザーはAI Agentの回答がリアルタイムで表示されるのを見ることができる + + +#### 7. UIレンダリング + +```typescript +
+ {/* ヘッダー */} +
+

JPYC AI Agent

+

Current Chain: {currentChainName}

+
+ + {/* メッセージリスト */} +
+ {messages.map((message, index) => ( +
+ {message.content} +
+ ))} +
+ + {/* 入力フォーム */} +
+ setInput(e.target.value)} + onKeyPress={(e) => e.key === "Enter" && sendMessage()} + /> + +
+
+``` + +**UIの構成:** + +- **ヘッダー**: タイトルと現在のチェーン表示 +- **メッセージリスト**: ユーザーとAI Agentのメッセージ +- **入力フォーム**: メッセージ入力とEnterキーでの送信 + +**ReactMarkdown**: AI Agentの回答に含まれるマークダウン(リンクなど)を適切に表示します。 + +### 🧪 動作確認 + +この段階では、基本的なチャット機能が動作します。 + +1. **開発サーバーの起動** + +```bash +# ターミナル1: MCPサーバー +pnpm mcp:dev + +# ターミナル2: Next.jsアプリ +pnpm dev +``` + +2. **ブラウザで確認** + +`http://localhost:3000`にアクセスし、メッセージを送信してみましょう: + +- 「残高教えて」 +- 「総供給量は?」 +- 「現在のチェーンは?」 + +AI Agentが適切に応答することを確認できます。 + +次のレッスンでは、設定画面とプロフィール・友達リスト管理UIを実装します。 ### 🙋‍♂️ 質問する @@ -21,4 +461,4 @@ title: ストリーミングレスポンスの実装 --- -次のレッスンに進みましょう! +次のレッスンでは、設定画面と友達リスト管理UIを実装します! diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md index ea9a8ec3..dd61f1b7 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md @@ -1,49 +1,584 @@ --- -title: アプリケーションの完成とテスト +title: チャットインターフェース(後半) --- -### 🎉 アプリケーションの完成とテスト +### 💬 チャットインタフェース(後半) -このレッスンでは、アプリケーションを完成させ、動作確認を行います。 +このレッスンでは、前のレッスンで実装したチャットインタフェースに、設定画面と友達リスト管理UIを追加して完成させます。 -### ✅ 最終確認 +これにより、ユーザーは自分のプロフィールと友達リストをGUI上で管理できるようになります。 -以下の機能が正しく動作することを確認します: +### 📝 実装するファイル(後半部分) -1. **残高確認**:「残高を教えて」と聞いてJPYC残高が表示される -2. **送金処理**:「〇〇にXX JPYC送って」と指示して送金が実行される -3. **取引履歴**:「取引履歴を表示して」と聞いて履歴が表示される +前のレッスンで作成した`src/components/ChatInterface.tsx`ファイルの`return`文を以下のコードに置き換えます: -(詳細なテスト手順はここに追加予定) +```typescript +// UIレンダリング +return ( +
+ {/* ヘッダー */} +
+
+

JPYC AI Agent

+

Current Chain: {currentChainName}

+
+ +
-### 🎊 プロジェクト完了 + {/* 設定モーダル */} + {showSettings && ( +
+
+
+

設定

+ +
-おめでとうございます! AI Agent × JPYCチャットアプリが完成しました。 + {/* プロフィール設定 */} +
+

プロフィール

+ {profile ? ( +
+

名前: {profile.name}

+

+ アドレス: {profile.address} +

+ +
+ ) : ( +
+ setProfileName(e.target.value)} + placeholder="名前" + className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" + /> + { + const value = e.target.value; + // 0xで始まる16進数のアドレスのみ許可 + if (value === "" || /^0x[0-9a-fA-F]*$/.test(value)) { + setInput(value); + } + }} + placeholder="アドレス (0x...)" + className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" + /> + +
+ )} +
-このプロジェクトを通じて、以下のスキルを習得しました: + {/* 友達リスト */} +
+

友達リスト

+
+ {friends.map((friend) => ( +
+
+

{friend.name}

+

+ {friend.address} +

+
+ +
+ ))} +
-- JPYCとステーブルコインの理解 -- AI Agentの実装方法 -- MCPプロトコルの活用 -- Mastraフレームワークの使い方 -- web3とAIの統合 + {/* 友達追加フォーム */} +
+ setFriendName(e.target.value)} + placeholder="友達の名前" + className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" + /> + { + const value = e.target.value; + // 0xで始まる16進数のアドレスのみ許可 + if (value === "" || /^0x[0-9a-fA-F]*$/.test(value)) { + setFriendAddress(value); + } + }} + placeholder="友達のアドレス (0x...)" + className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" + /> + +
+
+
+
+ )} -### 🌍 プロジェクトをアップグレードする + {/* メッセージリスト */} +
+ {messages.map((message, index) => ( +
+
+ {message.content} +
+
+ ))} + {loading && ( +
+
+

...

+
+
+ )} +
+
-[UNCHAIN](https://unchain.tech/)のプロジェクトは[UNCHAIN License](https://github.com/unchain-tech/UNCHAIN-projects/blob/main/LICENSE)により運用されています。 + {/* 入力フォーム */} +
+
+ setInput(e.target.value)} + onKeyPress={(e) => e.key === "Enter" && sendMessage()} + placeholder="メッセージを入力..." + className="flex-1 px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" + disabled={loading} + /> + +
+
+
+); +``` -プロジェクトに参加していて、「こうすればもっと分かりやすいのに!」「これは間違っている!」と思ったら、ぜひ`pull request`を送ってください。 +### 💡 コードの解説 + +このレッスンでは、設定モーダルとプロフィール・友達リスト管理UIを実装します。主要なポイントを見ていきましょう。 + +#### 1. 設定モーダルの表示/非表示 + +```typescript +{showSettings && ( +
+
+ ... +
+
+)} +``` + +**モーダルの実装:** + +- `fixed inset-0`: 画面全体を覆う固定配置 +- `bg-black bg-opacity-50`: 半透明の黒背景(オーバーレイ) +- `z-50`: 他の要素より前面に表示 +- `max-h-[80vh] overflow-y-auto`: 画面の80%以内で、超えた場合はスクロール + +#### 2. プロフィール設定UI + +**既存プロフィールの表示** + +```typescript +{profile ? ( +
+

名前: {profile.name}

+

+ アドレス: {profile.address} +

+ +
+) : ( + // 新規プロフィール作成フォーム +)} +``` + +プロフィールが存在する場合は表示し、削除ボタンを提供します。 + +**新規プロフィール作成** + +```typescript + setProfileName(e.target.value)} + placeholder="名前" +/> + { + const value = e.target.value; + // 0xで始まる16進数のアドレスのみ許可 + if (value === "" || /^0x[0-9a-fA-F]*$/.test(value)) { + setInput(value); + } + }} + placeholder="アドレス (0x...)" +/> +``` + +**バリデーション:** + +- アドレス入力時に正規表現で16進数のみ許可 +- 保存時に完全な形式(0x + 40桁)をチェック + +**保存処理** + +```typescript +onClick={() => { + if (profileName && input && /^0x[0-9a-fA-F]{40}$/.test(input)) { + try { + const newProfile = setProfile(profileName, input as `0x${string}`); + setProfileState(newProfile); + setProfileName(""); + setInput(""); + } catch (error) { + alert(error instanceof Error ? error.message : "プロフィールの保存に失敗しました"); + } + } else { + alert("名前と有効なアドレス(0x + 40桁の16進数)を入力してください"); + } +}} +``` + +**処理の流れ:** + +1. 入力値とアドレス形式をバリデーション +2. `setProfile()`でlocalStorageに保存 +3. React stateを更新 +4. 入力フィールドをクリア +5. エラーハンドリング + +#### 3. 友達リストの表示 + +```typescript +{friends.map((friend) => ( +
+
+

{friend.name}

+

{friend.address}

+
+ +
+))} +``` + +**表示のポイント:** + +- `key={friend.id}`: Reactのリストレンダリングに必須 +- `break-all`: 長いアドレスを折り返して表示 +- `flex justify-between`: 名前/アドレスと削除ボタンを両端に配置 + +**削除処理** + +```typescript +onClick={() => { + if (window.confirm(`${friend.name}を友達リストから削除しますか?`)) { + deleteFriend(friend.id); + setFriendsState(getFriends()); + } +}} +``` + +**処理の流れ:** + +1. 確認ダイアログを表示 +2. `deleteFriend()`でlocalStorageから削除 +3. `getFriends()`で最新の友達リストを取得 +4. React stateを更新 + +#### 4. 友達追加フォーム + +```typescript + setFriendName(e.target.value)} + placeholder="友達の名前" +/> + { + const value = e.target.value; + if (value === "" || /^0x[0-9a-fA-F]*$/.test(value)) { + setFriendAddress(value); + } + }} + placeholder="友達のアドレス (0x...)" +/> +``` + +プロフィール入力と同様に、アドレスの入力時に16進数のみを許可します。 + +**追加処理** + +```typescript +onClick={() => { + if (friendName && friendAddress && /^0x[0-9a-fA-F]{40}$/.test(friendAddress)) { + try { + addFriend(friendName, friendAddress as `0x${string}`); + setFriendsState(getFriends()); + setFriendName(""); + setFriendAddress(""); + } catch (error) { + alert(error instanceof Error ? error.message : "友達の追加に失敗しました"); + } + } else { + alert("名前と有効なアドレス(0x + 40桁の16進数)を入力してください"); + } +}} +``` + +**処理の流れ:** + +1. 入力値とアドレス形式をバリデーション +2. `addFriend()`でlocalStorageに保存 + - 重複チェックは`addFriend()`内で実行される +3. React stateを更新 +4. 入力フィールドをクリア +5. エラーハンドリング(重複エラーを含む) + +#### 5. メッセージリストと入力フォーム + +```typescript +{/* メッセージリスト */} +
+ {messages.map((message, index) => ( +
+
+ {message.content} +
+
+ ))} + {loading && ( +
+
+

...

+
+
+ )} +
+
+ +{/* 入力フォーム */} +
+
+ setInput(e.target.value)} + onKeyPress={(e) => e.key === "Enter" && sendMessage()} + placeholder="メッセージを入力..." + disabled={loading} + /> + +
+
+``` + +これらは前のレッスンと同じコードです。設定モーダルと共存できるように、適切にレイアウトされています。 + +### 🧪 動作確認 + +完成したアプリケーションを起動して、全機能を確認しましょう。 + +1. **開発サーバーの起動** + +```bash +# ターミナル1: MCPサーバー +pnpm mcp:dev + +# ターミナル2: Next.jsアプリ +pnpm dev +``` + +2. **ブラウザで確認** + +`http://localhost:3000`にアクセスします。 + +**プロフィール設定** + +1. 右上の「設定」ボタンをクリック +2. 名前とアドレスを入力 +3. 「保存」をクリック +4. プロフィールが表示されることを確認 + +**友達追加** + +1. 設定画面で「友達の名前」と「友達のアドレス」を入力 +2. 「友達を追加」をクリック +3. 友達リストに追加されることを確認 + +**名前を使った送金** + +1. 設定画面を閉じる +2. チャット欄に「太郎に100JPYC送って」と入力(太郎は友達リストに登録済みの名前) +3. AI Agentが友達リストから太郎のアドレスを検索し、送金を実行 +4. トランザクションハッシュ付きの応答が返ることを確認 + +**友達の残高照会** + +1. 「太郎の残高教えて」と入力 +2. AI Agentが友達リストから太郎のアドレスを検索し、残高を照会 +3. 残高が表示されることを確認 + +### 🎉 完成! + +おめでとうございます! JPYC AI Agent ChatAppが完成しました! + +このアプリケーションでは、以下の機能が実装されています: + +**AI Agent機能** +- 自然言語でのJPYC操作(送金、残高照会、総供給量照会) +- マルチチェーン対応(Ethereum Sepolia、Avalanche Fuji) +- チェーン切り替え機能 + +**ユーザー管理機能** +- プロフィール設定(名前、アドレス) +- 友達リスト管理(追加、削除) +- 名前を使った送金・残高照会 + +**チャットUI** +- リアルタイムストリーミング応答 +- マークダウン対応 +- 自動スクロール +- ローディング表示 ### 🚀 次のステップ -このアプリケーションをさらに改善するアイデア: +このアプリケーションをベースに、さらに以下のような機能を追加できます: -1. **複数ウォレット対応**:複数のウォレットを管理できるようにする -2. **トランザクション通知**:送金完了時にプッシュ通知を送る -3. **定期送金機能**:毎月自動で送金するスケジュール機能 -4. **マルチチェーン対応**:Polygon以外のチェーンもサポート -5. **音声入力**:音声でAI Agentに指示できる機能 -6. **グラフ表示**:残高や取引履歴をグラフで可視化 +1. **会話履歴の保存**: localStorageにメッセージを保存 +2. **友達の編集機能**: 名前やアドレスの変更 +3. **送金履歴の表示**: 過去のトランザクション一覧 +4. **通知機能**: 送金完了時のトースト通知 +5. **ダークモード**: UIのテーマ切り替え +6. **複数ウォレット対応**: MetaMask連携 ### 🙋‍♂️ 質問する @@ -58,4 +593,4 @@ title: アプリケーションの完成とテスト --- -プロジェクト完了おめでとうございます! 次のプロジェクトもお楽しみに! +これでAI Agent JPYC ChatAppのすべてのレッスンが完了しました! お疲れ様でした! From 1577ef36733d9d0e1d861a94f61f705965b0f926 Mon Sep 17 00:00:00 2001 From: Mameta29 Date: Tue, 4 Nov 2025 11:38:02 +0900 Subject: [PATCH 08/10] Add metadata for AI-Agent-JPYC-ChatApp project MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - description.json with project details - Placeholder images (to be replaced with project-specific images) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../AI-Agent-JPYC-ChatApp/description.json | 9 +++++++++ .../AI-Agent-JPYC-ChatApp/learn-banner.jpg | Bin 0 -> 246349 bytes .../metadata/AI-Agent-JPYC-ChatApp/square.png | Bin 0 -> 107656 bytes 3 files changed, 9 insertions(+) create mode 100644 public/metadata/AI-Agent-JPYC-ChatApp/description.json create mode 100644 public/metadata/AI-Agent-JPYC-ChatApp/learn-banner.jpg create mode 100644 public/metadata/AI-Agent-JPYC-ChatApp/square.png diff --git a/public/metadata/AI-Agent-JPYC-ChatApp/description.json b/public/metadata/AI-Agent-JPYC-ChatApp/description.json new file mode 100644 index 00000000..fb67a051 --- /dev/null +++ b/public/metadata/AI-Agent-JPYC-ChatApp/description.json @@ -0,0 +1,9 @@ +{ + "project_id": 201, + "title": "AI Agent JPYC ChatApp", + "difficulty": "intermediate", + "chain": "Ethereum", + "description": "👉 MCP と Mastra を使って、JPYC トークンを送金できる AI Agent チャットアプリを構築します。", + "total_sections": 5, + "total_lessons": 17 +} diff --git a/public/metadata/AI-Agent-JPYC-ChatApp/learn-banner.jpg b/public/metadata/AI-Agent-JPYC-ChatApp/learn-banner.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2c83baa1ee1d54204c6395fcd4fd2b875b18e9ae GIT binary patch literal 246349 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 z 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 literal 0 HcmV?d00001 diff --git a/public/metadata/AI-Agent-JPYC-ChatApp/square.png b/public/metadata/AI-Agent-JPYC-ChatApp/square.png new file mode 100644 index 0000000000000000000000000000000000000000..c2851ce4d9c4e90ca031fd7f4ab64cc0ff569c4e GIT binary patch literal 107656 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

$&axdhutyHNx4t8{iI5VL+oObs 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 Ef{FW4SO5S3 literal 0 HcmV?d00001 From 036103ae9b7bf05615a0befacdcb180504b8b440 Mon Sep 17 00:00:00 2001 From: Mameta29 Date: Wed, 5 Nov 2025 14:54:59 +0900 Subject: [PATCH 09/10] =?UTF-8?q?=E3=80=8C=E9=80=81=E9=87=91=E3=80=8D?= =?UTF-8?q?=E3=82=92=E3=80=8C=E9=80=81=E4=BF=A1=E3=80=8D=E3=81=AB=E7=B5=B1?= =?UTF-8?q?=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../section-1/lesson-0.md | 6 +- .../section-1/lesson-1.md | 61 +++++++------------ .../section-1/lesson-2.md | 6 +- .../section-1/lesson-3.md | 18 +++--- .../section-1/lesson-4.md | 2 +- .../section-1/lesson-5.md | 4 +- .../section-3/lesson-1.md | 4 +- .../section-3/lesson-2.md | 22 +++---- .../section-3/lesson-3.md | 4 +- .../section-4/lesson-3.md | 10 +-- .../section-5/lesson-1.md | 2 +- .../section-5/lesson-2.md | 4 +- .../section-5/lesson-4.md | 12 ++-- 13 files changed, 68 insertions(+), 87 deletions(-) diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-0.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-0.md index b77f9992..33a71217 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-0.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-0.md @@ -6,7 +6,7 @@ title: プロジェクトの概要 このプロジェクトでは、AI AgentとJPYC(日本円ステーブルコイン)を組み合わせたインタラクティブなチャットアプリケーションを構築します。 -AI Agentが自律的にJPYCを使った送金や残高確認などの操作を行える、次世代のAI×web3のアプリケーションを体験しましょう。 +AI Agentが自律的にJPYCを使った送信や残高確認などの操作を行える、次世代のAI×web3のアプリケーションを体験しましょう。 ### 🎯 このプロジェクトで学べること @@ -34,7 +34,7 @@ AI Agentが自律的にJPYCを使った送金や残高確認などの操作を このプロジェクトでは、以下の機能を持つチャットアプリケーションを構築します: - **AI Agentとの自然な対話**:ユーザーはAI Agentと自然言語でコミュニケーション -- **JPYC送金機能**:「〇〇さんに100 JPYC送って」とお願いすると、AI Agentが自動で送金処理 +- **JPYC送信機能**:「〇〇さんに100 JPYC送って」とお願いすると、AI Agentが自動で送信処理 - **残高確認機能**:「残高を教えて」と聞くと、AI Agentが現在のJPYC残高を確認 - **トランザクション履歴**:過去の取引履歴をAI Agentが取得・表示 @@ -46,7 +46,7 @@ AI Agentが自律的にJPYCを使った送金や残高確認などの操作を **実用的なステーブルコイン体験** -JPYCは日本円と1:1でペッグされたステーブルコインです。価格変動が少ないため、実際の決済や送金のユースケースに最適です。 +JPYCは日本円と1:1でペッグされたステーブルコインです。価格変動が少ないため、実際の決済や送信のユースケースに最適です。 **最新技術の習得** diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md index b6792ae6..131bc2ed 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-1.md @@ -2,72 +2,53 @@ title: JPYCについて --- +※ 本コンテンツはJPYC株式会社による公式コンテンツではありません。 + ### 💴 JPYC とは? JPYC(JPY Coin)は、日本円と1:1でペッグされた**日本円ステーブルコイン**です。 -2025年8月18日に、JPYC株式会社は資金決済法第37条に基づく**資金移動業者(第二種)**の登録を取得しました(関東財務局長 第00099号)。これは**国内初となる日本円建ステーブルコイン発行にかかるライセンス取得**であり、2025年10月27日より正式に発行が開始されています。 - -JPYCは法的に**電子決済手段**として認定されており、1 JPYC = 1円での償還が保証されています。ステーブルコインとは、法定通貨(この場合は日本円)の価値に連動するように設計された電子決済手段です。 +2025年8月に、JPYC株式会社は資金決済法に基づく**資金移動業者(第二種)**の登録を得ました。これにより、国内で最初の、日本円と1:1で連動する電子決済手段(ステーブルコイン)を発行可能な資金移動業者となり、2025年10月27日より正式に発行を開始しています。 詳細は[JPYC公式サイト](https://jpyc.co.jp/)をご覧ください。 ### 🔑 JPYC の特徴 -**1. 価格の安定性と償還保証** - -JPYCは常に1 JPYC = 1円の価値を維持するように設計されています。電子決済手段として認定されたことで、1 JPYC = 1円での日本円への償還が保証されています。ビットコインやイーサリアムのような価格変動がないため、日常的な決済や送金に適しています。 +**1. 高速かつ低コストな送信** -**2. 高速かつ低コストな送金** - -従来の銀行振込と比較して、JPYCを使った送金は下記の特徴があります: -- 24時間365日いつでも送金可能 +従来の銀行振込と比較して、JPYCを使った送信は下記の特徴があります: +- 24時間365日いつでも送信可能 - 数秒〜数分で着金 - 低い手数料(ブロックチェーンの手数料のみ) -**3. プログラマビリティ** +**2. プログラマビリティ** -JPYCはERC20規格(イーサリアム互換)のトークンの拡張として発行されており、スマートコントラクトと組み合わせることで、自動送金や条件付き決済などの複雑な処理を実装できます。 +JPYCはERC20規格(イーサリアム互換)のトークンの拡張として発行されており、スマートコントラクトと組み合わせることで、自動送信や条件付き決済などの複雑な処理を実装できます。 -**4. 透明性とトレーサビリティ** +**3. 透明性とトレーサビリティ** すべての取引がブロックチェーン上に記録されるため、透明性が高く、取引履歴を追跡することができます。 -### 🌐 JPYC の利用可能なチェーン - -JPYCは複数のブロックチェーンで発行されています: +**4. JPYCは複数のブロックチェーンで発行** - **Ethereum**(イーサリアム) - **Polygon**(ポリゴン) - **Avalanche**(アバランチ) -### 🎯 JPYC のユースケース例 - -**決済・送金** -- ECサイトでの商品購入 -- 個人間の送金 -- 給与や報酬の支払い - -**DeFi(分散型金融)** -- レンディング(貸し借り) -- 流動性プール -- イールドファーミング - -**web3アプリケーション** -- NFTマーケットプレイスでの取引 -- ゲーム内通貨 -- DAO(分散型自律組織)での運用 - ### 📖 JPYC の仕組み -JPYCは**電子決済手段**として発行されており、資金移動業者としてのライセンスに基づいて運営されています。 +JPYCの発行と償還は、専用プラットフォーム「JPYC EX」を通じて行われます。 +ユーザーが保有しているJPYCは、不特定多数の間で、自由に、金額の制限なく移転が可能です。 -1. ユーザーが日本円をJPYC株式会社に預ける -2. 預けた金額と同額のJPYCが発行される -3. ユーザーはJPYCを自由に使用・送金できる -4. JPYCを日本円に戻したい場合、1 JPYC = 1円で償還を申請できる +発行の手順 +1. 本人確認したユーザーが発行予約を行う。 +2. 予約時に指定された銀行口座に、銀行振込で送信する +2. 振込金額と同額のJPYCが発行される -JPYCの発行と償還は、専用プラットフォーム「JPYC EX」を通じて行われます。 +償還の手順 +1. 本人確認したユーザーが償還予約を行う。 +2. 予約時に指定されたアドレスに、JPYCを送信する +3. 送信したJPYCと同額の日本円が登録の出金先口座に振込される。 ### 💡 このプロジェクトでの JPYC の役割 @@ -75,7 +56,7 @@ JPYCの発行と償還は、専用プラットフォーム「JPYC EX」を通じ - **総供給量確認**:JPYCの流通額を取得 - **残高確認**:ユーザーのJPYC残高を取得 -- **送金処理**:指定されたアドレスにJPYCを送金 +- **送信処理**:指定されたアドレスにJPYCを送信 AI Agentが自然言語での指示を理解し、これらの操作を自動的に実行することで、より直感的なweb3体験を提供します。 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-2.md index 534abe7e..6df4e029 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-2.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-2.md @@ -28,16 +28,16 @@ const balance = await jpyc.balanceOf(address); console.log(`残高: ${balance} JPYC`); ``` -**3. 送金処理** +**3. 送信処理** -指定したアドレスにJPYCを送金します。 +指定したアドレスにJPYCを送信します。 ```typescript const tx = await jpyc.transfer( recipientAddress, amount ); -console.log(`送金完了: ${tx.hash}`); +console.log(`送信完了: ${tx.hash}`); ``` ### 📦 JPYC SDK のインストール diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-3.md index e5daa2f9..41a3f10a 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-3.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-3.md @@ -47,7 +47,7 @@ AI Agentが実行できる具体的な機能です。例: - APIの呼び出し - ファイル操作 -このプロジェクトでは、JPYCの残高確認や送金などがツールになります。 +このプロジェクトでは、JPYCの残高確認や送信などがツールになります。 **3. メモリ(Memory)** @@ -69,31 +69,31 @@ AI Agentは、以下のようなループで動作します: このサイクルを、目標が達成されるまで繰り返します。 -### 💬 具体例:JPYC 送金の場合 +### 💬 具体例:JPYC 送信の場合 ユーザーが「太郎さんに100 JPYC送って」と指示した場合: ``` 1. 入力の理解 - → 「送金」というアクションが必要 - → 送金先:太郎さん - → 送金額:100 JPYC + → 「送信」というアクションが必要 + → 送信先:太郎さん + → 送信額:100 JPYC 2. 計画の立案 Step 1: 太郎さんのウォレットアドレスを取得 - Step 2: 送金を実行 + Step 2: 送信を実行 Step 3: 結果をユーザーに報告 3. ツールの実行 - アドレス帳ツールで太郎さんのアドレスを検索 - - 送金ツールで送金を実行 + - 送信ツールで送信を実行 4. 結果の評価 - - 送金が成功したかを確認 + - 送信が成功したかを確認 - エラーがあれば原因を特定 5. 応答の生成 - 「太郎さん(0x123...)に100 JPYCを送金しました。 + 「太郎さん(0x123...)に100 JPYCを送信しました。 トランザクションID: 0xabc...」 ``` diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md index 32896984..3ee0d935 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-4.md @@ -156,7 +156,7 @@ MCPは、様々なAI Agentフレームワークで利用できます: **提供するツール:** 1. `jpyc_balance` - 残高照会 -2. `jpyc_transfer` - 送金 +2. `jpyc_transfer` - 送信 3. `jpyc_switch_chain` - チェーン切り替え 4. `jpyc_get_current_chain` - 現在のチェーン取得 5. `jpyc_total_supply` - 総供給量照会 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md index 349ee89a..fd9824d0 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-5.md @@ -83,7 +83,7 @@ instructions: ` 以下の操作が可能です: - 残高照会 - - 送金処理 + - 送信処理 - チェーン切り替え ## 回答スタイル: @@ -210,7 +210,7 @@ await jpycAgent.generate('私の残高は?', { threadId }); // 同じスレッドで続けて会話(コンテキストを保持) await jpycAgent.generate('半分を太郎さんに送って', { threadId }); -// → コンテキストから「500 JPYC」と推測して送金 +// → コンテキストから「500 JPYC」と推測して送信 ``` ### 🎯 モデルの設定 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md index 460c1ce4..763ed270 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-1.md @@ -204,7 +204,7 @@ export const jpyc = { }, /** - * JPYCを送金するメソッド + * JPYCを送信するメソッド * @param params * @returns */ @@ -316,7 +316,7 @@ export const jpyc = { - **totalSupply()**: JPYCの総供給量を取得 - **balanceOf()**: 指定したアドレスの残高を取得 -- **transfer()**: JPYCを送金 +- **transfer()**: JPYCを送信 これらのメソッドは、内部でJPYC SDKを呼び出し、結果を適切な形式で返します。 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md index f69bd0f8..4204bc52 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-2.md @@ -88,16 +88,16 @@ export const jpycBalanceTool = createTool({ }); /** - * JPYC送金ツール - * JPYCトークンを指定したアドレスに送金します(現在選択されているテストネット) + * JPYC送信ツール + * JPYCトークンを指定したアドレスに送信します(現在選択されているテストネット) */ export const jpycTransferTool = createTool({ id: "jpyc_transfer", description: - "JPYCトークンを指定したアドレスに送金します(現在選択されているテストネット)。例: 10 JPYCを0x123...に送る", + "JPYCトークンを指定したアドレスに送信します(現在選択されているテストネット)。例: 10 JPYCを0x123...に送る", inputSchema: z.object({ to: z.string().describe("送信先のEthereumアドレス (0xから始まる42文字)"), - amount: z.number().describe("送金額(JPYC単位、例: 10)"), + amount: z.number().describe("送信額(JPYC単位、例: 10)"), }), execute: async ({ context }) => { try { @@ -106,7 +106,7 @@ export const jpycTransferTool = createTool({ const currentChain = getCurrentChain(); const chainName = getChainName(currentChain); - // SDKのtransferメソッドを呼び出してJPYCを送金する + // SDKのtransferメソッドを呼び出してJPYCを送信する const txHash = await jpyc.transfer({ to: to as `0x${string}`, value: amount, @@ -116,7 +116,7 @@ export const jpycTransferTool = createTool({ return { success: true, - message: `✅ ${amount} JPYCを ${to} に送金しました(${chainName})`, + message: `✅ ${amount} JPYCを ${to} に送信しました(${chainName})`, transactionHash: txHash, explorerUrl: `${explorerUrl}${txHash}`, chain: currentChain, @@ -270,7 +270,7 @@ createTool({ ```typescript inputSchema: z.object({ to: z.string().describe("送信先のEthereumアドレス (0xから始まる42文字)"), - amount: z.number().describe("送金額(JPYC単位、例: 10)"), + amount: z.number().describe("送信額(JPYC単位、例: 10)"), }), ``` @@ -282,13 +282,13 @@ Zodは、TypeScriptの型検証ライブラリです。`inputSchema`で定義し ```typescript description: - "JPYCトークンを指定したアドレスに送金します(現在選択されているテストネット)。例: 10 JPYCを0x123...に送る", + "JPYCトークンを指定したアドレスに送信します(現在選択されているテストネット)。例: 10 JPYCを0x123...に送る", ``` `description`は、AI Agentがこのツールをいつ使うべきかを判断するための重要な情報です。 例えば、ユーザーが「太郎に100JPYC送って」と言った場合、AIは: -1. この`description`を読んで「送金する」ツールであることを理解 +1. この`description`を読んで「送信する」ツールであることを理解 2. `inputSchema`を参照して、`to`(送信先)と`amount`(金額)が必要だと認識 3. 適切なパラメータを抽出して`execute`を呼び出す @@ -306,7 +306,7 @@ const balanceString = await jpyc.balanceOf({ アドレスが指定されていない場合は、自分のアドレスの残高を返します。前のレッスンで作成したWrapperの`jpyc.balanceOf()`を呼び出します。 -**jpyc_transfer(送金)** +**jpyc_transfer(送信)** ```typescript const txHash = await jpyc.transfer({ to: to as `0x${string}`, @@ -314,7 +314,7 @@ const txHash = await jpyc.transfer({ }); ``` -JPYCを送金し、トランザクションハッシュを返します。ブロックチェーンエクスプローラーのURLも生成して返すことで、ユーザーがトランザクションを確認できるようにします。 +JPYCを送信し、トランザクションハッシュを返します。ブロックチェーンエクスプローラーのURLも生成して返すことで、ユーザーがトランザクションを確認できるようにします。 **jpyc_switch_chain(チェーン切り替え)** ```typescript diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md index 5afaea1b..c2f65721 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-3/lesson-3.md @@ -96,7 +96,7 @@ httpServer.listen(PORT, () => { ║ ║ ║ Available Tools: ║ ║ - jpyc_balance (残高照会) ║ -║ - jpyc_transfer (送金) ║ +║ - jpyc_transfer (送信) ║ ║ - jpyc_switch_chain (チェーン切り替え) ║ ║ - jpyc_get_current_chain (現在のチェーン取得) ║ ║ - jpyc_total_supply (総供給量照会) ║ @@ -241,7 +241,7 @@ pnpm mcp:dev ║ ║ ║ Available Tools: ║ ║ - jpyc_balance (残高照会) ║ -║ - jpyc_transfer (送金) ║ +║ - jpyc_transfer (送信) ║ ║ - jpyc_switch_chain (チェーン切り替え) ║ ║ - jpyc_get_current_chain (現在のチェーン取得) ║ ║ - jpyc_total_supply (総供給量照会) ║ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md index 548da391..9ea4a073 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-4/lesson-3.md @@ -46,7 +46,7 @@ export const jpycAgent = new Agent({ 以下の操作が可能です: 1. **チェーン切り替え**: テストネットを変更 -2. **送金**: 指定したアドレスにJPYCを送金(現在選択中のチェーン) +2. **送信**: 指定したアドレスにJPYCを送信(現在選択中のチェーン) 3. **残高照会**: アドレスのJPYC残高を確認(現在選択中のチェーン、アドレス省略時は自分の残高) 4. **総供給量照会**: JPYCの総供給量を確認(現在選択中のチェーン) @@ -54,7 +54,7 @@ export const jpycAgent = new Agent({ ## 名前を使った操作について: メッセージの最後に[ユーザー情報]として、ユーザーの名前と友達リストが含まれている場合があります。 -- 「太郎に100JPYC送って」のような名前を使った送金指示の場合、友達リストから該当する名前のアドレスを探してjpyc_transferを実行してください +- 「太郎に100JPYC送って」のような名前を使った送信指示の場合、友達リストから該当する名前のアドレスを探してjpyc_transferを実行してください - 「太郎の残高教えて」のような場合、友達リストから該当する名前のアドレスを探してjpyc_balanceを実行してください - 「残高教えて」や「私の残高」のような場合は、自分のアドレスを使用してjpyc_balanceを実行してください - 友達リストに該当する名前がない場合は、「{名前}さんは友達リストに登録されていません」と返答してください @@ -80,7 +80,7 @@ export const jpycAgent = new Agent({ - チャットアプリのような自然な会話を心がけてください ## 回答例: -- **送金成功時**: +- **送信成功時**: 「{to} に {amount} JPYC送りました!トランザクションは[こちらで確認]({explorerUrl})できます({chainName})」 名前を使った場合: 「{friendName}さんに {amount} JPYC送りました!トランザクションは[こちらで確認]({explorerUrl})できます({chainName})」 @@ -184,7 +184,7 @@ instructions: ` **ツール使用の指針** - どのような指示でどのツールを使うか - パラメータの抽出方法 -- 複数ステップの操作(チェーン切り替え→送金) +- 複数ステップの操作(チェーン切り替え→送信) **名前ベース操作** - 友達リストからアドレスを検索 @@ -210,7 +210,7 @@ instructions: ` **回答フォーマットを指定** ``` -- **送金成功時**: +- **送信成功時**: 「{to} に {amount} JPYC送りました!トランザクションは[こちらで確認]({explorerUrl})できます({chainName})」 ``` diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md index 68e29529..f763a7fd 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-1.md @@ -250,7 +250,7 @@ catch (error) { 5. jpyc_transfer ツールを呼び出し { to: "0x...", amount: 100 } ↓ -6. MCPサーバー経由でJPYC SDKが送金実行 +6. MCPサーバー経由でJPYC SDKが送信実行 ↓ 7. トランザクションハッシュを取得 ↓ diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md index 31ff7dae..3824a549 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-2.md @@ -6,7 +6,7 @@ title: ローカルストレージの実装 このレッスンでは、ユーザーのプロフィールと友達リストをブラウザのlocalStorageに保存する機能を実装します。 -これにより、ユーザーは名前とアドレスを登録し、友達の名前を使ってJPYC送金ができるようになります。 +これにより、ユーザーは名前とアドレスを登録し、友達の名前を使ってJPYC送信ができるようになります。 ### 📝 実装するファイル @@ -326,7 +326,7 @@ export function deleteFriend(id: string): void { ↓ 4. AI Agentが友達リストから太郎のアドレスを検索 ↓ -5. jpyc_transferツールで送金実行 +5. jpyc_transferツールで送信実行 ``` 次のレッスンでは、これらの関数を使用するチャットインタフェースを実装します。 diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md index dd61f1b7..9f1c79c4 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-5/lesson-4.md @@ -534,11 +534,11 @@ pnpm dev 2. 「友達を追加」をクリック 3. 友達リストに追加されることを確認 -**名前を使った送金** +**名前を使った送信** 1. 設定画面を閉じる 2. チャット欄に「太郎に100JPYC送って」と入力(太郎は友達リストに登録済みの名前) -3. AI Agentが友達リストから太郎のアドレスを検索し、送金を実行 +3. AI Agentが友達リストから太郎のアドレスを検索し、送信を実行 4. トランザクションハッシュ付きの応答が返ることを確認 **友達の残高照会** @@ -554,14 +554,14 @@ pnpm dev このアプリケーションでは、以下の機能が実装されています: **AI Agent機能** -- 自然言語でのJPYC操作(送金、残高照会、総供給量照会) +- 自然言語でのJPYC操作(送信、残高照会、総供給量照会) - マルチチェーン対応(Ethereum Sepolia、Avalanche Fuji) - チェーン切り替え機能 **ユーザー管理機能** - プロフィール設定(名前、アドレス) - 友達リスト管理(追加、削除) -- 名前を使った送金・残高照会 +- 名前を使った送信・残高照会 **チャットUI** - リアルタイムストリーミング応答 @@ -575,8 +575,8 @@ pnpm dev 1. **会話履歴の保存**: localStorageにメッセージを保存 2. **友達の編集機能**: 名前やアドレスの変更 -3. **送金履歴の表示**: 過去のトランザクション一覧 -4. **通知機能**: 送金完了時のトースト通知 +3. **送信履歴の表示**: 過去のトランザクション一覧 +4. **通知機能**: 送信完了時のトースト通知 5. **ダークモード**: UIのテーマ切り替え 6. **複数ウォレット対応**: MetaMask連携 From a66c157a17e637a24e0a0b985f2234a947d61a21 Mon Sep 17 00:00:00 2001 From: Mameta29 Date: Wed, 5 Nov 2025 21:46:06 +0900 Subject: [PATCH 10/10] =?UTF-8?q?add=20=E5=85=8D=E8=B2=AC=E4=BA=8B?= =?UTF-8?q?=E9=A0=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-0.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-0.md b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-0.md index 33a71217..5245b7a1 100644 --- a/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-0.md +++ b/docs/AI/AI-Agent-JPYC-ChatApp/section-1/lesson-0.md @@ -4,6 +4,12 @@ title: プロジェクトの概要 ### 👋 AI Agent × JPYC チャットアプリへようこそ +```sh +※ 本サービス(コンテンツ・作品等)はJPYC株式会社による公式コンテンツではありません。 +※ 「JPYC」はJPYC株式会社の提供するステーブルコインです。 +※ JPYC及びJPYCロゴは、JPYC株式会社の登録商標です。 +``` + このプロジェクトでは、AI AgentとJPYC(日本円ステーブルコイン)を組み合わせたインタラクティブなチャットアプリケーションを構築します。 AI Agentが自律的にJPYCを使った送信や残高確認などの操作を行える、次世代のAI×web3のアプリケーションを体験しましょう。