AWS S3 と連携する MCP サーバーを作ってみてわかったこと 🪣🔌🤖
MCP とは?
Model Context Protocol (MCP)の説明としてはざっくり以下です。
- コア機能: AI モデルが外部ツールやデータソースにアクセスできるようにする
- 主なメリット: 学習データを超えて AI 機能を拡張する
- 例え: AI モデル用の「USB-C」のような役割 - 汎用的なコネクター
- 実装: 開発者が LLM に接続できる MCP サーバーを作成する
MCP アーキテクチャ
公式 MCP ドキュメントによると、MCP は言語モデルと外部コンポーネント間の標準化された通信プロトコルを確立します:
- クライアント・サーバーアーキテクチャ: LLM は機能を公開する MCP サーバーに接続
コアコンポーネント:
- Tool: 特定のアクション(検索や計算など)を実行する機能
- Resource: 外部データ(ファイル、データベース、API)へのアクセスポイント
※ 他にも Prompt, Sampling Roots などのコンポーネントがありますが、この記事では触れません。
┌────────────────┐ ┌───────────────────────────────┐
│ LLM Platform │ │ MCP Server │
│ │ │ │
│ ┌────────────┐ │ │ ┌────────┐ ┌─────────┐ │
│ │ Claude/GPT │ │ │ │MCP SDK │<--->│Custom │ │
│ └────────────┘ │ │ │ │ │Server │ │
│ ▲ │ │ └────────┘ └────┬────┘ │
│ │ │ │ │ │
│ ┌────────────┐ │ │ ▼ │
│ │MCP Client │◄├─────┤ ┌─────────────┐ │
│ └────────────┘ │ │ │External API │ │
└────────────────┘ │ └─────────────┘ │
└───────────────────────────────┘
このアーキテクチャにより、LLM は以下のことが可能になります:
- 学習データを超えたリアルタイム情報にアクセスする
- カスタム統合不要で特殊なツールを使用する
- 保護されたリソースに制御された方法でアクセスする
aws-s3-mcp: AWS S3 と連携する MCP サーバー
この動画では、予め AWS S3 バケット内に保存した PDF ファイルを取得し、その内容を要約するデモ
実装
aws-s3-mcp
サーバーは 3 つのコアツールを実装しています:
- list-buckets: 利用可能な S3 バケットを表示
- list-objects: 特定のバケット内のファイルを表示
- get-object: ファイルコンテンツの取得と処理(ex. PDF の場合はバイナリからテキスト変換)
使用した主要技術:
- TypeScript: 型安全性と最新の開発機能のため
- AWS SDK v3: S3 との連携
-
MCP SDK:
@modelcontextprotocol/sdk
からプロトコル実装のため - pdf-parse: PDF ファイルからテキストを抽出するため
実装の概要としては以下のような内容:
// すべてのツール実装で使用するIMCPToolインターフェース定義
export interface IMCPTool<
TParams extends Record<string, z.ZodType> = Record<string, z.ZodType>
> {
// ツール名
readonly name: string;
// ツールの説明
readonly description: string;
// パラメータ定義
readonly parameters: TParams;
// ツールの実行
execute(args: InferZodParams<TParams>): Promise<{
content: {
type: "text";
text: string;
[key: string]: unknown;
}[];
isError?: boolean;
[key: string]: unknown;
}>;
}
// 実装例: List Buckets Tool
export class ListBucketsTool implements IMCPTool {
readonly name = "list-buckets";
readonly description = "List available S3 buckets";
readonly parameters = {} as const;
constructor(private s3Resource: S3Resource) {}
async execute() {
try {
const buckets = await this.s3Resource.listBuckets();
return {
content: [
{
type: "text" as const,
text: JSON.stringify(buckets, null, 2),
},
],
};
} catch (error) {
return createErrorResponse(
error,
`Error listing buckets: ${
error instanceof Error ? error.message : String(error)
}`
);
}
}
}
MCP サーバーのセキュリティ考慮事項
AWS S3 のような特にクラウドリソースにアクセスする MCP サーバーでは、セキュリティが重要です。
実際に Equixly 2025 セキュリティ分析によると、MCP サーバーにはいくつかの一般的な脆弱性があります:
- 🚨 コマンドインジェクション: 分析された MCP サーバーの 43%が脆弱
- 🔍 パストラバーサル: サーバーの 22%が影響を受ける
- 🌐 サーバーサイドリクエストフォージェリ(SSRF): サーバーの 30%がリスクあり
アプローチ:Docker と Deno による分離
これらのセキュリティリスクを確保するために、Docker と Deno が効果的な方法です。
Deno を使用した Dockerfile:
FROM denoland/deno:latest
WORKDIR /app
# セキュリティ強化のための非rootユーザー作成
USER deno
# セキュリティを強化するためのDenoのPermission flagを使用して特定の権限制約を使用
ENTRYPOINT ["deno", "run", \
"--allow-net=s3.amazonaws.com", \
"--allow-env=AWS_REGION,AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY", \
"--allow-read=/app", \
"--allow-sys"]
CMD ["src/index.ts"]
これで以下のような要件の Dockerfile が作成されます:
- コンテナ分離: Docker は潜在的な被害を制限するサンドボックスを提供
-
非 Root 実行:
deno
ユーザーが特権を制限 - 権限ベースセキュリティ: Deno の明示的な権限システムが不正アクションを防止
- ネットワークセキュリティ: 必要なエンドポイントへの接続のみを許可
- 環境変数コントロール: 必要な環境変数のみを公開
安全な vs 不安全な設定
Claude Desktop で aws-s3-mcp サーバーを設定する場合、セキュリティはセットアップによって異なります:
安全でない設定:
"mcpServer": {
"command": "npx",
"args": ["aws-s3-mcp"],
"env": {
"AWS_ACCESS_KEY_ID": "your_key",
"AWS_SECRET_ACCESS_KEY": "your_secret"
}
}
安全な設定:
"mcpServer": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"AWS_REGION",
"-e",
"S3_BUCKETS",
"-e",
"AWS_ACCESS_KEY_ID",
"-e",
"AWS_SECRET_ACCESS_KEY",
"aws-s3-mcp:latest"
],
"env": {
"AWS_REGION": "us-east-1",
"S3_BUCKETS": "bucket1,bucket2",
"AWS_ACCESS_KEY_ID": "${YOUR_ACCESS_KEY}",
"AWS_SECRET_ACCESS_KEY": "${YOUR_SECRET_KEY}"
}
}
この設定により、Claude は分離のための Docker と認証情報のための環境変数を使用して、安全に AWS S3 バケットに接続します。claude_desktop_config.json
ファイルは以下の場所にあります:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
- Windows:
%APPDATA%\\Claude\\claude_desktop_config.json
設定後、変更を適用するために Claude Desktop を再起動してください。その後、Claude に S3 バケットとの対話を依頼できるようになります。
安全なアプローチでは、Docker 分離と環境変数を使用することで、認証情報の漏洩や不正アクセスのリスクを大幅に低減します。
残念ながら、main ブランチではまだ Docker + Deno による MCP サーバー起動の対応ができていないですが、別ブランチで Docker + Deno で、 MCP Inspector 上で動作はできます。
詳細に興味がある場合は、PR をチェックしてみてください。👇
https://github.com/samuraikun/aws-s3-mcp/pull/7
今は過度期で、ローカルで MCP サーバーを動かす必要はなくなる?
2025-3-26 に、MCP の仕様が更新され、Streamable HTTP が追加されました。
また、MCP の TypeScript SDK も更新され、Streamable HTTP に対応されました。
これにより、少なくとも TypeScript で MCP サーバーを開発する際は、今後は MCP サーバーをどこかしらにデプロイして、各 MCP クライアントはリモートの MCP サーバーに接続する形になると思います。他の言語の SDK も同様の対応がされるでしょう。
そのため、リモート MCP サーバーが普及すれば、ローカルで MCP サーバーを立てる必要はなくなっていくのではないかと思います。
実際にどう MCP サーバーをリモート MCP として実装するかは、こちらの記事が参考になりました。
まとめ
AWS S3 と連携する MCP サーバーを作ってみた結果:
- MCP 自体はシンプルなアーキテクチャで、SDK を使えば開発は難しくない
- サードパーティの MCP サーバーを利用する場合、セキュリティに注意が必要
- Docker と Deno を組み合わせることで、セキュリティを強化できる
- MCP 自体が、Streamable HTTP に対応したので今後は Remote MCP Server が増え、ローカルで MCP を動かす必要はなくなっていきそう
Discussion