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
37 changes: 37 additions & 0 deletions .github/workflows/azure-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Azure smoke

# The Azure tool against the LocalStack Azure emulator, weekly and on demand.
on:
workflow_dispatch:
schedule:
- cron: "0 6 * * 1"

permissions:
contents: read

jobs:
azure-smoke:
runs-on: ubuntu-latest
timeout-minutes: 30
env:
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Use Node.js 22
uses: actions/setup-node@v4
with:
node-version: 22.x

- name: Install dependencies
run: yarn

- name: Install the latest Azure CLI
run: curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash && az version

- name: Pull the LocalStack Azure emulator image
run: docker pull localstack/localstack-azure:latest

- name: Run az commands through the Azure tool
run: yarn build && npx playwright test -c playwright.config.mjs tests/mcp/azure-smoke.spec.mjs
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,16 @@ Once the server is configured, talk to LocalStack through your agent in natural
- "My Lambda calls are failing. Read the LocalStack logs, find the permission errors, and generate an IAM policy that fixes them."
- "Inject 500ms of latency into DynamoDB and confirm my retry logic still works."
- "Search the LocalStack docs for how to enable S3 event notifications and summarize the steps."
- "Start the LocalStack Azure emulator, create a resource group and a storage account, and upload `./data/sample.csv` to a new blob container."

## How it works

The server connects MCP-compatible apps directly to your local LocalStack environment and its emulated AWS services, so your assistant can operate the stack securely without custom scripts or manual setup.

This server eliminates custom scripts and manual LocalStack management. Your agent can:

- Start, stop, restart, and monitor LocalStack for AWS container status with built-in auth.
- Start, stop, restart, and monitor the LocalStack for AWS, Snowflake and Azure emulators with built-in auth.
- Run Azure CLI (`az`) commands against the LocalStack for Azure emulator.
- Deploy CDK, Terraform, and SAM projects with automatic configuration detection.
- Search LocalStack documentation for guides, API references, and configuration details.
- Parse logs, catch errors, and auto-generate IAM policies from violations.
Expand All @@ -64,7 +66,7 @@ This server provides your AI with dedicated tools for managing your LocalStack e

