Skip to content

Connect Pulumi to Claude: Monitor Compliance and ESC Environments

Learn how to connect Pulumi to Claude using a managed MCP server to automate ESC environments, audit policy violations, and detect infrastructure drift.

Riya Sethi Riya Sethi · · 9 min read
Connect Pulumi to Claude: Monitor Compliance and ESC Environments

If your team needs to connect Pulumi to Claude to automate infrastructure provisioning, monitor continuous compliance, or manage ESC (Environments, Secrets, and Configuration), you need a Model Context Protocol (MCP) server. This server acts as the translation layer between Claude's tool calls and Pulumi's Cloud REST API. You can either build and maintain this infrastructure yourself, or use a managed integration platform like Truto to dynamically generate a secure, authenticated MCP server URL. If your team uses ChatGPT, check out our guide on connecting Pulumi to ChatGPT or explore our broader architectural overview on connecting Pulumi to AI Agents.

Giving a Large Language Model (LLM) read and write access to your Infrastructure as Code (IaC) state is a massive security and engineering challenge. You have to handle access tokens, map deep JSON schemas to MCP tool definitions, and deal with Pulumi's highly asynchronous deployment operations. Every time Pulumi updates an endpoint or deprecates an old REST resource, you have to update your server code, redeploy, and test the integration.

This guide breaks down exactly how to use Truto to generate a secure, managed MCP server for Pulumi, connect it natively to Claude Desktop, and execute complex infrastructure workflows using natural language.

The Engineering Reality of the Pulumi API

A custom MCP server is a self-hosted integration layer. While the open MCP standard provides a predictable way for models to discover tools, the reality of implementing it against a stateful cloud API is painful. Pulumi is not a simple CRUD application. It manages live cloud infrastructure, complex policy engines, and encrypted secrets.

If you decide to build a custom MCP server for Pulumi, here are the specific integration challenges you will face:

Asynchronous Stack Operations and Engine Events Unlike a typical REST API where a POST creates a resource instantly, infrastructure changes in Pulumi (like running pulumi up or pulumi preview) are highly asynchronous. The API requires you to create an update record, start the update, and then stream or poll engine events until completion. If you expose this directly to an LLM, the model will timeout waiting for a 20-minute Terraform/Pulumi deployment to finish. Your MCP server must provide polling mechanisms or webhook listeners that the LLM can query to check the status of a deployment, meaning you must maintain intermediate state.

Environment, Secrets, and Configuration (ESC) Complexity Pulumi ESC manages dynamic secrets and configuration across environments. The API does not just return flat key-value pairs. It returns references to external systems (AWS KMS, HashiCorp Vault, 1Password), encrypted ciphertexts, and function evaluations (like fn::open or fn::secret). Building an MCP tool to simply "read a secret" requires teaching the LLM how to parse these proprietary references or building an abstraction layer that handles the decryption payloads on behalf of the agent.

Policy Packs and Continuous Compliance Pulumi CrossGuard enforces policy as code. The API data model for policy results is deeply nested: organizations have policy groups, which have applied policy packs, which evaluate against specific environments, resulting in policy issues with varying enforcement levels (advisory, mandatory). Mapping this multi-level hierarchy into a flat, predictable JSON Schema for Claude's tool definitions requires extensive manual curation. If you pass the raw schema, Claude will struggle to formulate the correct query filters.

How Truto Solves the MCP Translation Layer

Truto eliminates the need to hand-code MCP servers by dynamically generating tools directly from Pulumi's API documentation. When you connect a Pulumi account, Truto's integration layer parses the resources, methods, and JSON schemas, instantly exposing them as an MCP-compliant JSON-RPC 2.0 endpoint.

There are three critical architectural decisions that make this safe and reliable for AI workloads:

  1. Documentation-Driven Tool Generation: Tools are not manually maintained. Truto derives them from Pulumi's resource definitions. If a Pulumi endpoint is documented, it becomes a tool. The tool name is generated as a descriptive snake_case string (e.g., list_all_pulumi_policyresults_issues), and the LLM receives the exact JSON Schema for both query and body parameters.
  2. No Data Caching: Truto acts as a pure proxy. When Claude calls a Pulumi tool, Truto validates the MCP token, injects the correct Pulumi credentials, and executes the request against Pulumi's servers in real-time. Truto does not cache your infrastructure state, stack outputs, or ESC secrets. This zero-data-retention approach is critical when dealing with IaC data.
  3. Strict Rate Limit Pass-Through: Truto does not retry, throttle, or apply backoff on rate limit errors. When the Pulumi API returns an HTTP 429, Truto passes that error directly to the caller. Truto normalizes the upstream rate limit info into standardized headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) per the IETF spec. The caller (Claude or your agent framework) is responsible for reading these headers and executing its own backoff logic.

Creating the Pulumi MCP Server

To give Claude access to your Pulumi environment, you first need to generate a secure MCP URL. Truto scopes every MCP server to a single integrated account, ensuring tenant isolation. You can generate this URL using the Truto UI or programmatically via the API.

