vishnu.
AWSKiro CLIMCPCloudWatchCloudTrail

Kiro CLI + CloudWatch MCP: Investigating Alarms From a Terminal

I typed the wrong alarm name on purpose. It found the right one, ruled out DynamoDB, and located the fault in the service's own code. Four tool calls, under two minutes.

VR
Vishnu Rachapudi Cloud & AI Engineer · AWS Community Builder (Security)
September 2026 · 8 min read
In this post
  1. Why run this from a terminal
  2. Install on CloudShell
  3. Install on your own Linux or macOS machine
  4. Prerequisites for the MCP servers
  5. Configure the MCP servers
  6. Verify
  7. Investigating an alarm
  8. Prompts that actually work
  9. Permissions and what to watch
  10. CLI or console
Section 01

Why run this from a terminal

In my previous post I ran a CloudWatch investigation entirely from the console: click Investigate on a failing metric, accept a hypothesis, fill the facts, get an RCA. That flow is good, and it is the right one when you want a document at the end.

This is the other way in. Kiro CLI plus the AWS MCP servers, running in a terminal, talking to the same CloudWatch data. No console tabs, no report, just questions and answers.

What you get is different in a useful way. The console runs a structured investigation with a defined output. The CLI is conversational. You ask about an alarm, it pulls the alarm history, notices something adjacent, pulls that too, and tells you what it found. When you are triaging at 2 AM and do not yet know what you are looking for, that is the better shape.

Kiro CLI is the successor to Amazon Q Developer CLI. It reads the same .kiro/ configuration as Kiro IDE, so the MCP setup in this post works in both.

Section 02

Install on CloudShell

CloudShell is the fastest path because credentials are already there. No profile, no keys.

Open CloudShell from the console header, pick your region, and work in /tmp:

cd /tmp
curl --proto '=https' --tlsv1.2 -sSf \
  'https://desktop-release.q.us-east-1.amazonaws.com/latest/kirocli-x86_64-linux.zip' \
  -o 'kirocli.zip'
unzip kirocli.zip

Then put it on your PATH:

export PATH="$HOME/.local/bin:$PATH"
The gotcha that will bite you

That export does not persist. CloudShell sessions time out, and every new tab or reconnect starts without it. If kiro-cli suddenly says command not found, that is why. Add it to ~/.bashrc if you are going to be in there a while, since CloudShell keeps your home directory between sessions.

Log in with the device flow:

kiro-cli login --use-device-flow

Choose Use for Free with Builder ID. Copy the URL it prints into a browser, sign in with your AWS Builder ID, or create one, and come back. Then check it works:

kiro-cli

You should get the Kiro banner and a prompt. /quit to come back out.

Section 03

Install on your own Linux or macOS machine

For anything beyond a workshop, install it locally. One command on macOS and Linux:

curl -fsSL https://cli.kiro.dev/install | bash

The installer detects an existing Amazon Q CLI install and upgrades it in place. It offers to modify your shell config so PATH is set for you, which is worth saying yes to. On Debian and Ubuntu there is also a .deb, and a universal AppImage for other distributions, both on the Kiro downloads page. Windows 11 installs from PowerShell.

If anything looks wrong afterwards:

kiro-cli doctor

That catches most PATH and shell-integration problems on its own.

One difference from CloudShell: locally, the MCP servers use your AWS credentials, so you need a working profile. Set AWS_PROFILE in the MCP config, which I will come to next.

Section 04

Prerequisites for the MCP servers

The AWS MCP servers run through uvx, so install uv and a Python it can use:

curl -LsSf https://astral.sh/uv/install.sh | sh
uv self update
uv python install 3.10

You do not need sudo for any of this. It installs under your home directory, which matters for the next step.

Section 05

Configure the MCP servers

Kiro reads MCP configuration from two places:

For ops work you want user level. And this is shared configuration: if you use Kiro IDE, drop the same file at the same path and the IDE picks up the same servers.

mkdir -p ~/.kiro/settings
nano ~/.kiro/settings/mcp.json
Do not use sudo here

sudo nano ~/.kiro/settings/mcp.json writes a root-owned file into your home directory. Kiro CLI runs as you, and you then get permission errors that look like config problems. Edit it as your normal user.

Here is the config I would actually recommend for CloudWatch work. Two servers: CloudWatch for metrics, alarms and logs, and CloudTrail for the change events that explain most incidents.

{
  "mcpServers": {
    "awslabs.cloudwatch-mcp-server": {
      "autoApprove": [],
      "disabled": false,
      "command": "uvx",
      "args": ["awslabs.cloudwatch-mcp-server@latest"],
      "env": {
        "FASTMCP_LOG_LEVEL": "ERROR",
        "AWS_REGION": "us-west-2"
      },
      "transportType": "stdio"
    },
    "awslabs.cloudtrail-mcp-server": {
      "autoApprove": [],
      "disabled": false,
      "command": "uvx",
      "args": ["awslabs.cloudtrail-mcp-server@latest"],
      "env": {
        "FASTMCP_LOG_LEVEL": "ERROR",
        "AWS_REGION": "us-west-2"
      },
      "transportType": "stdio"
    }
  }
}

Field by field, because these trip people up:

