Generative AI Use Case JP (GenU) に Amazon S3 Tables MCP サーバーを組み込んで自然言語でデータ分析してみた

AWS

2025.9.3

Topics

概要

Amazon Bedrock Knowledge Bases 構造化データを使った自然言語でのデータ分析において、日本語対応に課題があったため、S3 Tables MCP サーバーを活用したアプローチを検証しました。

Bedrock Knowledge Bases 構造化データの内容については以下をご覧ください。

関連記事
Amazon Bedrock Knowledge Bases 構造化データを使って自然言語でデータ分析を行う

本記事では、GenU と S3 Tables MCP サーバーを組み合わせて自然言語でデータ分析を行う方法について記載します。

検証の大まかな流れは、以下の通りです。

  1. S3 Tables の作成
    1. テーブルバケットの作成
    2. サンプルデータ投入
  2. GenU の作成
    1. S3 Tables MCP サーバー設定追加
  3. S3 Tables MCP サーバーに対して自然言語でデータ分析をする

なお、今回は MCP チャットを使用しますが、MCP チャットは現在非推奨となっておりますのでご注意ください。

Warning
MCP チャットユースケースは Deprecated ステータスになりました。
MCP の活用には AgentCore ユースケースをご利用ください。MCP チャットユースケースは v6 で完全削除予定です。
generative-ai-use-cases/docs/ja/DEPLOY_OPTION.md at main · aws-samples/generative-ai-use-cases

後継の AgentCore を使った MCP サーバーの検証についても記録がありますので、併せてご確認ください。

関連記事
Generative AI Use Case JP (GenU) で AgentCore を使ってみる

S3 Tables の作成

以下の手順に沿って作成していきます。
チュートリアル: S3 Tables の開始方法 – Amazon Simple Storage Service

コンソールからテーブルバケットを作成します。

AWS S3のテーブルバケット作成画面

Athena からクエリを実行するため、「統合を有効にする」にチェックを入れます。

AWS分析サービスとの統合設定

テーブルバケットが作成完了しました。

テーブルバケット作成完了画面

続いては、テーブルを作成します。

S3バケット内の空のテーブル一覧

テーブルには、名前空間が必要なため作成します。

Athenaでのテーブル作成ダイアログ

実際に Iceberg テーブルを作成する場合は、Athena から SQL を実行します。
Iceberg テーブルを作成する – Amazon Athena

生成 AI で作成した、以下の SQL を実行して、テーブルとサンプルデータを作成します。

-- 注文データ用の ICEBERG テーブル作成
CREATE TABLE orders_data_iceberg (
  order_id string,
  tenant_id string,
  company_name string,
  user_id string,
  user_name string,
  product_name string,
  category string,
  quantity bigint,
  unit_price bigint,
  total_amount bigint,
  order_date date,
  region string,
  status string
) PARTITIONED BY (month(order_date))
TBLPROPERTIES ('table_type' = 'ICEBERG');

-- 注文データの挿入
INSERT INTO orders_data_iceberg VALUES
('ORD001', 'tenant_a', '株式会社 Alpha', 'user_a1', '田中太郎', 'ノート PC', 'Electronics', 2, 80000, 160000, DATE '2024-01-15', '東京', '完了'),
('ORD002', 'tenant_a', '株式会社 Alpha', 'user_a2', '佐藤花子', 'マウス', 'Electronics', 5, 3000, 15000, DATE '2024-01-16', '東京', '完了'),
('ORD003', 'tenant_b', 'Beta 商事', 'user_b1', '鈴木一郎', 'デスク', 'Furniture', 1, 50000, 50000, DATE '2024-01-17', '大阪', '処理中'),
-- 以下割愛

サンプルデータの準備が完了しました。

クエリ結果のデータテーブル

これで S3 Tables の設定が完了したので、次は GenU を構築します。

GenU の構築

以下のワークショップに沿って GenU の構築を行います。
生成 AI 体験ワークショップ

GenU で MCP を使うには、Docker のインストールが必要です。
そのため、EC2 上(Amazon Linux 2023)で Docker をセットアップしてから AWS CDK をデプロイをします。

MCP チャットユースケースを有効化するためには、docker コマンドが実行可能である必要があります。
generative-ai-use-cases/docs/ja/DEPLOY_OPTION.md at main · aws-samples/generative-ai-use-cases

mcpEnabledを true にすると MCP チャット が利用できるようになります。

[root@ip-10-0-1-183 generative-ai-use-cases]# grep mcpEnabled packages/cdk/cdk.json
    "mcpEnabled": true,

S3 Tables MCP サーバーの細かい設定は、注意点がいくつかあるため後述でまとめて記載します。
そのため、ひとまずはデフォルトで設定されている MCP サーバーを使用します。