Method 1: Via the Truto UI

  1. Navigate to the Integrated Accounts page in your Truto dashboard and select your active Pulumi connection.
  2. Click the MCP Servers tab.
  3. Click Create MCP Server.
  4. Configure your server. You can select specific tags (e.g., compliance, stacks) or restrict methods to read-only access.
  5. Copy the generated MCP server URL (e.g., https://api.truto.one/mcp/a1b2c3d4...).

Method 2: Via the Truto API

For teams managing AI infrastructure programmatically, you can generate MCP servers via a simple API call. The payload allows you to restrict the agent's capabilities - for example, ensuring the LLM can only read data and cannot accidentally delete a stack.

Request:

curl -X POST https://api.truto.one/integrated-account/{account_id}/mcp \
  -H "Authorization: Bearer YOUR_TRUTO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Pulumi Compliance Auditor AI",
    "config": {
      "methods": ["read"]
    },
    "expires_at": "2026-12-31T23:59:59Z"
  }'

Response:

{
  "id": "mcp_8f7e6d5c",
  "name": "Pulumi Compliance Auditor AI",
  "config": { "methods": ["read"] },
  "expires_at": "2026-12-31T23:59:59Z",
  "url": "https://api.truto.one/mcp/a1b2c3d4e5f67890"
}

Connecting the MCP Server to Claude

Once you have the Truto MCP URL, connecting it to Claude is a zero-code process. The URL itself acts as the secure endpoint and authentication token.

Method 1: Via the Claude UI

If you are using Claude Desktop or an enterprise workspace with custom connectors enabled:

  1. Open Settings and navigate to Integrations or Connectors.
  2. Select Add MCP Server.
  3. Paste the Truto MCP URL you generated in the previous step.
  4. Click Add. Claude will instantly handshake with the server, retrieve the Pulumi capabilities, and populate the tool definitions.

Method 2: Via Manual Configuration (claude_desktop_config.json)

For advanced users running Claude Desktop locally, you can modify the configuration file to use the Server-Sent Events (SSE) transport natively supported by Truto.

Open your claude_desktop_config.json file (typically found in ~/Library/Application Support/Claude/ on macOS or %APPDATA%\Claude\ on Windows) and add the Pulumi MCP server:

{
  "mcpServers": {
    "pulumi_cloud": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-sse",
        "https://api.truto.one/mcp/a1b2c3d4e5f67890"
      ]
    }
  }
}

Restart Claude Desktop. The agent will discover the Pulumi tools and make them available for your natural language prompts.

Hero Tools for Pulumi

When connected, Truto exposes the entire Pulumi API to Claude. However, for AI-driven infrastructure management, certain endpoints provide massive leverage. Here are six hero tools that enable advanced agentic workflows.

get_single_pulumi_env_by_id

Retrieves the YAML definition of a Pulumi ESC environment, including its imports, values, provider configurations, and function invocations. This is critical for auditing secrets management.

"Claude, get the ESC environment definition for the production environment in the 'core-infra' project. Are there any plaintext secrets that haven't been wrapped in fn::secret?"

list_all_pulumi_policyresults_issues

Lists Pulumi Cloud policy issues across an organization. This tool detects violations triggered by Policy Packs during stack updates or continuous compliance scans, returning the violating resource, enforcement level, and triage status.

"Pull all mandatory policy violations across the organization from the last 24 hours. Group them by stack name and summarize the failing rules."

list_all_pulumi_drift_status

Checks the current drift detection status for a Pulumi stack, revealing whether manual, unmanaged changes have been made directly in the cloud console since the last deployment.

"Check the drift status for the 'data-warehouse-prod' stack. If drift is detected, list the specific AWS resources that differ from the state file."

create_a_pulumi_preview

Initiates a dry-run update for a Pulumi stack. This tool creates the preview operation, allowing the LLM to inspect proposed infrastructure changes before they are actually applied to production.

"Create a preview for the 'network-core' stack using the latest configuration. Tell me how many resources will be created, updated, and deleted."

list_all_pulumi_member_stacks

Audits a user's effective permissions on a specific stack, covering access inherited from default roles, team memberships, and explicitly assigned grants. Ideal for security reviews.

"Check the effective permissions for user 'jdoe' on the 'payment-gateway-prod' stack. Does this user have admin rights, and if so, is it inherited from a team?"

list_all_pulumi_outputs

Extracts the runtime state and outputs of a Pulumi stack, as recorded by the most recent completed update. This is heavily used by agents to pass IDs and connection strings between disparate systems.

"Get the outputs for the 'shared-database' stack. I need the database connection endpoint and the generated read-only username to pass to the application deployment."

To see the full list of available tools, including payload structures and schema details, visit the Pulumi integration page.

Workflows in Action

Once Claude is connected to your Pulumi MCP server, it can orchestrate multi-step infrastructure tasks that previously required clicking through the Pulumi Cloud UI or writing custom Python scripts. Here are two real-world examples.

