MCP による AI Agents 活用の設計:AIによるインフラ操作
|
AI MCP Automation LLM Claude Cloudflare Infrastructure
Model Context Protocol(MCP)とAIを使って定型的なインフラ操作を自動化した記録。Claude DesktopとAWSをMCPで連携させてみた実装メモです。
Part 1: MCP とは
「AIに道具を渡すプロトコル」= 「AIが外部のツールやAPIを自分で呼び出せるようにする仕組み」
通常のAIチャット:
ユーザー → [質問] → AI → [テキストで回答]
MCP使用時:
ユーザー → [質問] → AI → [ツールを呼び出す判断]
↓
[MCP Server]
↓
[外部API・DBなどを実行]
↓
[結果をAIに返す]
↓
AI → [結果を踏まえて回答]
AIが外部API呼び出しや外部DB操作を実行できるようになります。
Part 2: MCP Server の実装(TypeScript)
プロジェクトのセットアップ
mkdir infra-mcp-server && cd infra-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk @aws-sdk/client-ecs \
@aws-sdk/client-cloudwatch-logs @aws-sdk/client-ec2 \
@aws-sdk/client-ecr zod
npm install -D typescript @types/node tsx
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"strict": true
}
}
Tool の定義と実装
// src/server.ts
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import { CloudWatchLogsClient, FilterLogEventsCommand } from '@aws-sdk/client-cloudwatch-logs';
import { z } from 'zod';
const AWS_REGION = process.env.AWS_REGION ?? 'ap-northeast-1';
const logs = new CloudWatchLogsClient({ region: AWS_REGION });
const server = new Server(
{ name: 'infra-mcp-server', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
// ── Tool の一覧を返す ──────────────────────────────
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'search_cloudwatch_errors',
description: '指定したロググループから ERROR ログを検索して返す。障害調査の最初のステップ。',
inputSchema: {
type: 'object',
properties: {
logGroupName: { type: 'string', description: 'CloudWatch ロググループ名' },
minutesAgo: { type: 'number', description: '何分前からのログを検索するか(デフォルト: 60)' },
filterPattern:{ type: 'string', description: 'CloudWatch フィルターパターン(デフォルト: ERROR)' },
},
required: ['logGroupName'],
}},
]
}));
// ── Tool の実行ロジック ───────────────────────────
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
// CloudWatch ログ検索
case 'search_cloudwatch_errors': {
const { logGroupName, minutesAgo = 60, filterPattern = 'ERROR' } = z.object({
logGroupName: z.string(),
minutesAgo: z.number().default(60),
filterPattern: z.string().default('ERROR'),
}).parse(args);
const startTime = Date.now() - minutesAgo * 60 * 1000;
const res = await logs.send(new FilterLogEventsCommand({
logGroupName,
startTime,
filterPattern,
limit: 20,
}));
const events = (res.events ?? []).map(e =>
`[${new Date(e.timestamp ?? 0).toISOString()}] ${e.message?.trim()}`
).join('\n');
return {
content: [{
type: 'text',
text: events.length > 0
? `Found ${res.events?.length} events:\n\n${events}`
: `No ${filterPattern} events in the last ${minutesAgo} minutes`,
}],
};
}
default:
throw new Error(`Unknown tool: ${name}`);
}
});
Tool の description は人間ではなく AI に向けて書きます。「いつこのToolを使うべきか」が伝わる説明にするほど、AIが適切なタイミングで呼び出してくれます。
Part 3: Claude Desktop での設定
{
"mcpServers": {
"infra": {
"command": "node",
"args": ["/path/to/infra-mcp-server/dist/server.js"],
"env": {
"AWS_REGION": "ap-northeast-1",
"AWS_PROFILE": "my-aws-profile"
}
}
}
}
Part 4: 「任せられる範囲」の設計
MCPでAIを活用するうえで大事なのは、どこまで任せるか 読み取り操作は問題になりづらく、破壊的操作は大事故と隣り合わせです。
設計例:
✅ AIに全委譲してよい操作(読み取り専用):
- CloudWatch ログの検索・集計
- Cost Explorer でのコスト照会
- S3 バケットの一覧の確認
→ 何も変更しないので、誤判断しても被害なし
⚠️ AIが提案し、人間が承認する操作:
- 古いイメージの削除(dry_run→確認→実行の2ステップ)
- S3 オブジェクトの削除
→ AIが「何を、なぜ変更するか」を提示し、人間がYesを押す
🚫 AIに渡さない、Toolとして定義しない操作:
- terraform apply の実行
- IAM ポリシーの変更
- RDS インスタンスの削除
- S3 バケット自体の削除
- 本番環境の環境変数変更
→ MCP Server のコード上にToolとして存在させない
= AIがそもそも実行できない構造
Toolの権限が上限 AIがどんなミスをしても、Toolとして実装されていない操作は実行できません。
Part 5: MCP Serverのセキュリティ設計
ローカル実行時の認証
// 環境変数から AWS 認証情報を取得(ハードコード禁止)
// ~/.aws/credentials の named profile か IAM Instance Profile を使う
const ecs = new ECSClient({
region: process.env.AWS_REGION,
// credentials は SDK が自動解決(環境変数・profile・IMDS の順)
});
// MCP Server に渡す IAM ポリシーは最小権限で
// 読み取り専用Toolなら ReadOnly ポリシーのみ
// 変更系Toolは対象リソースを ARN で絞る
Zod によるInput Validation
// 全 Tool の引数を Zod で厳密にバリデート
// AI が不正な引数(負の desired count 等)を渡しても弾かれる
const { desiredCount } = z.object({
desiredCount: z.number().min(0).max(100), // 0〜100 の範囲外は拒否
}).parse(args);
まとめ:
MCPを使ったAIエージェント活用の設計は 「AIの実行範囲をコードで定義する」 作業です。
スクリプトやcronによる自動化には、当然ですが判断がなく、状況変化やイレギュラーな場合に対応できません。 MCPによってToolを与えられたAIは、想定外の結果が出たら別のアプローチを試みる、といった臨機応変な対応を可能にします。 ただし、勝手に判断して実行してくれるが故に、出来ることの範囲(=権限)は人間が細心の注意を払って設計する必要があります。
| 観点 | スクリプト自動化 | MCP + AI Agent |
|---|---|---|
| 定型手順の実行 | ✅ 得意 | ✅ 得意(かつ自然言語で指示可能) |
| 状況に応じた判断 | ❌ 苦手 | ✅ 得意(ログの内容を読んで次の手を考える) |
| 権限の制御 | IAM で制御 | IAM + Tool定義の2層で制御 |
| 実行の透明性 | ログのみ | AIの「思考過程」が可視化される |
| 破壊的操作の安全性 | スクリプトの品質次第 | dry_run + 人間承認ステップを構造化できる |
「AIにインフラを触らせるのは怖い」からこそ、怖い操作をToolとして定義しないという設計判断が何よりも大事になります。
この記事をシェア