packages/cdk/mcp-api/mcp.json

{
  "mcpServers": {
    "time": {
      "command": "uvx",
      "args": ["mcp-server-time"]
    },
    "awslabs.aws-documentation-mcp-server": {
      "command": "uvx",
      "args": ["awslabs.aws-documentation-mcp-server@latest"]
    },
    "awslabs.cdk-mcp-server": {
      "command": "uvx",
      "args": ["awslabs.cdk-mcp-server@latest"]
    },
    "awslabs.aws-diagram-mcp-server": {
      "command": "uvx",
      "args": ["awslabs.aws-diagram-mcp-server@latest"]
    },
    "awslabs.nova-canvas-mcp-server": {
      "command": "uvx",
      "args": ["awslabs.nova-canvas-mcp-server@latest"]
    }
  }
}

この状態でデプロイを行い、正常に MCP サーバーを利用することができました。

Bedrockのセキュリティに関するチャット

S3 Tables MCP サーバーを追加する

本題の S3 Tables MCP サーバーを追加します。
AWS S3 Tables MCP Server | AWS MCP Servers

手順は、 MCP チャットの設定ファイルに S3 Tables MCP サーバーの記載を追加するだけです。

packages/cdk/mcp-api/mcp.json

その際に 3 点ほど注意が必要です。

  • Lambda の IAM 権限
  • Lambda 内の Linux ディレクトリの権限不足
  • Lambda メモリ不足

詳細について後述で記載します。

Lambda 内の Linux ディレクトリの権限不足

ドキュメントに記載のあるデフォルトの MCP 設定をそのまま使用するとエラーが発生します。
AWS S3 Tables MCP Server | AWS MCP Servers

{
  "mcpServers": {
    "awslabs.s3-tables-mcp-server": {
      "command": "uvx",
      "args": ["awslabs.s3-tables-mcp-server@latest"],
      "env": {
        "AWS_PROFILE": "your-aws-profile",
        "AWS_REGION": "us-east-1"
      }
    }
  }
}

実際に実行すると以下のエラーが出力されます。

ERROR: Failed to create or write to log file in directory '/home/sbx_user1051/.local/share/s3-tables-mcp-server/logs/': [Errno 30] Read-only file system: '/home/sbx_user1051'

理由としては、Lambda で操作できないディレクトリにログを出力しようとするためです。
これは、S3 Tables MCP サーバーの設定で、ログの出力先を変更できるのでその設定を追加します。

ログディレクトリ設定のコード例

サンプルにあったディレクトリのパスをそのまま追加しました。

 "awslabs.s3-tables-mcp-server": {
      "command": "uvx",
      "args": ["awslabs.s3-tables-mcp-server@latest", "--log-dir","/tmp/s3-tables-logs"],
      "env": {
        "AWS_REGION": "us-east-1"
      }
    }

Lambda 関数のエフェメラルストレージを設定する – AWS Lambda
Lambda 分離テクノロジー – AWS Lambda のセキュリティの概要

Lambda メモリ不足

MCP チャットで、チャットを投げると「MCP サーバーと接続しています。時間がかかる場合があります。そのまま待機してください…」から応答がありません。

そこで、MCP サーバーで使用する Lambda のログを確認すると、メモリが Max まで使われてタイムアウトしていたので、Lambda のメモリを増設しました。

  • 1024 → 2048 に変更

以下、CDK のファイルを修正します。

packages/cdk/lib/construct/mcp-api.ts

const mcpFunction = new DockerImageFunction(this, "McpFunction", {
  code: DockerImageCode.fromImageAsset("./mcp-api"),
  memorySize: 2048,
  timeout: Duration.minutes(15),
  architecture: Architecture.ARM_64,
  environment: {
    AWS_LWA_INVOKE_MODE: "RESPONSE_STREAM",
  },
});

S3 Tables の権限不足

MCP サーバーで使用する Lambda には、デフォルトでは Bedrock の権限しか付与されてないです。

IAMロールのアクセス許可設定

Lambda から S3 Tables に対する処理を実行するため、Lambda の実行ロールに S3 Tables へのアクセス権限を付与する必要があります。

適切な権限がない状態で、MCP チャットを行うと以下のような結果が返ってきます。

S3 Tablesの権限エラー画面

IAM権限不足を示すエラーとSQL例

以下、CDK のファイルを修正します。
packages/cdk/lib/construct/mcp-api.ts

S3 Tables に関わる権限を追加しています。
※必要に応じて権限を設定してください