Scenario 1: Infrastructure Drift Triage

When a critical stack drifts from its IaC definition, security teams need to know what changed, what the current outputs are, and who has the access to make those changes.

"Check if the 'eks-cluster-prod' stack has drifted. If it has, pull the stack outputs so I have the cluster endpoints, and then list who has admin access to this stack so I can notify them."

How the agent executes this:

  1. list_all_pulumi_drift_status: Claude queries the drift status. The API confirms the stack has drifted and identifies the specific AWS Security Group that was modified manually.
  2. list_all_pulumi_outputs: Claude pulls the stack outputs to secure the current active endpoints and resource IDs for the incident report.
  3. list_all_pulumi_member_stacks: Claude queries the permissions on the stack, returning the list of engineers and teams with admin or edit access.
  4. Result: Claude synthesizes a complete incident brief, highlighting the exact manual change, the impacted endpoints, and a list of authorized users to contact for remediation.
sequenceDiagram
    participant User as User
    participant Claude as Claude Desktop
    participant MCP as Truto MCP Server
    participant Pulumi as "Pulumi Cloud API"

    User->>Claude: "Check drift on eks-cluster-prod and audit access..."
    Claude->>MCP: Call list_all_pulumi_drift_status
    MCP->>Pulumi: GET /api/stacks/{org}/{project}/{stack}/drift
    Pulumi-->>MCP: Drift detected on AWS SG
    MCP-->>Claude: JSON response
    Claude->>MCP: Call list_all_pulumi_outputs
    MCP->>Pulumi: GET /api/stacks/{org}/{project}/{stack}/outputs
    Pulumi-->>MCP: Cluster endpoints returned
    MCP-->>Claude: JSON response
    Claude->>MCP: Call list_all_pulumi_member_stacks
    MCP->>Pulumi: GET /api/stacks/{org}/{project}/{stack}/members
    Pulumi-->>MCP: List of admins returned
    MCP-->>Claude: JSON response
    Claude->>User: Deliver incident summary and contact list

Scenario 2: Continuous Compliance Audit

Platform teams often need to audit compliance across hundreds of stacks and verify that environments are using the correct managed secrets.

"Find all mandatory policy violations across the organization. For any stack failing a compliance check, pull its ESC environment definition to ensure it is using the required AWS KMS provider."

How the agent executes this:

  1. list_all_pulumi_policyresults_issues: Claude requests all active policy issues for the organization, filtering the JSON response for enforcementLevel: mandatory.
  2. get_single_pulumi_env_by_id: For each failing stack, Claude extracts the environment reference and fetches the raw YAML environment definition.
  3. Analysis: Claude parses the YAML to check if the secretsProvider block is correctly pointing to the approved AWS KMS key.
  4. Result: Claude provides a markdown report listing the non-compliant stacks, the specific rules they violated, and whether their ESC environment configurations are lacking the required KMS setup.

Security and Access Control

Giving an LLM access to Pulumi requires strict security guardrails. Truto's MCP architecture enforces security at the infrastructure layer, ensuring you never hand over unrestricted credentials to an AI model.

  • Method Filtering: You can configure the MCP token with config.methods: ["read"]. Truto enforces this at the routing layer, guaranteeing the LLM can only query data (like outputs and drift) and physically cannot execute create, update, or delete tools.
  • Tag Filtering: Limit the server to specific domains. If Pulumi resources are tagged, you can restrict the MCP server to only expose tools relevant to compliance or esc.
  • Time-to-Live (TTL): By setting an expires_at timestamp during server creation, Truto will automatically destroy the MCP server and revoke access using scheduled distributed alarms. Perfect for temporary audit sessions.
  • Layered Authentication: By enabling require_api_token_auth, possessing the MCP URL is no longer sufficient. The Claude client (or your custom agent framework) must also pass a valid Truto API token in the headers, adding a crucial second layer of identity verification.

By leveraging managed MCP servers, your engineering team can connect Claude to Pulumi in minutes without writing custom translation logic, handling pagination, or managing API lifecycles. The LLM gets predictable, schema-validated tools, and your infrastructure remains secure.

FAQ

How does Truto handle Pulumi API rate limits?
Truto does not retry, throttle, or apply backoff on rate limit errors. When Pulumi returns an HTTP 429, Truto passes that error directly to the caller, normalizing the rate limit info into standardized headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset). The caller is responsible for implementing retry logic.
Can I restrict Claude to read-only operations in Pulumi?
Yes. When generating the MCP server URL, you can configure method filtering to expose only 'read' operations (like get and list). This ensures the LLM cannot mutate infrastructure state or trigger deployments.
How are Pulumi tools exposed to Claude?
Truto dynamically generates MCP tools from Pulumi's API documentation and OpenAPI schemas. Claude receives these as a flat JSON-RPC array of tools, complete with JSON schemas mapping exactly to Pulumi's required parameters.

More from our Blog