Skip to main content
Glama
localstack

LocalStack MCP Server

Official
by localstack

localstack-iam-policy-analyzer

Configure IAM enforcement modes and analyze logs to automatically generate missing IAM policies for LocalStack development environments.

Instructions

Configures LocalStack's IAM enforcement and analyzes logs to automatically generate missing IAM policies.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesThe action to perform: 'set-mode' to configure enforcement, 'analyze-policies' to generate a policy from logs, or 'get-status' to check the current mode.
modeNoThe enforcement mode to set. This is required only when the action is 'set-mode'.

Implementation Reference

  • Tool metadata that registers the tool with name 'localstack-iam-policy-analyzer', description, and annotations.
    export const metadata: ToolMetadata = {
      name: "localstack-iam-policy-analyzer",
      description:
        "Configures LocalStack's IAM enforcement and analyzes logs to automatically generate missing IAM policies.",
      annotations: {
        title: "LocalStack IAM Policy Analyzer",
        readOnlyHint: false,
        destructiveHint: false,
        idempotentHint: false,
      },
    };
  • Zod schema defining input parameters: action (enum) and optional mode (enum).
    export const schema = {
      action: z
        .enum(["set-mode", "analyze-policies", "get-status"])
        .describe(
          "The action to perform: 'set-mode' to configure enforcement, 'analyze-policies' to generate a policy from logs, or 'get-status' to check the current mode."
        ),
      mode: z
        .enum(["ENFORCED", "SOFT_MODE", "DISABLED"])
        .optional()
        .describe("The enforcement mode to set. This is required only when the action is 'set-mode'."),
    };
  • Primary handler function that performs preflights, then switches on 'action' to call get-status, set-mode, or analyze-policies sub-handlers.
    export default async function localstackIamPolicyAnalyzer({
      action,
      mode,
    }: InferSchema<typeof schema>) {
      const preflightError = await runPreflights([
        requireLocalStackCli(),
        requireProFeature(ProFeature.IAM_ENFORCEMENT),
      ]);
      if (preflightError) return preflightError;
    
      switch (action) {
        case "get-status":
          return await handleGetStatus();
        case "set-mode":
          if (!mode) {
            return ResponseBuilder.error(
              "Missing Required Parameter",
              `The 'mode' parameter is required when using 'set-mode' action.
    
    Valid modes:
    - **ENFORCED**: Strict IAM enforcement (blocks unauthorized actions)
    - **SOFT_MODE**: Log IAM violations without blocking
    - **DISABLED**: Turn off IAM enforcement completely`
            );
          }
          return await handleSetMode(mode);
        case "analyze-policies":
          return await handleAnalyzePolicies();
        default:
          return ResponseBuilder.error(
            "Unknown action",
            `Unknown action: ${action}. Supported actions: get-status, set-mode, analyze-policies`
          );
      }
    }
  • Helper function for 'analyze-policies' action: retrieves logs, filters IAM denials, enriches with resource data, deduplicates permissions, generates IAM policy, and formats the report.
    async function handleAnalyzePolicies() {
      try {
        const logRetriever = new LocalStackLogRetriever();
        const logResult = await logRetriever.retrieveLogs(5000);
    
        if (!logResult.success) {
          return ResponseBuilder.markdown(`❌ **Failed to Retrieve Logs**
    
    ${logResult.errorMessage}
    
    Please ensure LocalStack is running and generating logs.`);
        }
    
        const iamDenials = logResult.logs.filter((log) => log.isIamDenial === true);
    
        if (iamDenials.length === 0) {
          return ResponseBuilder.markdown(`✅ **Analysis Complete - No IAM Denials Found**
    
    No IAM permission errors were found in the recent logs.
    
    **This means either:**
    - Your application has all necessary permissions
    - IAM enforcement is not active (check with \`get-status\`)
    - No recent activity has triggered permission checks
    - IAM denials occurred outside the analyzed log window
    
    **Next steps:**
    - If you expected to see denials, ensure IAM enforcement is in \`ENFORCED\` or \`SOFT_MODE\`
    - Try running your application again to generate fresh logs
    - Increase the log analysis window if needed`);
        }
    
        const enrichedDenials = await enrichWithResourceData(iamDenials, logResult.logs);
        const uniquePermissions = deduplicatePermissions(enrichedDenials);
        const iamPolicy = generateIamPolicy(uniquePermissions);
    
        return formatPolicyReport(enrichedDenials, uniquePermissions, iamPolicy);
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        return ResponseBuilder.markdown(`❌ **Policy Analysis Failed**
    
    Error: ${errorMessage}
    
    Please ensure LocalStack is running and check the logs for more details.`);
      }
    }
  • Generates the IAM policy document (JSON) from a map of unique permissions, grouping actions by resource.
    export function generateIamPolicy(permissions: Map<string, UniquePermission>) {
      const resourcesToActionMap = new Map<string, Set<string>>();
    
      for (const permission of permissions.values()) {
        const resource = permission.resource || "*";
        if (!resourcesToActionMap.has(resource)) {
          resourcesToActionMap.set(resource, new Set());
        }
        resourcesToActionMap.get(resource)!.add(permission.action);
      }
    
      const statements = Array.from(resourcesToActionMap.entries()).map(([resource, actions], i) => ({
        Sid: `GeneratedStatement${i + 1}`,
        Effect: "Allow",
        Action: Array.from(actions).sort(),
        Resource: resource,
      }));
    
      return {
        Version: "2012-10-17",
        Statement: statements,
      };
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate this is not read-only, not idempotent, and not destructive, but the description adds context about what the tool does (configuring enforcement and analyzing logs). However, it doesn't disclose important behavioral traits like whether changes are persistent, what permissions are needed, or how the analysis works. With annotations covering basic safety, the description provides some value but lacks depth.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core functionality. Every word earns its place without redundancy or fluff, making it easy to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 2 parameters, 100% schema coverage, and no output schema, the description is minimally adequate. It covers the high-level purpose but lacks details on usage context, behavioral nuances, or output expectations. Given the annotations provide basic safety info, it's complete enough to understand what the tool does but not how to use it effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with clear enum descriptions for both parameters. The description mentions 'configures LocalStack's IAM enforcement' and 'analyzes logs', which loosely map to the 'set-mode' and 'analyze-policies' actions, but adds no additional semantic details beyond what the schema provides. Baseline 3 is appropriate given high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: configuring IAM enforcement and analyzing logs to generate missing policies. It uses specific verbs ('configures', 'analyzes', 'generates') and identifies the resource (IAM policies). However, it doesn't explicitly differentiate from sibling tools like 'localstack-logs-analysis' or 'localstack-management', which might have overlapping functionality.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites, appropriate contexts, or exclusions. Given the sibling tools include 'localstack-logs-analysis' and 'localstack-management', which might handle similar tasks, the lack of differentiation is a significant gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/localstack/localstack-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server