Cloud Services·
advanced
·15 min read·Jul 9, 2026·Updated Oct 10, 2026
By Rad Tome·Lead AI Systems Architect·How we verify this

Cloud Infrastructure Auditor MCP Guide

Run automated cloud configuration security audits. Identify leaky S3 buckets, open security group ports, and loose IAM profiles directly from your IDE.

awsgcpiamsecuritycloud-servicesauditingcompliancemcp
Interactive Tool
1-Click Export

Generate & Validate Multi-Client MCP Config

One-click export with environment variables & path locators for Claude Desktop, Cursor, Windsurf, and OpenAI Codex CLI.

Open in Generator

Cloud Infrastructure Auditor MCP Guide

Maintaining cloud security posture across sprawling AWS and GCP environments requires continuous verification against industry baselines such as CIS Benchmarks, SOC 2, and HIPAA. DevSecOps engineers often spend excessive time manually navigating cloud web consoles, running cross-region CLI inspection commands, and cross-referencing security group rules against IP CIDR blocks to ensure sensitive databases are not publicly exposed.

By connecting cloud provider auditing SDKs directly to the Model Context Protocol (MCP), organizations can provide AI assistants in Claude Desktop, Cursor, or OpenAI Codex CLI with structured, read-only security inspection tools. Agents can proactively identify unencrypted storage buckets, detect open ingress ports (such as SSH 0.0.0.0/0), and flag stale IAM credentials.

However, granting cloud API access to generative language models introduces serious security risks if permissions are overly permissive. An agent must never possess write or mutation capabilities that could accidentally terminate instances or alter network access control lists.

This guide provides an end-to-end architectural manual, multi-client configurations, a production TypeScript MCP server using the AWS SDK v3, JSON-RPC wire frames, and compliance guardrails for cloud auditing.


1. System Architecture: Read-Only Cloud Security Gates

The Cloud Infrastructure Auditor MCP server operates as an unprivileged, read-only inspection gateway between the AI host application and cloud provider control planes.

diagram

IAM and Scope Enforcement

Mutation Detected

Read Only

AI Agent: tools/call audit_ec2_security_groups

Cloud Infrastructure Auditor MCP Server

IAM Policy: Read-Only / SecurityAudit?

-32004 Security Error: Write Prohibited

AWS SDK v3 Client Pool

AWS Control Plane: S3, EC2, IAM

Raw JSON Policy Results

Token-Efficient Compliance Filter

Essential Security Guardrails

  1. ▸Strict Managed Policy Scoping: The server credentials must be bound exclusively to the AWS-managed SecurityAudit policy or an equivalent GCP viewer role. Never supply AdministratorAccess or power-user credentials.
  2. ▸Ephemeral STS Sessions: Avoid provisioning permanent, long-lived access key pairs. Instead, use AWS Security Token Service (STS) or IAM Identity Center to generate temporary credentials that expire automatically after one hour.
  3. ▸Structured Finding Serialization: Raw AWS API responses contain deep metadata trees, pagination markers, and internal ARNs. The MCP server extracts only actionable vulnerability signals (e.g., bucket name, public access block status, open CIDR ranges) to protect the agent context window.

2. Environment Prerequisites and Software Matrix

Verify that your system satisfies the following runtime requirements:

ComponentMinimum VersionInstallation VerificationPurpose
Node.js>= 20.0.0node -vServer runtime environment
AWS CLI>= 2.15.0aws --versionAuthentication and credential verification
@aws-sdk/client-s3>= 3.650.0Package manifestAWS SDK v3 S3 client module
@aws-sdk/client-ec2>= 3.650.0Package manifestAWS SDK v3 EC2 client module
@modelcontextprotocol/sdk>= 1.2.0Package manifestCore Model Context Protocol framework

Verify your active AWS authentication identity:

bash
aws sts get-caller-identity

3. Creating a Hardened Read-Only IAM Auditor Role

Provision an unprivileged IAM user or role attached strictly to the AWS SecurityAudit managed policy:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSecurityAuditReadOnly",
      "Effect": "Allow",
      "Action": [
        "s3:GetBucketPublicAccessBlock",
        "s3:GetBucketPolicyStatus",
        "s3:ListAllMyBuckets",
        "ec2:DescribeSecurityGroups",
        "iam:ListUsers",
        "iam:ListAccessKeys"
      ],
      "Resource": "*"
    }
  ]
}

4. Multi-Host Configuration Snippets

Configure your MCP clients to launch the auditor server over standard input and output (stdio). Pass temporary credentials or profile names through environment variables.

Claude Desktop Configuration (claude_desktop_config.json)

json
{
  "mcpServers": {
    "cloud-auditor": {
      "command": "node",
      "args": ["/opt/mcp-servers/cloud-auditor/dist/index.js"],
      "env": {
        "AWS_REGION": "us-east-1",
        "AWS_PROFILE": "security-auditor-profile"
      }
    }
  }
}

