1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code に Pulumi のプラグインと MCP Server を入れるてできること

1
Posted at

はじめに

Pulumi は、AI で Pulumi を扱うための公式のツールを 2 つ提供しています。

  • Pulumi MCP Server:Pulumi Cloud や Registry を Claude から直接調べるための窓口
  • Pulumi プラグイン(Agent Skills):Pulumi の作業手順をまとめた手順書(Skill)のセット

この 2 つを Claude Code に入れて、それぞれで何ができるのかを実際に試してみました。

用語の整理

Pulumi を知らない人のために簡単に Pulumi のサービスの用語だけ簡単に整理しておきます。

サービス ひとことで たとえば
Pulumi Cloud スタックの状態や更新履歴を保存しておく Pulumi の Web サービス 「いつ誰が pulumi up して、何が失敗したか」が残る
Pulumi Registry AWS や Azure などのプロバイダーの仕様を集めたカタログ 「S3 バケットにはどんな引数がある?」を調べる
Pulumi Neo Pulumi Cloud 上で動く Pulumi の AI エージェント(使った分だけ課金) 「この変更を staging に適用して」とタスクを任せる

MCP とプラグインとについてざっくり説明

Claude Code に Pulumi のプラグインと MCP を入れたときの全体像

MCP は「調べる」担当、
Skill は「Pulumi の作法どおりに作業する」担当

です。

Pulumi MCP Server Pulumi プラグイン
中身 ツール 14 個 手順書(SKILL.md)15 個
ひとことで Pulumi のサービスに問い合わせる Pulumi 公式の手順で作業する
動く場所 Pulumi がホストするリモートサーバー 手元の Claude Code が読み込み、CLI を実行

導入方法

MCP Server

MCP Server は、URL を登録してから Claude Code の中で /mcp を開き、pulumi を選んでブラウザで認証します。認証画面では Pulumi のアクセストークンを貼り付け、使う組織を選びます。

claude mcp add --transport http pulumi https://mcp.ai.pulumi.com/mcp

プラグイン

プラグインは、マーケットプレイスを追加してからインストールします

claude plugin marketplace add pulumi/agent-skills
claude plugin install pulumi@pulumi-agent-skills

なお、マーケットプレイスには 4 つのプラグインがあります。
今回入れた pulumi は、下の表の上 3 つをまとめた全部入りです。

プラグイン 入っているスキル pulumi と一緒に入れる?
pulumi 書く・運用する・移行する・Neo に渡す(15 個) ー
pulumi-migration 移行するだけ(5 個) 不要(中身が重複する)
pulumi-delegation Neo に渡すだけ(1 個) 不要(中身が重複する)
pulumi-package-maintenance プロバイダーを開発する人向け(2 個) 必要なら追加

検証用のスタックを作る

ここからの検証では、東京リージョンに S3 バケットと SSM パラメータを作るスタックを使います。

前提として、Pulumi CLI と Node.js が入っていること、pulumi login で Pulumi Cloud にログインしていること、AWS CLI と同じ認証情報をセットアップ済みとします。

まず、作業用のフォルダーを作ります。

mkdir -p ~/pulumi-aws-demo/app
cd ~/pulumi-aws-demo/app

次に、プロジェクトのファイルを 4 つ作ります。

プロジェクトのファイルを作る(クリックで展開)
cat > Pulumi.yaml <<'EOF'
name: pulumi-aws-demo
runtime: nodejs
EOF

cat > package.json <<'EOF'
{
  "name": "pulumi-aws-demo",
  "main": "index.ts",
  "dependencies": { "@pulumi/pulumi": "^3", "@pulumi/aws": "^7" },
  "devDependencies": { "typescript": "^5", "@types/node": "^20" }
}
EOF

cat > tsconfig.json <<'EOF'
{
  "compilerOptions": { "strict": true, "target": "es2020", "module": "commonjs", "moduleResolution": "node", "outDir": "bin" },
  "files": ["index.ts"]
}
EOF

cat > index.ts <<'EOF'
import * as aws from "@pulumi/aws";

const bucket = new aws.s3.Bucket("data", { forceDestroy: true });
const appName = new aws.ssm.Parameter("appName", { type: "String", value: "pulumi-aws-demo" });

export const bucketName = bucket.bucket;
export const parameterName = appName.name;
EOF

最後に、スタック dev を作って反映します。

npm install
pulumi stack init dev
pulumi config set aws:region ap-northeast-1
pulumi up --yes

