
Claude Code で AWS 公式プラグイン「deploy-on-aws」を使ってシンプルなAPIをデプロイしてみた
はじめに
みなさん Claude Code でプラグインを使っているでしょうか。
AWS が公式で提供している awslabs/agent-plugins というリポジトリにdeploy-on-aws というプラグインがあります。
アーキテクチャの選定からコスト見積、CDK コード生成、デプロイまでを一気通貫でやってくれるとのことです。「本当にそこまでやってくれるのかな」と思いつつ、実際にインストールしてお試し URL 短縮サービスをデプロイしてみました。
何が嬉しいのか
5 ステップのワークフローで迷わない
deploy-on-aws は Analyze → Recommend → Estimate → Generate → Deploy という 5 ステップのワークフローで動きます。「どのサービスを使えばいいか」という判断を Claude Code が担ってくれます。
3 つの MCP サーバーがリアルタイムで知識を補完
プラグインをインストールすると、以下の 3 つの MCP サーバーが自動で設定されます。
| MCP サーバー | 役割 |
|---|---|
| awsknowledge | アーキテクチャ判断・AWS ドキュメントの参照 |
| awspricing | リアルタイムのコスト見積 |
| awsiac | IaCのベストプラクティス適用 |
Claude Code の学習データだけでなく、最新の AWS 情報をリアルタイムで参照しながら提案してくれるのは嬉しいですね。
セキュリティの基準が明確
プラグインに含まれるリファレンスの security.md には セキュリティのデフォルトが定義されています。
S3 のプライベート設定、HTTPS 強制、IAM 最小権限、暗号化が生成されるコードに自動で含まれる設計です。
前提条件
- Claude Code v2.1.29 以降
- AWS CLI が設定済み
- Node.js(CDK 実行用)
- uvx(
awspricing、awsiacMCP サーバー実行用)
インストール手順
以下の 2 コマンドでインストールできます。
❯ /plugin marketplace add awslabs/agent-plugins
❯ /plugin install deploy-on-aws@agent-plugins-for-aws
インストール後、プラグインの.mcp.json に 3 つの MCP サーバーが設定されます。
{
"mcpServers": {
"awsiac": {
"args": [
"awslabs.aws-iac-mcp-server@latest"
],
"command": "uvx"
},
"awsknowledge": {
"type": "http",
"url": "https://knowledge-mcp.global.api.aws"
},
"awspricing": {
"args": [
"awslabs.aws-pricing-mcp-server@latest"
],
"command": "uvx",
"disabled": false,
"env": {
"FASTMCP_LOG_LEVEL": "ERROR"
},
"timeout": 120000,
"type": "stdio"
}
}
}
やってみる
実際にプラグインをインストールした状態で、URL 短縮サービスをデプロイしてみました。
プラグインを実行
以下のコマンドで作成したいものを伝えてみます。
❯ /deploy-on-aws:deploy URL短縮サービスを作りたい
1. 分析 & 推奨サービス
以下のように要望に応じた分析と推奨のアーキテクチャが提案されます。
| レイヤー | サービス | 理由 |
|---|---|---|
| API | API Gateway (HTTP API) | シンプルなREST API、低コスト |
| コンピュート | Lambda (Node.js 22.x) | ステートレスAPI、フレームワーク不要 |
| データベース | DynamoDB (オンデマンド) | key-valueアクセスパターンに最適 |
| IaC | CDK (TypeScript) | 型安全、最も表現力が高い |
2. 月額コスト見積もり(dev環境、ap-northeast-1、月10,000リクエスト想定)
合わせてアーキテクチャのコスト見積もりも MCP サーバーを使って出力されます。
| サービス | 月額費用 | 内訳 |
|---|---|---|
| API Gateway (HTTP API) | ~$0.01 | $1.29/100万リクエスト |
| Lambda | ~$0.00 | 無料枠内(100万リクエスト/月、40万GB秒) |
| DynamoDB (オンデマンド) | ~$0.01 | $1.4269/100万WRU, $0.2854/100万RRU |
| 合計 | ~$0.02/月 | 無料枠適用で実質$0に近い |
アーキテクチャを検討する上でコストを踏まえて確認できるのはいいですね。
今回はお試しなので、このまま進めてみます。
生成されたコード
構成の承認後、CDK プロジェクトと Lambda 関数のコードが自動生成されました。中身を見てみましょう。
CDK スタック(インフラ定義)
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigwv2 from 'aws-cdk-lib/aws-apigatewayv2';
import * as apigwv2Integrations from 'aws-cdk-lib/aws-apigatewayv2-integrations';
import * as path from 'path';
export class UrlShortenerStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// DynamoDB Table - オンデマンド、暗号化有効
const table = new dynamodb.Table(this, 'UrlTable', {
partitionKey: { name: 'shortId', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
encryption: dynamodb.TableEncryption.AWS_MANAGED,
pointInTimeRecovery: true,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
// Lambda Function
const fn = new lambda.Function(this, 'UrlShortenerFn', {
runtime: lambda.Runtime.NODEJS_22_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(path.join(__dirname, '..', 'lambda')),
memorySize: 128,
timeout: cdk.Duration.seconds(10),
environment: {
TABLE_NAME: table.tableName,
},
architecture: lambda.Architecture.ARM_64,
});
// 最小権限: Lambda → DynamoDB
table.grantReadWriteData(fn);
// HTTP API (API Gateway v2)
const httpApi = new apigwv2.HttpApi(this, 'UrlShortenerApi', {
apiName: 'url-shortener',
corsPreflight: {
allowOrigins: ['*'],
allowMethods: [apigwv2.CorsHttpMethod.GET, apigwv2.CorsHttpMethod.POST],
},
});
const integration = new apigwv2Integrations.HttpLambdaIntegration(
'LambdaIntegration',
fn,
);
// POST /shorten - URL短縮
httpApi.addRoutes({
path: '/shorten',
methods: [apigwv2.HttpMethod.POST],
integration,
});
// GET /{shortId} - リダイレクト
httpApi.addRoutes({
path: '/{shortId}',
methods: [apigwv2.HttpMethod.GET],
integration,
});
// Outputs
new cdk.CfnOutput(this, 'ApiUrl', {
value: httpApi.apiEndpoint,
description: 'URL Shortener API endpoint',
});
new cdk.CfnOutput(this, 'TableName', {
value: table.tableName,
description: 'DynamoDB table name',
});
}
}
前半で触れた「セキュリティのデフォルト」が実際に適用されているか確認してみます。
- DynamoDB の暗号化
encryption: AWS_MANAGEDとポイントインタイムリカバリが有効
- IAM 最小権限
table.grantReadWriteData(fn)で Lambda に必要な権限だけを付与
- ARM64 を選択してコスト最適化
- REST API ではなく HTTP API(API Gateway v2) を選択し、低コスト構成
そのままデプロイできるレベルのコードが生成されました。
一点気になったのが、dynamodb.Table が使われている点です。現在の CDK では TableV2 がすべてのユースケースで推奨されており、今後プラグイン側のアップデートで最新のコンストラクトが使われることを期待したいですね。
Lambda 関数(アプリケーション)
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, PutCommand, GetCommand } from '@aws-sdk/lib-dynamodb';
import { randomBytes } from 'crypto';
const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);
const TABLE_NAME = process.env.TABLE_NAME;
export const handler = async (event) => {
const { httpMethod, path, body, pathParameters } = parseEvent(event);
if (httpMethod === 'POST' && path === '/shorten') {
return await shortenUrl(JSON.parse(body));
}
if (httpMethod === 'GET' && pathParameters?.shortId) {
return await redirectUrl(pathParameters.shortId);
}
return { statusCode: 404, body: JSON.stringify({ error: 'Not found' }) };
};
async function shortenUrl({ url }) {
if (!url) {
return { statusCode: 400, body: JSON.stringify({ error: 'url is required' }) };
}
const shortId = randomBytes(4).toString('hex');
await docClient.send(new PutCommand({
TableName: TABLE_NAME,
Item: { shortId, originalUrl: url, createdAt: new Date().toISOString() },
}));
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ shortId, shortUrl: `/${shortId}` }),
};
}
async function redirectUrl(shortId) {
const result = await docClient.send(new GetCommand({
TableName: TABLE_NAME,
Key: { shortId },
}));
if (!result.Item) {
return { statusCode: 404, body: JSON.stringify({ error: 'URL not found' }) };
}
return {
statusCode: 301,
headers: { Location: result.Item.originalUrl },
body: '',
};
}
function parseEvent(event) {
return {
httpMethod: event.requestContext?.http?.method || event.httpMethod,
path: event.rawPath || event.path,
body: event.body,
pathParameters: event.pathParameters,
};
}
Lambda のコードもシンプルで読みやすいですね。AWS SDK v3 の DynamoDBDocumentClient を使っています。shortenUrl(短縮 URL 作成)と redirectUrl(リダイレクト)の 2 つのエンドポイントを処理しています。
デプロイ
コードが作成されたら CDK をデプロイします。
❯ npm exec cdk deploy --profile test-account --require-approval broadening
✅ UrlShortenerStack
✨ Deployment time: 64.19s
Outputs:
UrlShortenerStack.ApiUrl = https://i3mv7mhbyg.execute-api.ap-northeast-1.amazonaws.com
UrlShortenerStack.TableName = UrlShortenerStack-UrlTable6FBD0DEA-1DN2HNO7UG7DC
Stack ARN:
arn:aws:cloudformation:ap-northeast-1:111111111111:stack/UrlShortenerStack/382b8a10-2986-11f1-a894-0e59a1265639
ApiUrl が確認できるので実行してみましょう。
❯ curl -s -X POST https://i3mv7mhbyg.execute-api.ap-northeast-1.amazonaws.com/shorten \
-H 'Content-Type: application/json' \
-d '{"url":"https://dev.classmethod.jp"}'
{"shortId":"76dddba5","shortUrl":"/76dddba5"}
shortId が返ってきたので、リダイレクトされるか確認してみます。
❯ curl -s -o /dev/null -w "%{http_code} %{redirect_url}" \
https://i3mv7mhbyg.execute-api.ap-northeast-1.amazonaws.com/76dddba5
301 https://dev.classmethod.jp/
問題なく 301 でリダイレクトされています。
数分で API の用意からアプリケーションの動作確認までが完了しました。
まとめ
deploy-on-aws プラグインで URL 短縮サービスを実際にデプロイできました。
今回は実装規模が小さいため、非常にシンプルな構成で実装できました。
全く手直しなしで利用できるというわけではないですが、動くものをすぐに作成できます。特にプラグインの実行で意思決定する部分がはっきりしており、判断箇所が見やすいのもいいですね。
ぜひプラグインを導入して AWS のベストプラクティスに沿った開発をしていきましょう。
以上、鈴木純がお送りしました。