| Tool Name | Description | Key Features |
| :-------------------------------------------------------------------------------- | :------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`localstack-management`](./src/tools/localstack-management.ts) | Manages LocalStack runtime operations for AWS and Snowflake stacks | - Execute start, stop, restart, and status checks<br/>- Integrate LocalStack authentication tokens<br/>- Inject custom environment variables<br/>- Verify real-time status and perform health monitoring |
| [`localstack-management`](./src/tools/localstack-management.ts) | Manages LocalStack runtime operations for AWS, Snowflake and Azure stacks | - Execute start, stop, restart, and status checks<br/>- Integrate LocalStack authentication tokens<br/>- Inject custom environment variables<br/>- Verify real-time status and perform health monitoring |
| [`localstack-deployer`](./src/tools/localstack-deployer.ts) | Handles infrastructure deployment to LocalStack for AWS environments | - Automatically run CDK, Terraform, and SAM tooling to deploy infrastructure locally<br/>- Enable parameterized deployments with variable support<br/>- Process and present deployment results<br/>- Requires you to have [`cdklocal`](https://github.com/localstack/aws-cdk-local), [`tflocal`](https://github.com/localstack/terraform-local), or [`samlocal`](https://github.com/localstack/aws-sam-cli-local) installed in your system path |
| [`localstack-logs-analysis`](./src/tools/localstack-logs-analysis.ts) | Analyzes LocalStack for AWS logs for troubleshooting and insights | - Offer multiple analysis options including summaries, errors, requests, and raw data<br/>- Filter by specific services and operations<br/>- Generate API call metrics and failure breakdowns<br/>- Group errors intelligently and identify patterns |
| [`localstack-iam-policy-analyzer`](./src/tools/localstack-iam-policy-analyzer.ts) | Handles IAM policy management and violation remediation | - Set IAM enforcement levels including `enforced`, `soft`, and `disabled` modes<br/>- Search logs for permission-related violations<br/>- Generate IAM policies automatically from detected access failures<br/>- Requires a valid LocalStack Auth Token |
Expand All @@ -74,6 +76,7 @@ This server provides your AI with dedicated tools for managing your LocalStack e
| [`localstack-extensions`](./src/tools/localstack-extensions.ts) | Installs, uninstalls, lists, and discovers LocalStack Extensions | - Manage installed extensions (`list`, `install`, `uninstall`) inside the running container<br/>- Browse the LocalStack Extensions marketplace (`available`)<br/>- Requires a valid LocalStack Auth Token |
| [`localstack-ephemeral-instances`](./src/tools/localstack-ephemeral-instances.ts) | Manages cloud-hosted LocalStack Ephemeral Instances | - Create temporary cloud-hosted LocalStack instances and get an endpoint URL<br/>- List available ephemeral instances, fetch logs, and delete instances<br/>- Supports lifetime, extension preload, Cloud Pod preload, and custom env vars on create<br/>- Requires a valid LocalStack Auth Token |
| [`localstack-aws-client`](./src/tools/localstack-aws-client.ts) | Runs AWS CLI commands inside the LocalStack for AWS container | - Executes commands via `awslocal` inside the running container<br/>- Sanitizes commands to block shell chaining<br/>- Auto-detects LocalStack coverage errors and links to docs |
| [`localstack-azure-client`](./src/tools/localstack-azure-client.ts) | Runs Azure CLI (`az`) commands against the LocalStack for Azure emulator | - Runs the Azure CLI installed on your machine with its own profile, never your Azure login<br/>- Blocks shell syntax and commands that would change the profile, install software or never end<br/>- Uses the extensions you installed with `az extension add`<br/>- Requires the Azure CLI (2.85 or newer) and a valid LocalStack Auth Token |
| [`localstack-aws-replicator`](./src/tools/localstack-aws-replicator.ts) | Replicates external AWS resources into a running LocalStack instance | - Start single-resource replication jobs with a resource type and identifier or ARN<br/>- Start batch replication jobs, such as SSM parameters under a path prefix<br/>- Poll job status by job ID and list existing jobs<br/>- List resource types supported by the running Replicator extension<br/>- Reads source AWS credentials from the MCP server environment and supports optional target account or region overrides |
| [`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 |
Expand Down Expand Up @@ -124,6 +127,7 @@ Run `npx -y @localstack/localstack-mcp-server init --help` for all options.
- Docker installed and running. The MCP server manages the LocalStack container directly through the Docker API.
- [`cdklocal`](https://github.com/localstack/aws-cdk-local), [`tflocal`](https://github.com/localstack/terraform-local), or [`samlocal`](https://github.com/localstack/aws-sam-cli-local) installed in your system path if you want to deploy CDK, Terraform, or SAM projects
- Snowflake CLI (`snow`) installed in your system path if you want to use the Snowflake tool
- Azure CLI (`az`) 2.85 or newer installed in your system path if you want to use the Azure tool (see [Azure tool](#azure-tool))
- A [valid LocalStack Auth Token](https://docs.localstack.cloud/aws/getting-started/auth-token/) configured as `LOCALSTACK_AUTH_TOKEN` (**required for all MCP tools**)
- [Node.js v20](https://nodejs.org/en/download/) or higher installed in your system path

Expand Down Expand Up @@ -221,6 +225,22 @@ See **[docs/DOCKER.md](./docs/DOCKER.md)** for the run command, MCP client confi
| `AWS_ACCESS_KEY_ID` (**required for AWS Replicator tool**) | Source AWS access key used by AWS Replicator to read external AWS resources | None |
| `AWS_SECRET_ACCESS_KEY` (**required for AWS Replicator tool**) | Source AWS secret access key used by AWS Replicator to read external AWS resources | None |
| `AWS_DEFAULT_REGION` (**required for AWS Replicator tool**) | Source AWS region used by AWS Replicator | None |
| `LOCALSTACK_AZURE_IMAGE_NAME` | Docker image the `start` action launches for the Azure stack (default `localstack/localstack-azure:latest`). | Latest Azure image |
| `LOCALSTACK_AZURE_ENDPOINT` | The ARM endpoint the Azure tool calls, a local `https` origin (default `https://azure.localhost.localstack.cloud:<LOCALSTACK_PORT>`). | Derived from `LOCALSTACK_PORT` |
| `LOCALSTACK_AZ_PATH` | The `az` launcher, or the Azure CLI's Python, for the Azure tool. | Found on `PATH` |
| `LOCALSTACK_AZ_CONFIG_DIR` | The Azure tool's own Azure CLI profile directory (default `~/.localstack/azure/mcp-config-<port>`); it must not overlap your `~/.azure`. | Under `~/.localstack/azure` |
| `LOCALSTACK_AZ_WORKDIR` | The directory the Azure tool runs `az` in; relative file paths resolve against it. | The server's working directory |
| `LOCALSTACK_AZ_TIMEOUT_SECONDS` | Time limit for one Azure CLI command (5–3600). | `300` |

### Azure tool

`localstack-azure-client` runs the Azure CLI (`az`, 2.85 or newer) installed on your machine against the LocalStack for Azure emulator; start the emulator with `localstack-management` (`service: azure`).

- The tool keeps its own Azure CLI profile (`LOCALSTACK_AZ_CONFIG_DIR`), logged in to the emulator with a dummy account, so your own Azure login is never used or changed.
- It uses your Azure CLI extensions: install one with `az extension add --name <extension>`.
- Bicep templates need the `bicep` binary on your `PATH` (for example `brew install bicep` or `winget install Microsoft.Bicep`).
- Relative file paths in commands resolve against `LOCALSTACK_AZ_WORKDIR`, by default the directory the MCP client starts the server in.
- The Docker image does not include the Azure CLI yet: run the server with npx or from source to use the Azure tool.

### Migration notes (CLI-free lifecycle)

Expand Down
1 change: 1 addition & 0 deletions data/sample-azure/hello.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello from the LocalStack MCP server Azure stage
10 changes: 10 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@
"name": "localstack-aws-client",
"description": "Runs AWS CLI commands inside the running LocalStack container"
},
{
"name": "localstack-azure-client",
"description": "Runs Azure CLI (az) commands against the LocalStack for Azure emulator"
},
{
"name": "localstack-aws-replicator",
"description": "Replicates external AWS resources into a running LocalStack instance using the AWS Replicator HTTP API"
Expand Down Expand Up @@ -156,6 +160,12 @@
"arguments": ["description"],
"text": "Please query the LocalStack container for ${arguments.description}."
},
{
"name": "localstack-azure-client",
"description": "Runs Azure CLI commands against the LocalStack Azure emulator",
"arguments": ["description"],
"text": "Please query the LocalStack Azure emulator for ${arguments.description}."
},
{
"name": "aws-replicator-start",
"description": "Start an AWS Replicator job",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"prepack": "yarn build",
"format": "prettier --write .",
"test": "jest",
"test:mcp:direct": "yarn build && playwright test -c playwright.config.mjs tests/mcp/direct.spec.mjs",
"test:mcp:direct": "yarn build && playwright test -c playwright.config.mjs tests/mcp/direct.spec.mjs tests/mcp/azure-offline.spec.mjs",
"test:mcp:evals": "yarn build && playwright test -c playwright.config.mjs tests/mcp/evals-gemini.spec.mjs",
"test:mcp": "yarn test:mcp:direct && yarn test:mcp:evals"
},
Expand Down
35 changes: 35 additions & 0 deletions playwright.config.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { defineConfig } from "@playwright/test";
import net from "node:net";
import { tmpdir } from "node:os";
import { join } from "node:path";

const mcpCommand = process.env.MCP_TEST_COMMAND || "node";
const mcpArgs = process.env.MCP_TEST_ARGS
? process.env.MCP_TEST_ARGS.split(" ").filter(Boolean)
: ["dist/cli.js"];

// A port where nothing listens, for the Azure tool's tests without an emulator.
const probe = net.createServer();
await new Promise((resolve) => probe.listen(0, "127.0.0.1", resolve));
const freePort = probe.address().port;
await new Promise((resolve) => probe.close(resolve));

export default defineConfig({
testDir: "./tests/mcp",
timeout: 120000,
Expand All @@ -23,6 +32,7 @@ export default defineConfig({
projects: [
{
name: "localstack-mcp-server",
testIgnore: /azure-offline\.spec\.mjs$/,
use: {
mcpConfig: {
transport: "stdio",
Expand All @@ -40,5 +50,30 @@ export default defineConfig({
},
},
},
{
// The Azure tool with no emulator: a dummy token, a port where nothing listens and a
// config dir of its own.
name: "azure-offline",
testMatch: /azure-offline\.spec\.mjs$/,
use: {
mcpConfig: {
transport: "stdio",
command: mcpCommand,
args: mcpArgs,
cwd: process.cwd(),
quiet: true,
connectTimeoutMs: 30000,
requestTimeoutMs: 300000,
callTimeoutMs: 300000,
env: {
...process.env,
LOCALSTACK_AUTH_TOKEN: "ls-dummy-token-for-offline-tests",
LOCALSTACK_PORT: String(freePort),
LOCALSTACK_AZ_CONFIG_DIR: join(tmpdir(), "lsmcp-azure-offline"),
MCP_ANALYTICS_DISABLED: "1",
},
},
},
},
],
});
Loading
Loading