Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Dependencies
node_modules/
.yarn/cache/
.yarn/unplugged/
.yarn/build-state.yml
.yarn/install-state.gz
.vercel
dist
.xmcp
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ This server provides your AI with dedicated tools for managing your LocalStack e
| [`localstack-app-inspector`](./src/tools/localstack-app-inspector.ts) | Inspects LocalStack application traces, spans, events, and IAM evaluations | - Enable or disable App Inspector for the running LocalStack instance<br/>- List and inspect traces to understand AWS service-to-service flows<br/>- Drill into spans, events, payload metadata, and IAM policy evaluation events<br/>- Filter by service, region, operation, resource, ARN, status, and time range<br/>- Requires a valid LocalStack Auth Token and the App Inspector feature in the connected LocalStack license |
| [`localstack-docs`](./src/tools/localstack-docs.ts) | Searches LocalStack documentation through CrawlChat | - Queries LocalStack docs through a public CrawlChat collection<br/>- Returns focused snippets with source links only<br/>- Helps answer coverage, configuration, and setup questions without requiring LocalStack runtime |
| [`localstack-snowflake-client`](./src/tools/localstack-snowflake-client.ts) | Runs SQL against the LocalStack Snowflake emulator through the `snow` CLI | - Execute SELECT, DDL (CREATE/DROP), DML (INSERT/UPDATE/DELETE), and SHOW/DESCRIBE statements from a query string or a `.sql` file<br/>- Check the Snowflake connection before running queries<br/>- Set optional database, schema, warehouse, and role context per query<br/>- Requires the Snowflake CLI (`snow`) and a valid LocalStack Auth Token |
| [`localstack-preflight`](./src/tools/localstack-coverage.ts) | Checks LocalStack API coverage and deploy-readiness for IaC templates | - Scan Terraform, CloudFormation, CDK, or Pulumi projects and get a per-resource verdict<br/>- Look up which AWS service operations are implemented vs missing<br/>- Check individual `service:Operation` pairs against the coverage database<br/>- Requires LocalStack running with the `localstack-extension-coverage` extension installed |

## Prompts

Expand Down
20 changes: 20 additions & 0 deletions data/evals/gemini-comprehensive.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,26 @@
"expect": {
"toolsTriggered": { "calls": [{ "name": "localstack-iam-policy-analyzer", "required": true }], "order": "any" }
}
},
{
"id": "discover-preflight-tool-services",
"mode": "mcp_host",
"scenario": "Show me an overview of all AWS services supported by LocalStack and their coverage percentages.",
"mcpHostConfig": { "provider": "google", "model": "gemini-2.0-flash", "temperature": 0 },
"iterations": 5,
"expect": {
"toolsTriggered": { "calls": [{ "name": "localstack-preflight", "required": true }], "order": "any" }
}
},
{
"id": "discover-preflight-tool-resources",
"mode": "mcp_host",
"scenario": "Will my Terraform resources aws_s3_bucket and aws_lambda_function work on LocalStack? Check if they are fully supported.",
"mcpHostConfig": { "provider": "google", "model": "gemini-2.0-flash", "temperature": 0 },
"iterations": 5,
"expect": {
"toolsTriggered": { "calls": [{ "name": "localstack-preflight", "required": true }], "order": "any" }
}
}
]
}
4 changes: 4 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@
{
"name": "localstack-app-inspector",
"description": "Inspect LocalStack application traces, spans, events, payload metadata, and IAM policy evaluations"
},
{
"name": "localstack-preflight",
"description": "Query the LocalStack coverage extension to find out which AWS service operations are implemented and get a deploy-readiness verdict for IaC templates"
}
],
"prompts": [
Expand Down
1 change: 1 addition & 0 deletions src/core/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export const TOOL_ARG_ALLOWLIST: Record<string, string[]> = {
"localstack-logs-analysis": ["analysisType", "lines", "service", "operation", "filter"],
"localstack-management": ["action", "service", "envVars"],
"localstack-snowflake-client": ["action"],
"localstack-preflight": ["action", "service"],
};

let posthogClient: PostHog | null = null;
Expand Down
6 changes: 6 additions & 0 deletions src/core/response-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,10 @@ export class ResponseBuilder {
content: [{ type: "text", text: content }],
};
}