Cursor IDE Configuration (.cursor/mcp.json)

json
{
  "mcpServers": {
    "cloud-auditor": {
      "command": "node",
      "args": ["./dist/index.js"],
      "env": {
        "AWS_REGION": "us-east-1"
      }
    }
  }
}

OpenAI Codex CLI Configuration (~/.codex/config.toml)

toml
[mcp_servers.cloud_auditor]
command = "node"
args = ["/opt/mcp-servers/cloud-auditor/dist/index.js"]

[mcp_servers.cloud_auditor.env]
AWS_REGION = "us-east-1"
AWS_PROFILE = "security-auditor-profile"

5. Production TypeScript Cloud Auditor MCP Server

The following server implementation exposes three core audit tools: audit_s3_public_access, audit_ec2_security_groups, and audit_iam_key_rotation. Save this as src/index.ts:

typescript
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { S3Client, ListBucketsCommand, GetPublicAccessBlockCommand } from '@aws-sdk/client-s3';
import { EC2Client, DescribeSecurityGroupsCommand } from '@aws-sdk/client-ec2';
import { IAMClient, ListUsersCommand, ListAccessKeysCommand } from '@aws-sdk/client-iam';

const region = process.env.AWS_REGION || 'us-east-1';
const s3 = new S3Client({ region });
const ec2 = new EC2Client({ region });
const iam = new IAMClient({ region });

const server = new Server(
  { name: 'cloud-infrastructure-auditor-mcp', version: '1.0.0' },
  { capabilities: { tools: {} } }
);

server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: 'audit_s3_public_access',
        description: 'Audit S3 buckets in account to identify missing Public Access Blocks or public exposure.',
        inputSchema: { type: 'object', properties: {} }
      },
      {
        name: 'audit_ec2_security_groups',
        description: 'Audit EC2 security groups for open ingress rules from 0.0.0.0/0 on sensitive ports (SSH 22, RDP 3389, DB 5432).',
        inputSchema: { type: 'object', properties: {} }
      },
      {
        name: 'audit_iam_key_rotation',
        description: 'Inspect active IAM user access keys to flag credentials older than 90 days.',
        inputSchema: { type: 'object', properties: {} }
      }
    ]
  };
});

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name } = request.params;

  try {
    if (name === 'audit_s3_public_access') {
      const { Buckets = [] } = await s3.send(new ListBucketsCommand({}));
      const findings = [];

      for (const bucket of Buckets.slice(0, 20)) {
        try {
          const block = await s3.send(new GetPublicAccessBlockCommand({ Bucket: bucket.Name }));
          const conf = block.PublicAccessBlockConfiguration;
          const isFullyProtected = conf?.BlockPublicAcls && conf?.BlockPublicPolicy && conf?.IgnorePublicAcls && conf?.RestrictPublicBuckets;

          if (!isFullyProtected) {
            findings.push({ bucket: bucket.Name, status: 'VULNERABLE: Public access block incomplete' });
          }
        } catch (err: any) {
          findings.push({ bucket: bucket.Name, status: 'WARNING: No public access block configured' });
        }
      }

      return {
        content: [{ type: 'text', text: JSON.stringify(findings, null, 2) }]
      };
    }

    if (name === 'audit_ec2_security_groups') {
      const { SecurityGroups = [] } = await ec2.send(new DescribeSecurityGroupsCommand({}));
      const openRules: any[] = [];

      for (const sg of SecurityGroups) {
        for (const rule of sg.IpPermissions || []) {
          const hasGlobalIngress = rule.IpRanges?.some(range => range.CidrIp === '0.0.0.0/0');
          if (hasGlobalIngress) {
            openRules.push({
              groupId: sg.GroupId,
              groupName: sg.GroupName,
              fromPort: rule.FromPort,
              toPort: rule.ToPort,
              protocol: rule.IpProtocol,
              risk: (rule.FromPort === 22 || rule.FromPort === 3389) ? 'CRITICAL: Open Management Port' : 'MEDIUM'
            });
          }
        }
      }

      return {
        content: [{ type: 'text', text: JSON.stringify(openRules, null, 2) }]
      };
    }

    if (name === 'audit_iam_key_rotation') {
      const { Users = [] } = await iam.send(new ListUsersCommand({ MaxItems: 25 }));
      const staleKeys = [];
      const now = Date.now();
      const ninetyDaysMs = 90 * 24 * 60 * 60 * 1000;

      for (const user of Users) {
        const { AccessKeyMetadata = [] } = await iam.send(new ListAccessKeysCommand({ UserName: user.UserName }));
        for (const key of AccessKeyMetadata) {
          if (key.Status === 'Active' && key.CreateDate) {
            const ageMs = now - new Date(key.CreateDate).getTime();
            if (ageMs > ninetyDaysMs) {
              staleKeys.push({
                user: user.UserName,
                keyId: key.AccessKeyId,
                ageDays: Math.floor(ageMs / (24 * 60 * 60 * 1000))
              });
            }
          }
        }
      }

      return {
        content: [{ type: 'text', text: JSON.stringify(staleKeys, null, 2) }]
      };
    }

    throw new Error(`Tool '${name}' is not recognized.`);
  } catch (err: any) {
    return {
      isError: true,
      content: [{ type: 'text', text: `AWS Audit Error: ${err.message}` }]
    };
  }
});

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
}