Resources: + 3 created と出れば準備完了です。

このフォルダーで claude を起動し、以降の質問を試していきます。

MCP Server でできること

ツールの種類

ツール 14 個は、問い合わせる先で 4 つに分かれます。ツールは随時変わる可能性もあるので詳細はドキュメントを参考にしましょう。

問い合わせる先 できること ツール数
Pulumi Cloud スタックやリソースの一覧・検索、メンバーやポリシー違反の確認 4
Pulumi Registry リソースの引数や型を調べる 5
Pulumi Neo Neo にタスクを頼む・状況を見る 4
コード生成 AWS にデプロイする Pulumi コードの書き方を返す 1

試してみた

検証用のスタックを作ったフォルダーで claude を起動し、日本語で聞いてみました。

聞いたこと 使われたツール 返ってきた内容
「組織にどんなスタックがある?」 get-stacks pulumi-aws-demo/dev などのスタックとリソース数
「resource-search で、組織全体から S3 バケットを探して」 resource-search スタックごとのバケット名、リージョン、作成日時
「メンバーとロール、ポリシー違反は?」 get-users / get-policy-violations 自分 1 人(Admin)、違反 0 件
「S3 バケットの主な入力プロパティは?」 get-resource aws.s3.Bucket の引数一覧と、versioning などが非推奨で別リソースに移ったこと

プラグイン(Skill)でできること

15 個のスキルは、用途で 4 つに分かれます。

用途 できること 主なスキル(数)
運用する 失敗の調査、秘密情報の管理、プロバイダーの更新 pulumi-debug-failed-operation ほか(4)
書く・直す Pulumi の作法どおりにコードを書く・レビューする pulumi-best-practices ほか(5)
移行する Terraform / CDK / CloudFormation / ARM から乗り換える pulumi-terraform-to-pulumi ほか(5)
Neo に渡す 作業の続きを Neo に引き継ぐ pulumi-neo-handoff(1)

ここからは、「運用する」「書く・直す」「移行する」から 1 つずつ試した結果を記載します。

pulumi-debug-failed-operation:失敗の原因を記録から調べる

S3 のバケット名は全 AWS アカウントで共有なので、サンプルによくある my-bucket のような名前は、すでに誰かに使われています。 これをわざと指定して pulumi up を失敗させます。

cd ~/pulumi-aws-demo/app

cat >> index.ts <<'EOF'
const logs = new aws.s3.Bucket("logs", { bucket: "my-bucket" });
export const logsBucket = logs.bucket;
EOF

pulumi up --yes

この状態で、ふつうに直してもらいます。今回はスキル名を指定しなくても、Claude がこのスキルを自分で読み込みました。

さっき dev スタックで pulumi up が失敗しました。原因を調べて直し、pulumi up --yes で反映まで確認して

ちなみに、スキルを使えない状態(--disallowedTools Skill)でも同じ依頼をしてスキルありなしを比べてみました。どちらも直りましたが、調べ方が違うようです。

スキルあり・なしでの調べ方の違い

スキルを使うと、失敗した更新のイベントを pulumi api で読みにいきます。 そのため、pulumi up を再実行しなくても AWS が返した実際のエラーが分かります。
スキルなしのときは、それらしい原因をコードから推測して当てていました。

pulumi-best-practices:Pulumi 特有の落とし穴を直す

Pulumi の典型的な間違いを 3 つ入れた index.ts に置き換えて、レビューしてもらいました。

間違いを入れた index.ts に置き換える(クリックで展開)
cd ~/pulumi-aws-demo/app

cat > index.ts <<'EOF'
import * as aws from "@pulumi/aws";

const bucket = new aws.s3.Bucket("data", { forceDestroy: true });
const appName = new aws.ssm.Parameter("appName", { type: "String", value: "pulumi-aws-demo" });
const logs = new aws.s3.Bucket("logs");

bucket.bucket.apply(name => {
    new aws.s3.BucketObject("readme-" + name, { bucket: name, content: "hello" });
});

const dbPassword = new aws.ssm.Parameter("dbPassword", { type: "String", value: "P@ssw0rd-demo" });

const role = new aws.iam.Role("reader", {
    assumeRolePolicy: JSON.stringify({
        Version: "2012-10-17",
        Statement: [{ Effect: "Allow", Principal: { Service: "lambda.amazonaws.com" }, Action: "sts:AssumeRole" }],
    }),
});