public static blocks(...parts: string[]): ToolResponse {
return {
content: parts.map((text) => ({ type: "text" as const, text })),
};
}
}
105 changes: 105 additions & 0 deletions src/prompts/coverage-advisor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { z } from "zod";
import { type InferSchema, type PromptMetadata } from "xmcp";
import { withPromptAnalytics } from "../core/analytics";

export const schema = {
iac_path: z
.string()
.optional()
.describe(
"(Optional) Path to a CloudFormation, Terraform, CDK, or SAM project. When provided, the advisor parses the template and checks every required operation automatically."
),
services: z
.string()
.optional()
.describe(
"(Optional) Comma-separated AWS service names to check in full (e.g. 's3,lambda,dynamodb'). Use when you want per-service detail without a template."
),
operations: z
.string()
.optional()
.describe(
"(Optional) Comma-separated 'service:Operation' pairs to check directly (e.g. 's3:CreateBucket,iam:CreateRole'). Overrides auto-extraction when provided."
),
mode: z
.string()
.optional()
.describe(
"(Optional) 'summary' (default) shows only gaps and a deploy verdict; 'full' lists every implemented and missing operation."
),
};

export const metadata: PromptMetadata = {
name: "localstack-preflight",
title: "Coverage Advisor",
description:
"Check LocalStack API coverage for an IaC template, a list of services, or specific operations — and get a clear deploy-readiness verdict.",
role: "user",
};

type PromptArgs = InferSchema<typeof schema>;

export default async function coverageAdvisor(args: PromptArgs): Promise<string> {
return withPromptAnalytics(metadata.name, args, async () => {
const values = {
iac_path: args.iac_path?.trim() ?? "",
services: args.services?.trim() ?? "",
operations: args.operations?.trim() ?? "",
mode: normalize(args.mode, "summary"),
};
return renderCoverageAdvisorPrompt(values);
});
}

function normalize(value: string | undefined, fallback: string): string {
const v = value?.trim();
return v && v.length > 0 ? v : fallback;
}

function renderCoverageAdvisorPrompt(values: {
iac_path: string;
services: string;
operations: string;
mode: string;
}): string {
const hasIac = values.iac_path.length > 0;
const hasServices = values.services.length > 0;
const hasOperations = values.operations.length > 0;

return `# LocalStack Coverage Check

## OUTPUT RULE — follow exactly

Call the tool, then render the results as a **markdown table** in your response with columns Resource and Status (✅ / ❌). Group by stack or framework if there are multiple. End with a single bold verdict line. No preamble, no extra analysis beyond the verdict.

## What to call

Use only the \`mcp__localstack__localstack-preflight\` tool.

${hasOperations
? `Split \`${values.operations}\` on commas and call \`check_operations\` with the resulting array.`
: hasIac
? `Call \`scan_iac\` with \`iac_path: "${values.iac_path}"\`. Do not read the files yourself.`
: hasServices
? `Call \`get_service_coverage\` once for each service in \`${values.services}\` (split on commas).`
: `Call \`scan_iac\` with the workspace root as \`iac_path\`. If the tool returns "No resource types found", ask the user: "I didn't find any IaC files in <path> — where is your Terraform project?"`}

${hasIac && !hasOperations ? `If the template has more than 50 resource types, chunk \`check_resources\` into batches of 50 and concatenate the outputs.` : ""}

## After showing the verdict

If the scan found **any blockers** and the project is Terraform, append exactly this line after the tool output:

> Want me to patch this so it deploys on LocalStack? I'll gate the unsupported resources with \`count = 0\` and add the LocalStack provider config — shown as a diff before anything is changed.

If the user says yes, call \`patch_iac\` with the same \`iac_path\`.

## Absolute prohibitions

- Do NOT read IaC files yourself. The tool does this — call the tool.
- Do NOT add a "LocalStack Tier" column or any tier/edition labels (Community, Pro, etc.).
- Do NOT add file paths or line numbers.
- Do NOT add risk labels, impact descriptions, or percentages.
- Do NOT reorder, rename, or add rows beyond what the tool returned.
- Do NOT add any text before the tool output other than the patch offer line above.`;
}
Loading
Loading