FieldWhat it does
command / argsuvx fetches and runs the server package. The @latest suffix re-checks PyPI on every start, which costs a few seconds of load time. Drop it and manage the uv cache yourself if you want faster startup.
AWS_REGIONThe region the server queries. Set it to where your workload runs, not where you happen to be sitting.
AWS_PROFILENot shown above because CloudShell does not need it. On a local machine, add it and point it at your named profile.
FASTMCP_LOG_LEVELERROR keeps the server quiet. Set it to DEBUG when a server will not start.
disabledTurn a server off without deleting the block. Useful when you are narrowing down which server is misbehaving.
autoApproveTool names that run without asking you first. Leave it empty until you know exactly which tools you are happy to auto-run.

Adding Application Signals

The workshop I did also had the Application Signals server configured, and it is worth adding if you have Application Signals deployed with SLOs defined. If you do not, it adds 38 tools that will never have anything to say. Add it only when the telemetry exists:

"awslabs.cloudwatch-appsignals-mcp-server": {
  "autoApprove": [],
  "disabled": false,
  "command": "uvx",
  "args": ["awslabs.cloudwatch-applicationsignals-mcp-server@latest"],
  "env": {
    "FASTMCP_LOG_LEVEL": "ERROR",
    "AWS_REGION": "us-west-2"
  }
}

Note the mismatch, which catches everyone: the server key is usually written cloudwatch-appsignals-mcp-server, but the package is awslabs.cloudwatch-applicationsignals-mcp-server. Copy the package name exactly.

Section 06

Verify

Start the CLI. The first launch is slow because uvx is downloading packages.

kiro-cli
/mcp
kiro-cli / mcp
Both MCP servers running, with their tool counts. This is the check that everything wired up.
Both MCP servers running, with their tool counts. This is the check that everything wired up.

You want running against each server and a tool count. If a server is stuck or failed, set FASTMCP_LOG_LEVEL to DEBUG and start again. Usually it is a typo in the package name or a region the credentials cannot reach.

Section 07

Investigating an alarm

Now the part that matters. I asked it about an alarm, and I deliberately got the name wrong.

Investigate the alarm petfood-api-slo in us-west-2 region
kiro-cli / investigate alarm
Asking about an alarm by the wrong name. It calls get_alarm_history, then get_active_alarms.
Asking about an alarm by the wrong name. It calls get_alarm_history, then get_active_alarms.

There is no alarm called petfood-api-slo. It called get_alarm_history, found nothing useful, then called get_active_alarms and found what I actually meant:

alarm resolution
It reports the name mismatch, finds the real alarm, and keeps going.
It reports the name mismatch, finds the real alarm, and keeps going.

It reported the mismatch plainly, named the real alarm SLI-HealthAlarm-pet-api-rs-SLO, and kept going instead of stopping to ask me. It noticed the SLO had been created at 05:29 and gone into ALARM at 05:31, straight from INSUFFICIENT_DATA, then ran a root-cause audit.

The finding is where it earned its keep. A Rust service, petfood-api-rs, throwing server faults on POST /api, broken down by route:

root cause investigation
Server faults broken down by route. The cart items path dominates.
Server faults broken down by route. The cart items path dominates.

Then it ruled out the obvious suspect. The only downstream call was DynamoDB GetItem on ddbPetFoods, returning Status: OK at around 3ms every time. The fault was inside the service's own add_cart_item code path, not in DynamoDB.

slo root cause
DynamoDB ruled out, fault located in add_cart_item, with next steps offered.
DynamoDB ruled out, fault located in add_cart_item, with next steps offered.

It also caught the shape of the failure: 6 to 30 faults per minute over three hours, averaging about four. Intermittent but steady, not a spike. That changes the entire investigation, because you stop looking for a deployment or a traffic event and start looking for a conditional path in the code.

Total elapsed: under two minutes, across four tool calls. Doing that by hand means the alarms page, the SLO page, the trace map and Log Insights, in four tabs.

Section 08

Prompts that actually work

The CloudWatch MCP server gives the agent tools for alarms, metrics and log queries. What you get out depends heavily on how you ask. A few patterns that hold up:

With the CloudTrail server added, the follow-up that pays off most is "what changed in this account in the hour before the alarm fired". That is the question that solves the majority of real incidents, and it is tedious to answer by hand.

Section 09

Permissions and what to watch

In CloudShell the MCP servers inherit your console session's credentials. Whatever you can see, the agent can see. That is convenient in a workshop and worth thinking about in a customer account.

Locally, point AWS_PROFILE at a profile scoped to what the agent actually needs: CloudWatch read, Logs read, CloudTrail lookup. Read-only. There is no reason for an investigation profile to hold write permissions.

Two more things. Keep autoApprove empty until you have watched which tools get called and decided each one is safe to run unattended. And remember the output can contain account IDs, ARNs, table names and log content, so treat your terminal scrollback the same way you would treat a console screenshot before pasting it into a ticket or a Slack channel.

Section 10

CLI or console

Kiro CLI with MCPCloudWatch Investigations
ShapeConversational. You ask, it answers, you follow upStructured investigation with hypotheses to accept or rule out
OutputAnswers in your terminalAn incident report you complete with facts
SetupCLI, uv, an mcp.jsonAn investigation group with an IAM role, once per region
RetainedNothing beyond your scrollback7 to 90 days, shared with your team
Best forFast triage when you do not yet know the questionAnything that needs a document at the end

I use both, for different halves of the same incident. The CLI to work out what broke. The console to write down what happened. For the whole DevOps Agent comparison, I broke an EC2 instance to test that one back in March.

The setup is fifteen minutes and the same mcp.json works in Kiro IDE. If you already have a Builder ID, there is nothing stopping you doing this today.