mcpFunction.role?.addToPrincipalPolicy(
  new PolicyStatement({
    effect: Effect.ALLOW,
    actions: [
      "s3tables:ListTableBuckets",
      "s3tables:ListNamespaces",
      "s3tables:ListTables",
      "s3tables:CreateTableBucket",
      "s3tables:CreateNamespace",
      "s3tables:CreateTable",
      "s3tables:GetTable",
      "s3tables:GetTableBucket",
      "s3tables:GetTableData",
      "s3tables:GetTableMaintenanceConfiguration",
      "s3tables:GetTableMaintenanceJobStatus",
      "s3tables:GetTableMetadataLocation",
      "s3tables:RenameTable",
      "s3tables:UpdateTableMetadataLocation",
      "s3tables:PutTableData",
      "s3:GetBucketMetadataConfiguration",
    ],
    resources: ["*"],
  })
);

自然言語でデータ分析する

一通り設定が完了したので、MCP チャットで自然言語を使ったデータ分析をしてみます。

まずは、S3 Tables のテーブル一覧を問い合わせます。

S3 Tablesのテーブル一覧とARN

トレースの内容は以下の通りです。

データベースの列情報JSON出力

続いては、実際にデータ分析をする 「orders_data_iceberg」 のテーブル定義を確認します。

orders_data_icebergのテーブル定義

トレースの内容は以下の通りです。

SQLクエリのJSON出力結果

では、「orders_data_iceberg テーブルから高橋さんの売上を分析して。」と投げます。
すると、サマライズされた結果が返ってきます。

顧客の売上分析結果の表示

トレースの内容は以下の通りです。

SQLクエリ実行時の連続エラー

何度かエラーが発生していますが、最終的にほしい結果が取得できています。

SQLクエリのJSON形式での出力

アウトプット

# 高橋次郎さんの売上分析結果

##  総合売上サマリー

| 項目 | 数値 |
|
| **総売上** | **¥436,500** |
| **注文回数** | **6回** |
| **平均注文金額** | **¥72,750** |
| **最小注文金額** | ¥12,500 |
| **最大注文金額** | ¥240,000 |
| **総購入数量** | 23個 |
| **購入期間** | 2024年1月23日 ~ 2024年4月11日 |

##  月別売上推移

### 2024年1月
- **売上**: ¥240,000 (55.0%)
- **商品**: タブレット × 4台

### 2024年2月
- **売上**: ¥74,000 (16.9%)
- **商品**: モバイルバッテリー × 10個、ポータブルSSD × 2個

### 2024年3月
- **売上**: ¥110,000 (25.2%)
- **商品**: ポータブルプロジェクター × 1台、モバイルディスプレイ × 1台

### 2024年4月
- **売上**: ¥12,500 (2.9%)
- **商品**: USB扇風機 × 5個

##  購入傾向分析

### 顧客プロフィール
- **所属**: 株式会社Alpha(tenant_a)
- **地域**: 名古屋
- **ユーザーID**: user_a3

### 購入パターン
1. **高額商品志向**: 初回購入でタブレット(¥240,000)という高額商品を購入
2. **継続的な購入**: 約2-3週間間隔で継続的に注文
1. **Electronics特化**: 全て電子機器カテゴリの商品
2. **実用性重視**: モバイル関連アクセサリーを多く購入

### 売上貢献度
- 高橋次郎さんは**優良顧客**として位置づけられます
- 初回購入が全体売上の55%を占める重要な顧客
- 継続的な購入により安定した売上を創出

### 今後の営業戦略提案
1. **クロスセル**: 関連するモバイルアクセサリーの提案
2. **アップセル**: より高性能な電子機器の提案
3. **定期購入**: 消耗品(バッテリー等)の定期購入プラン
4. **季節商品**: 夏季にUSB扇風機を購入している点から、季節商品の提案効果が期待できる

回答された内容も間違っていないので、自然言語でデータ分析が行えました。

ちなみに、MCP サーバーの設定がうまく行ってないときでも生成 AI によってそれらしい回答が返ってきます。
その場合、MCP サーバーを使用しているかはトレースの有無で判別できます。

チャットUIのトレースボタン

まとめ

自然言語でのデータ分析クエリも適切に処理され、日本語での問い合わせに対しても期待通りの結果が得られました。
Bedrock Knowledge Base 構造化データより、自由度が高いためプロンプトによって回答精度を上げることができそうです。

参考資料

Build a transactional data lake using Apache Iceberg, AWS Glue, and cross-account data shares using AWS Lake Formation and Amazon Athena | AWS Big Data Blog
【開催報告 & 資料公開】Apache Iceberg on AWS ミートアップ開催報告 | Amazon Web Services ブログ
チュートリアル: S3 Tables の開始方法 – Amazon Simple Storage Service

テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!

Cold-Airflow

2021年新卒入社。インフラエンジニアです。RDBが三度の飯より好きです。 主にデータベースやAWSのサーバレスについて書く予定です。あと寒いのは苦手です。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら