📘

AWS LambdaをMCPサーバーとして利用してClaudeでEC2の起動・停止をする

に公開

はじめに

先日、AWSからLambdaをMCPサーバーとして使えるようにするライブラリ、AWS Lambda MCP Serverが公開されました。

最近なにかと話題のMCPサーバーをLambdaで実現できないのか、と考えていた私にとっては朗報だったので早速試してみました。

本記事では、AWS Lambda MCP Serverを使って、AWS LambdaをMCPサーバーとして実装し、Claudeを通じてEC2インスタンスの起動・停止する方法を紹介します。

実装

Lambdaの作成

まず、EC2インスタンスを制御するためのLambdaをpython3.13で作成します。

指定したタグを持つEC2をフィルタリングして、そのインスタンスの起動・停止を実施してインスタンスIDを返すだけのシンプルなLambdaです。

MCPサーバーとして利用できるように、LambdaにキーをManagedByで値をlambda-mcpのタグを付与します。
これをつけることによって、MCPサーバーとして認識されます。

import boto3
import os

TAG_KEY = os.environ.get('TARGET_TAG_KEY', 'MCP-Managed')
TAG_VALUE = os.environ.get('TARGET_TAG_VALUE', 'lambda-bastion-ec2-controller')

def lambda_handler(event: dict, context: dict) -> dict:
    """
    踏み台EC2サーバーを起動または停止する
    
    プロンプト例:
    「踏み台サーバーを起動して」
    「踏み台サーバーを停止して」
    """
    # 'action' パラメータを取得
    action = event.get('action')

    # 'action' が 'start' または 'stop' でない場合、エラーを返す
    if action not in ['start', 'stop']:
        return {'error': 'action は start または stop である必要があります'}
    
    # EC2クライアントを作成
    ec2 = boto3.client('ec2')
    filters = [
        {'Name': f'tag:{TAG_KEY}', 'Values': [TAG_VALUE]},
        {'Name': 'instance-state-name', 'Values': ['stopped' if action == 'start' else 'running']}
    ]

    try:
        # フィルタに基づいてインスタンスを取得
        instances = ec2.describe_instances(Filters=filters)
        instance_ids = [instance['InstanceId'] for reservation in instances['Reservations'] for instance in reservation['Instances']]
        
        # インスタンスが見つからない場合のメッセージを返す
        if not instance_ids:
            return {'message': f'{\"停止中\"if action == \"start\" else \"起動中\"}のインスタンスが見つかりません'}
        
        # 指定されたアクションを実行
        if action == 'start':
            ec2.start_instances(InstanceIds=instance_ids)
            return {'message': f'インスタンスを起動しました: {instance_ids}'}
        elif action == 'stop':
            ec2.stop_instances(InstanceIds=instance_ids)
            return {'message': f'インスタンスを停止しました: {instance_ids}'}

    except Exception as e:
        # エラーが発生した場合、エラーメッセージを返す
        return {'error': str(e)}

IAMロールの作成

LambdaがEC2インスタンスを操作するために必要な権限を付与するIAMロールを作成しアタッチします。

タグベースでフィルタリングを行ない、特定のタグを持つインスタンスのみを操作対象とするようにします。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeInstances"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:StopInstances",
        "ec2:StartInstances"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "ec2:ResourceTag/MCP-Managed": "lambda-bastion-ec2-controller"
        }
      }
    }
  ]
}

IAMユーザーの作成

MCPサーバーを実行する際にAWSの権限が必要になるのでIAMユーザーを作成し、以下のポリシーをアタッチします。
lambda:InvokeFunctionだけで良いと思ったら、MCPサーバーを起動する部分でlambda:ListFunctionslambda:ListTagsの権限も必要だったので、これらも追加しています。
作成後、認証情報を取得しlambda-mcpという名前のAWS PROFILEを作成します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "lambda:InvokeFunction"
      ],
      "Resource": [
        "<LambdaのARN>"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "lambda:ListFunctions",
        "lambda:ListTags"
      ],
      "Resource": "*"
    }
  ]
}

Claudeとの連携

Claudeとの連携Claude Desktopの設定ファイルに、MCPサーバーとして実装したLambdaを呼び出すための情報を追加します。

今回、envに設定する環境変数は以下の通りです:

  • AWS_PROFILE: MCPサーバーを実行するためのAWS PROFILE名
  • AWS_REGION: Lambdaがデプロイされているリージョン
  • FUNCTION_TAG_KEY: LambdaをMCPサーバーとして認識させるためのタグキー
  • FUNCTION_TAG_VALUE: LambdaをMCPサーバーとして認識させるためのタグ値

FUNCTION_TAG_KEYFUNCTION_TAG_VALUEで指定することによって、このタグを持つLambdaのみがMCPサーバーとして認識されます。

他にも下記のような環境変数も指定できます:

  • FUNCTION_LIST: "lambda-a,lambda-b,lambda-c"のように,で区切って指定することで、複数のLambdaをMCPサーバーとして認識させることができます。
  • FUNCTION_PREFIX: "lambda-"のように指定することで、特定のプレフィックスを持つLambdaをMCPサーバーとして認識させることができます。
"awslabs.lambda-mcp-server@latest": {
     "command": "uvx",
     "args": [
       "awslabs.lambda-mcp-server@latest"
     ],
     "env": {
       "AWS_PROFILE": "lambda-mcp",
       "AWS_REGION": "ap-northeast-1",
       "FUNCTION_TAG_KEY": "ManagedBy",
       "FUNCTION_TAG_VALUE": "lambda-mcp"
     }
   }

検証

実際にClaudeから操作できるかEC2を作成して確認してみました。

EC2インスタンスの起動

踏み台サーバーに見立ててタグをMCP-Managedで値をlambda-bastion-ec2-controllerにしたEC2を2台作成します。
EC2インスタンス作成画面1
EC2インスタンス作成画面2

MCP設定の確認

先ほど設定したものがClaudeにMCPサーバーとして認識されています。
MCP設定確認画面

停止

先ほど作成したEC2インスタンスを停止してみます。
1回目は処理がエラーになりましたが、すぐに2回目の実行を行なったところ成功しました。
停止処理が完了すると、停止したEC2のインスタンスIDが返ってきて、しばらくするとインスタンスが正常に停止したことを確認できました。
停止している状態でもう一度、停止をお願いすると、停止中のインスタンスが見つからないというメッセージが返ってきました。

EC2停止処理画面1
EC2停止処理画面2
EC2停止処理画面3

起動

次は、停止したEC2を起動してみます。
起動処理はスムーズに成功し、起動したEC2のインスタンスIDが返ってきました。
EC2起動処理画面1
EC2起動処理画面2

その他の操作検証

試しに「存在しない操作」として、EC2インスタンスの削除をClaudeに依頼してみました。Claudeは適切に機能し、Lambdaコードに削除操作が実装されていないことを説明してくれました。このように、コードで定義していない操作は実行されないため、誤って重要なリソースが削除されるリスクもありません。
その他の操作検証画面

まとめ

本記事では、AWS LambdaをMCPサーバーとして活用し、Claudeを介してEC2インスタンスの起動・停止を実施しました。自然言語でコマンドを伝えるだけで開発環境の起動・停止といった操作ができるため、AWS操作に不慣れな開発者でも便利に利用できます。

特筆すべき点として、タグベースでMCPサーバーとして認識される仕組みにより、既存のLambdaも簡単にMCP対応化できる柔軟性があります。

AWS Lambdaの汎用性を活かせば、広範囲な処理や運用タスクをAIに任せることも可能になるのではないでしょうか。今後は実際の開発のなかでも活用していきます。

参考資料

BLT SDC Tech Blog

Discussion