new aws.iam.RolePolicy("readerPolicy", {
    role: role.id,
    policy: JSON.stringify({
        Version: "2012-10-17",
        Statement: [{ Effect: "Allow", Action: "s3:GetObject", Resource: bucket.arn + "/*" }],
    }),
});

export const bucketName = bucket.bucket;
export const parameterName = appName.name;
export const logsBucket = logs.bucket;
EOF
/pulumi:pulumi-best-practices index.ts をレビューして、問題があれば直して。パスワードはデモ値のまま config に入れてよいので、直したら pulumi preview で確認して
問題 Before After
apply() の中でリソースを作る(preview に正しく出ない) bucket.bucket.apply(name => { new aws.s3.BucketObject(...) }) 外に出して bucket: bucket.bucket を直接渡す
Output(後から決まる値)を + で連結 IAM ポリシーの Resource: bucket.arn + "/*" bucket.arn.apply(arn => JSON.stringify({ ... Resource: `${arn}/*` }))
パスワードを直書き SSM パラメータに value: "P@ssw0rd-demo"(String 型) config.requireSecret("dbPassword") で読み、SecureString 型にする

なお、スキルを指定しない依頼でも同じ 3 点が直りました。こうした作法は、スキルがなくても Claude がある程度知っているようです。

pulumi-terraform-to-pulumi:Terraform を state ごと移行する

Terraform で作った S3 バケットと SSM パラメータを用意して、terraform apply しておきます。移行スキルは OpenTofu(Terraform 互換のオープンソース版)の tofu コマンドも使うので、あわせて入れておきます。

Terraform の構成を作って apply する(クリックで展開)
brew install opentofu

mkdir -p ~/pulumi-aws-demo/tf

cd ~/pulumi-aws-demo/tf

cat > main.tf <<'EOF'
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_s3_bucket" "assets" {
  bucket_prefix = "tf-assets-"
  force_destroy = true
}

resource "aws_s3_bucket_versioning" "assets" {
  bucket = aws_s3_bucket.assets.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_ssm_parameter" "app_env" {
  name  = "/pulumi-aws-demo/app-env"
  type  = "String"
  value = "dev"
}

output "bucket_name" {
  value = aws_s3_bucket.assets.bucket
}
EOF

terraform init
terraform apply -auto-approve

claude を起動し、次のように頼みました。

tf/ にある Terraform を Pulumi の TypeScript に移行して。移行先は migrated/ で、スタック名は dev。コードの変換だけでなく state も引き継いで、作り直しが起きないことを pulumi preview で確認して

スキル名を指定しなくても、Claude が自分でこのスキルを読み込みました。 スキルに書かれた手順は次のとおりです。

pulumi preview は「4 unchanged」(バケット、バージョニング、SSM パラメータ、スタック本体)で、既存のバケットを作り直さずにそのまま引き継げました。 生成されたコードは素直なものでした。

migrated/index.ts
import * as aws from "@pulumi/aws";

const assets = new aws.s3.Bucket("assets", {
    bucketPrefix: "tf-assets-",
    forceDestroy: true,
});

new aws.s3.BucketVersioning("assets", {
    bucket: assets.id,
    versioningConfiguration: {
        status: "Enabled",
    },
});

new aws.ssm.Parameter("app_env", {
    name: "/pulumi-aws-demo/app-env",
    type: "String",
    value: "dev",
});

export const bucketName = assets.bucket;

単純なコード変換(pulumi convert)を使わないよう、スキルに明記されているため、作り直しを起こさずに既存リソースを引き継げます。

後片付け

作ったスタック 2 つと、Terraform で作ったリソースを消し、作業用のフォルダーごと削除します。
移行したリソースは Pulumi 側で消してから、Terraform 側の state を片付けます。

cd ~/pulumi-aws-demo/app && pulumi destroy --yes && pulumi stack rm dev --yes
cd ~/pulumi-aws-demo/migrated && pulumi destroy --yes && pulumi stack rm dev --yes
cd ~/pulumi-aws-demo/tf && terraform destroy -auto-approve
cd ~ && rm -rf ~/pulumi-aws-demo /tmp/required-providers.json
find /tmp/ -maxdepth 1 -name 'pulumi-state*.json' -delete

まとめ

MCP で Pulumi Cloud と Registry の最新情報を調べ、Skill で Pulumi の作法どおりに作業する、ことが可能です。

参考リンク

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?