main().catch((err) => {
  process.stderr.write(`Fatal auditor error: ${err.message}\n`);
  process.exit(1);
});

6. JSON-RPC 2.0 Wire Payloads

Verifying JSON-RPC communication frames confirms proper parameter and response handling.

Tool Invocation Request (tools/call)

json
{
  "jsonrpc": "2.0",
  "id": "audit-sg-01",
  "method": "tools/call",
  "params": {
    "name": "audit_ec2_security_groups",
    "arguments": {}
  }
}

Result Payload

json
{
  "jsonrpc": "2.0",
  "id": "audit-sg-01",
  "result": {
    "content": [
      {
        "type": "text",
        "text": "[\n  {\n    \"groupId\": \"sg-04a18f29e19\",\n    \"groupName\": \"bastion-host-sg\",\n    \"fromPort\": 22,\n    \"toPort\": 22,\n    \"protocol\": \"tcp\",\n    \"risk\": \"CRITICAL: Open Management Port\"\n  }\n]"
      }
    ]
  }
}

7. Common Errors and Production Troubleshooting

When conducting cloud compliance scans through autonomous AI tools, prepare for the following operational challenges:

Error: AccessDenied: User is not authorized to perform: ...

  • ▸Root Cause: The unprivileged IAM user lacks specific read permissions for the requested service (e.g., s3:GetBucketPublicAccessBlock).
  • ▸Resolution: Attach the AWS-managed SecurityAudit policy to the IAM user or role rather than attempting to handcraft individual IAM statements.

Error: ExpiredToken: The security token included in the request is expired

  • ▸Root Cause: Temporary credentials obtained via AWS STS or AWS SSO have exceeded their 1-hour time-to-live.
  • ▸Resolution: Re-authenticate your terminal session using aws sso login or refresh your temporary session credentials.

API Rate Throttling (RequestLimitExceeded)

  • ▸Root Cause: An agent issued dozens of rapid queries across multiple AWS regions simultaneously.
  • ▸Resolution: Scope audit tools to explicit single regions (e.g. us-east-1) and incorporate exponential backoff in client handlers.

8. External Citations and Security Guardrails

Cloud infrastructure auditing must be conducted within rigorous compliance guardrails:

Technical Changelog

Weekly Protocol Diffs & Verified Drops

New server guides, benchmarks, and security audits. No spam. Unsubscribe anytime.

Zero marketing spam. 1-click unsubscribe anytime.

Ready to Deploy?

Build your full agent toolstack in the Visual Generator

Combine Cloud Infrastructure Auditor MCP Guide with databases, search APIs, and memory graphs in a single configuration file.

Customize in Generator
Developer Verification & Feedback
0 reports

Did this setup guide work with your AI host?

Help test this configuration across Claude, Cursor, and Codex CLI. Be the first to report:

Cloud Infrastructure Auditor MCP Guide FAQ

What is the Cloud Infrastructure Auditor MCP Guide?

Run automated cloud configuration security audits. Identify leaky S3 buckets, open security group ports, and loose IAM profiles directly from your IDE.

How do I configure Cloud Infrastructure Auditor MCP Guide in Claude Desktop or Cursor?

You can copy the configuration JSON from our guide or launch the interactive MCP Codex Config Generator at https://mcp-codex.com/generator to export valid configs in 1 click.

Can I use Cloud Infrastructure Auditor MCP Guide with the OpenAI Codex CLI?

Yes, OpenAI Codex CLI supports Model Context Protocol. You can add it directly to ~/.codex/config.toml or pass arguments to codex mcp add.

RT

Written by Rad Tome

Lead AI Systems Architect & Maintainer, MCP Codex

@RadTome

Specializing in Model Context Protocol (MCP) integrations, autonomous AI agent orchestration, and distributed developer toolchains. Researches and benchmarks production MCP client-server architectures across OpenAI Codex, Claude, and Cursor.

Editorial Integrity: Package names are checked against the npm registry and repositories against the GitHub API. Where a package could not be verified, the guide says so instead of giving you a command to run.

Related Guides