クロス イノベーション 本部、新卒1年目の大岡叡です。 今回は、1月29日にプレビュー公開された AWS Deployment SOPsを使ってみたので、その内容を報告します。 AWS Deployment SOPsを使ってみた結果、簡単なプロンプトを一度与えるだけで静的Webサイトをデプロイでき、CodePipelineのCI/CDについても簡単に構築することができました。この検証を通じて、非エンジニアがインフラ構築をして簡単なアプリケーションのデプロイを行う日も遠くないのではないかと思ったと同時に、 フルスタ ックアプリケーションも今回のように簡単なプロンプトを一度与えるだけでデプロイできる時代が来るのではないかと、期待が膨らみました。 AWS MCP Serverとは AWS Knowledge Tools AWS API Tools Agent SOP Tools AWS Deployment SOPsとは 検証の前提 検証1:Next.jsアプリケーションのデプロイ 検証内容 実装してくれたCDKのコード Deployment SOPsなしの場合 検証2:CodePipelineのセットアップ 検証内容 実装してくれたCDKのコード まとめ 参考文献 AWS MCP Serverとは AWS Deployment SOPsの説明をするうえで前提となる AWS MCP Server について説明します。 AWS MCP Serverは8つのツールを提供しており、 AWS Knowledge Tools 、 AWS API Tools 、 Agent SOP Tools の3つのカテゴリに分類されています。 AWS Knowledge Tools aws___search_documentation : API リファレンス・ベストプラクティス・サービスガイドを含む、すべての AWS ドキュメントを横断的に検索して関連情報を見つける。 aws___read_documentation : AWS ドキュメントページを取得し、 AIアシスタント が利用しやすいように Markdown 形式に変換する。 aws___recommend : AWS ドキュメントページに関連するトピックや、他のユーザーがよく一緒に閲覧しているコンテンツに基づいて、おすすめのドキュメントページを取得する。 aws___list_regions :リージョンID(例:ap-northeast-1)と名称(例:Asia Pacific (Tokyo))のペアの一覧を取得する。 aws___get_regional_availability :サービス、機能、 SDK API 、CloudFormationリソースについて、 AWS リージョンごとの利用可否情報を確認する。 AWS API Tools aws___call_aws : AWS API の呼び出しを実行する。 aws___suggest_aws_commands :関連する AWS API の説明と構文ヘルプを取得する。AIモデルの学習データに含まれていない可能性がある、新しくリリースされた API にも対応できる。 Agent SOP Tools aws___retrieve_agent_sop :Agent SOPsの検索または特定のSOPsの詳細情報の取得をする。 💡 Agent SOPsとは Agent SOPsとは、Claude Codeのような AIアシスタント が AWS 関連のタスクを行う際の標準作業手順書(Standard Operating Procedures)のことです。例えば、以下のようなSOPが用意されています。 SOP名 説明 create-secrets-using-best-practices ローテーション機能とKMSを備えたSecrets Managerによるシークレット作成 create-budget アラート機能付きの AWS Budgets作成 setup_cloudwatch_alarm_notifications SNS 経由でのCloudWatchアラーム通知セットアップ application-failure-troubleshooting CloudWatchログを分析してアプリケーション障害を デバッグ AWS Deployment SOPsとは AWS Deployment SOPsは、 aws___retrieve_agent_sop のツールが取得するデプロイ用のSOPのことです。 以下の4つのSOPがDeployment SOPsです。 SOP名 説明 deploy-webapp アプリケーションがDeployment SOPsでサポートされているものか確認し、適切なDeployment SOPを選択する。 deploy-frontend-app AWS CDKのコードを生成し、アプリケーションをデプロイした後、デプロイしたWebアプリのURLを提供する。 setup-pipeline AWS CodePipelineを使用してパイプラインを作成し、 GitHub に変更がプッシュされると自動的にアプリケーションの検証とデプロイを行う。 document-deployment デプロイに関するドキュメントを生成し、進捗を管理する。 Deployment SOPsがサポートしているアプリケーションタイプは以下のとおりです。 SPA:React, Vue, Angular, SvelteKit SSG:Next.js (static export), Nuxt, Gatsby , Hugo, Jekyll, Docusaurus, Astro, Eleventy Static websites そして、Deployment SOPsは2つの ユースケース 「 AWS へのアプリケーションのデプロイ」と「CodePipelineのセットアップ」をサポートしています。今回はこの2つの ユースケース を実際に試してみました。 検証の前提 今回はコーディングエージェントとしてClaude Codeを使用しました。 Skills等のカスタマイズ系のものは使用しないようにしました。 AWS CLI (認証情報設定済み)やGit CLI などの必要なツールはインストール済みです。 プロジェクトのルートで、以下のような .mcp.json を配置しました。 { " mcpServers ": { " aws-mcp ": { " command ": " uvx ", " args ": [ " mcp-proxy-for-aws@latest ", " https://aws-mcp.us-east-1.api.aws/mcp " ] } } } あらかじめ以下のようなTODOアプリケーションをNext.jsの静的エクスポートで実装しました。これはプロジェクトのルート ディレクト リにtodo-appという ディレクト リ名で配置しました。 検証1:Next.jsアプリケーションのデプロイ Claude Codeの挙動ベースで検証内容を報告します。結果としては、簡単なプロンプトを一度与えるだけでCloudFront + S3の構成を構築してデプロイを行い、CloudFrontのURLを共有してくれました。 検証内容 最初に「 AWS MCP の AWS Deployment SOPsを用いて、todo-appを AWS にデプロイしてください。」というプロンプトをClaude Codeに投げました(ちなみに、この検証で投げたプロンプトはこれだけです)。すると、 AWS MCP Serverの aws___retrieve_agent_sop を用いてdeploy-webappのSOPを取得してきて、アプリケーションがDeployment SOPsでサポートされているタイプか分析してくれました。 アプリケーションのファイルの読み込みが完了した後、 AWS MCP Serverの aws___retrieve_agent_sop を用いてdeploy-frontend-appのSOPを取得してきてくれました。そして、Next.jsの静的エクスポートはデプロイ可能ということで、デプロイ開始宣言をしてくれました。 続いて、 DEPLOYMENT_PLAN.md を生成してくれました。これ以降はこのプランに従って自律的に実装を進めてくれました。 --- sop_name: deploy-frontend-app, setup-pipeline repo_name: aws-deployment-sops-test app_name: TodoApp app_type: Frontend Application (Next.js Static Export) branch: main created: 2026-02-01 last_updated: 2026-02-01 --- # Deployment Plan: TodoApp Coding Agents should follow this Deployment Plan, and validate previous progress if picking up the Deployment in a new coding session. **IMPORTANT**: Update this plan after EACH step completes. Mark the step `[x]` and update `last_updated` timestamp. ## Phase 1: Gather Context and Configure - [x] Step 0: Inform User of Execution Flow - [x] Step 1: Create Deployment Plan - [] Step 2: Create Deploy Branch - [] Step 3: Detect Build Configuration - [] Step 4: Validate Prerequisites - [] Step 5: Revisit Deployment Plan ## Phase 2: Build CDK Infrastructure - [] Step 6: Initialize CDK Foundation - [] Step 7: Generate CDK Stack - [] Step 8: Create Deployment Script - [] Step 9: Validate CDK Synth ## Phase 3: Deploy and Validate - [] Step 10: Execute CDK Deployment - [] Step 11: Validate CloudFormation Stack ## Phase 4: Update Documentation - [] Step 12: Finalize Deployment Plan - [] Step 13: Update README.md そして、最終的にCloudFrontのURLを提供してくれました。このURLをクリックしたら実際にデプロイされたアプリケーションが正常に動作していることを確認できました。 実装してくれたCDKのコード 実際にClaude Codeが生成してくれたCDKのコードを以下に示します。CloudFront(Distribution, CloudFront Function)、S3(Webサイト用)、S3(CloudFront アクセスログ 用)、S3(S3 アクセスログ 用)などがセキュリティのベストプラクティスに基づいて実装されています。 import * as cdk from "aws-cdk-lib" ; import * as cloudfront from "aws-cdk-lib/aws-cloudfront" ; import * as s3deploy from "aws-cdk-lib/aws-s3-deployment" ; import { CloudFrontToS3 } from "@aws-solutions-constructs/aws-cloudfront-s3" ; import { Construct } from "constructs" ; export interface FrontendStackProps extends cdk.StackProps { environment : string ; buildOutputPath : string ; } export class FrontendStack extends cdk.Stack { public readonly distributionDomainName : string ; public readonly bucketName : string ; constructor ( scope : Construct , id : string , props : FrontendStackProps ) { super (scope, id, props); const { environment , buildOutputPath } = props; const isProd = environment === "prod" ; const removalPolicy = isProd ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY; // CSP via CloudFront Function - permissive policy for 3rd-party CDNs/APIs const cspFunction = new cloudfront.Function( this , "CspFunction" , { runtime : cloudfront.FunctionRuntime.JS_2_0, code : cloudfront.FunctionCode.fromInline( ` function handler(event) { var response = event.response; response.headers['content-security-policy'] = { value: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https: data: blob:; style-src 'self' 'unsafe-inline' https:; font-src 'self' https: data:; img-src 'self' https: data: blob:; connect-src 'self' https: wss:; frame-src 'self' https:; media-src 'self' https: blob:; worker-src 'self' https: blob:; object-src 'self' https:; manifest-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" }; return response; } ` ), comment : "Adds Content-Security-Policy header" , } ); // Extension rewrite function for Next.js static export (trailingSlash: false) // Rewrites /path to /path.html const extensionRewriteFunction = new cloudfront.Function( this , "ExtensionRewriteFunction" , { runtime : cloudfront.FunctionRuntime.JS_2_0, code : cloudfront.FunctionCode.fromInline( ` function handler(event) { var request = event.request; var uri = request.uri; if (!uri.includes('.') && uri !== '/') { request.uri = uri + '.html'; } return request; } ` ), comment : "Rewrites /path to /path.html for Next.js static export" , } ); const cloudfrontToS3 = new CloudFrontToS3( this , "CFToS3" , { bucketProps : { removalPolicy , autoDeleteObjects : !isProd, versioned : false , enforceSSL : true , } , loggingBucketProps : { removalPolicy , autoDeleteObjects : !isProd, lifecycleRules : [{ id : "DeleteOldLogs" , enabled : true , expiration : isProd ? cdk.Duration.days( 3650 ) : cdk.Duration.days( 7 ) }] , enforceSSL : true , } , cloudFrontLoggingBucketProps : { removalPolicy , autoDeleteObjects : !isProd, lifecycleRules : [{ id : "DeleteOldLogs" , enabled : true , expiration : isProd ? cdk.Duration.days( 3650 ) : cdk.Duration.days( 7 ) }] , enforceSSL : true , } , insertHttpSecurityHeaders : false , cloudFrontDistributionProps : { comment : ` ${ id } - ${ environment } ` , defaultRootObject : "index.html" , defaultBehavior : { responseHeadersPolicy : cloudfront.ResponseHeadersPolicy.SECURITY_HEADERS, functionAssociations : [ { function : cspFunction, eventType : cloudfront.FunctionEventType.VIEWER_RESPONSE, } , { function : extensionRewriteFunction, eventType : cloudfront.FunctionEventType.VIEWER_REQUEST, } , ] , } , priceClass : cloudfront.PriceClass.PRICE_CLASS_100, enableIpv6 : true , httpVersion : cloudfront.HttpVersion.HTTP2_AND_3, minimumProtocolVersion : cloudfront.SecurityPolicyProtocol.TLS_V1_2_2021, } , } ); const websiteBucket = cloudfrontToS3.s3Bucket!; const distribution = cloudfrontToS3.cloudFrontWebDistribution; new s3deploy.BucketDeployment( this , "DeployWebsite" , { sources : [ s3deploy.Source.asset(buildOutputPath) ] , destinationBucket : websiteBucket, distribution , distributionPaths : [ "/*" ] , prune : true , memoryLimit : 512 , } ); this .distributionDomainName = distribution.distributionDomainName; this .bucketName = websiteBucket.bucketName; // Outputs new cdk.CfnOutput( this , "WebsiteURL" , { value : `https:// ${ distribution.distributionDomainName } ` , description : "CloudFront distribution URL" , exportName : ` ${ id } -WebsiteURL` , } ); new cdk.CfnOutput( this , "BucketName" , { value : websiteBucket.bucketName, description : "S3 bucket name" , exportName : ` ${ id } -BucketName` , } ); new cdk.CfnOutput( this , "DistributionId" , { value : distribution.distributionId, description : "CloudFront distribution ID" , exportName : ` ${ id } -DistributionId` , } ); new cdk.CfnOutput( this , "DistributionDomainName" , { value : distribution.distributionDomainName, description : "CloudFront domain name" , exportName : ` ${ id } -DistributionDomain` , } ); if (cloudfrontToS3.s3LoggingBucket) { new cdk.CfnOutput( this , "S3LogBucketName" , { value : cloudfrontToS3.s3LoggingBucket.bucketName, description : "Bucket for S3 access logs" , exportName : ` ${ id } -S3LogBucket` , } ); } if (cloudfrontToS3.cloudFrontLoggingBucket) { new cdk.CfnOutput( this , "CloudFrontLogBucketName" , { value : cloudfrontToS3.cloudFrontLoggingBucket.bucketName, description : "Bucket for CloudFront access logs" , exportName : ` ${ id } -CloudFrontLogBucket` , } ); } cdk.Tags.of( this ). add ( "Stack" , "Frontend" ); cdk.Tags.of( this ). add ( "aws-mcp:deploy:sop" , "deploy-frontend-app" ); cdk.Tags.of(cloudfrontToS3). add ( "Stack" , "Frontend" ); cdk.Tags.of(cloudfrontToS3). add ( "aws-mcp:deploy:sop" , "deploy-frontend-app" ); } } 以上より、「 AWS MCP の AWS Deployment SOPsを用いて、todo-appを AWS にデプロイしてください。」と一言お願いをすれば、それなりの構成でインフラを構築してくれて、アプリケーションをデプロイできることを確認できました。これなら非エンジニアの方でも簡単かつ安全にアプリケーションをデプロイできるのではないでしょうか。 Deployment SOPsなしの場合 Deployment SOPsを使用せずにClaude Codeに「todo-appを AWS にデプロイしてください。」とお願いしたらどうなるか試してみました。ここでは非エンジニアがデプロイする想定で、条件などを一切与えずにお願いしました。こちらも検証1と同様、Claudeの指示に基本従う方針で進めました。 最初にdeploy方法の選択を迫られました。Recommendedの AWS Amplifyを選択しました。 デプロイを進めてくれて、最終的にAmplifyのURLを表示してくれました。 しかし、このURLにアクセスしたところ、以下のようなWebページでした。 Amplifyへのデプロイ手順はCloudFront + S3構成と比べて複雑ではないものの、単に「デプロイして」と依頼するだけでは、現状のClaude Codeでは自律的にタスクを完遂することが難しいようです。 検証2:CodePipelineのセットアップ Claude Codeの挙動ベースに検証内容を報告します。CodePipelineが構築され、 GitHub にプッシュするだけで変更が自動的にデプロイされる仕組みが整いました。 検証内容 最初に「 AWS MCP の AWS Deployment SOPsを用いて、CodePipelineをセットアップしてください。」というプロンプトをClaude Codeに投げました。すると、 AWS MCP Serverの aws___retrieve_agent_sop を用いてsetup-pipelineのSOPを取得してきて、CodePipelineのセットアップを開始してくれました。 次に以下のような確認をされました。lintエラーの修正だけお願いしておきました。 検証1と同様にDEPLOYMENT_PLAN.mdを更新しながらCDKのコード実装など色々やってくれた後に、以下の認証をお願いされました。これは手順通り対応しました。 その後、パイプラインのデプロイなど色々やってくれてタスクが完了しました。 CodePipelineの動作を確認するために以下のようにh1の中身に変更を加えて、deploy-to- aws ブランチにプッシュしたところ、CodePipelineがトリガーされてビルド→デプロイが実行され、Webページに変更内容が反映されました。 実装してくれたCDKのコード 実際にClaude Codeが生成してくれたCDKのコードを以下に示します。CodePipeline、CodeBuildプロジェクト、S3 バケット ( アーティファクト 用)が構築されます。 import * as cdk from "aws-cdk-lib" ; import * as codebuild from "aws-cdk-lib/aws-codebuild" ; import * as codepipeline from "aws-cdk-lib/aws-codepipeline" ; import * as pipelines from "aws-cdk-lib/pipelines" ; import { Construct } from "constructs" ; import { FrontendStack } from "./frontend-stack" ; export interface PipelineStackProps extends cdk.StackProps { codeConnectionArn : string ; repositoryName : string ; branchName : string ; } export class PipelineStack extends cdk.Stack { public readonly pipeline : pipelines.CodePipeline ; constructor ( scope : Construct , id : string , props : PipelineStackProps ) { super (scope, id, props); const source = pipelines.CodePipelineSource. connection ( props.repositoryName, props.branchName, { connectionArn : props.codeConnectionArn, triggerOnPush : true , } ); const synth = new pipelines.ShellStep( "Synth" , { input : source, commands : [ // Install dependencies "(cd todo-app && npm install)" , "(cd infra && npm install)" , // Quality checks "(cd todo-app && npm run lint)" , // Secret scanning "npx -y @secretlint/quick-start '**/*'" , // Build frontend "(cd todo-app && npm run build)" , // CDK synth "cd infra" , "npx tsc" , `npx -y cdk synth --context codeConnectionArn=" ${ props.codeConnectionArn } " --context repositoryName=" ${ props.repositoryName } " --context branchName=" ${ props.branchName } "` , ] , primaryOutputDirectory : "infra/cdk.out" } ); this .pipeline = new pipelines.CodePipeline( this , "Pipeline" , { pipelineName : "TodoAppPipeline" , selfMutation : true , pipelineType : codepipeline.PipelineType.V2, synth , synthCodeBuildDefaults : { buildEnvironment : { computeType : codebuild.ComputeType.MEDIUM, buildImage : codebuild.LinuxBuildImage.STANDARD_7_0 } , partialBuildSpec : codebuild.BuildSpec.fromObject( { version : "0.2" , phases : { install : { "runtime-versions" : { nodejs : "latest" , } , } , } , } ), } , } ); // Deploy stage for production const deployStage = new cdk.Stage( this , "Deploy" , { env : { account : this .account, region : this . region } , } ); new FrontendStack(deployStage, "TodoAppFrontend-prod" , { stackName : "TodoAppFrontend-prod" , environment : "prod" , buildOutputPath : "../todo-app/out" , } ); this .pipeline.addStage(deployStage); // Build pipeline to enable property access this .pipeline.buildPipeline(); cdk.Tags.of( this ). add ( "Stack" , "Pipeline" ); cdk.Tags.of( this ). add ( "aws-mcp:deploy:sop" , "setup-pipeline" ); new cdk.CfnOutput( this , "PipelineName" , { value : "TodoAppPipeline" , description : "CodePipeline Name" , } ); new cdk.CfnOutput( this , "PipelineArn" , { value : this .pipeline.pipeline.pipelineArn, description : "CodePipeline ARN" , } ); } } まとめ AWS Deployment SOPsを用いて、静的エクスポートしたNext.jsアプリケーションをデプロイしたり、CodePipelineのセットアップを行いました。特に問題なくAIがすべての作業を完了してくれたことは驚きでした。近い将来、非エンジニアでもデプロイを行える日は遠くないと感じました。さらに、 フルスタ ックアプリケーションも簡単なプロンプトを一度与えるだけで構築できる時代が来るのではないかと、期待が膨らみました。 最後までお読みいただきありがとうございました! 参考文献 https://docs.aws.amazon.com/aws-mcp/latest/userguide/what-is-mcp-server.html https://docs.aws.amazon.com/aws-mcp/latest/userguide/getting-started-aws-mcp-server.html https://docs.aws.amazon.com/aws-mcp/latest/userguide/understanding-mcp-server-tools.html https://docs.aws.amazon.com/aws-mcp/latest/userguide/agent-sops.html https://docs.aws.amazon.com/aws-mcp/latest/userguide/agent-sops-deployment.html https://aws.amazon.com/jp/about-aws/whats-new/2025/01/aws-announces-deployment-agent-sops-in-aws-mcp-server-preview/ 私たちは一緒に働いてくれる仲間を募集しています! 電通総研 キャリア採用サイト 電通総研 新卒採用サイト 執筆: @ooka.toru レビュー: @miyazawa.hibiki ( Shodo で執筆されました )