How to add product analytics to your app with Kiro

Connect Kiro to Amplitude's MCP servers, put your API key in an env file, and hand Kiro one prompt that installs the SDK the docs recommend for your stack. Then review the diff for the mistakes agents make, add one event that matches your taxonomy, and save the rules in a steering file. About 15 minutes, all copy-paste.

  • Kiro
  • Amplitude MCP
  • Docs MCP
  • Steering
  • 15 min

Chris Tam · Last updated 6 October 2026

Kiro is an agentic IDE that plans and writes code from your prompts. It can add product analytics to any web or Node.js app, as long as it reads current Amplitude docs and your real event names instead of guessing.

In this tutorial, you'll connect Kiro to Amplitude, have Kiro install the SDK, review its diff, and save the rules as a steering file.

What you'll build

A Kiro workspace connected to the Amplitude MCP server and the Docs MCP server, an app instrumented with the SDK the Quickstart recommends for its stack, one Report Exported event named to match your existing taxonomy, and a steering file in .kiro/steering/ that keeps Kiro on those conventions in every later session. By the end you'll see live events in your Amplitude project.

Prerequisites

  • The Kiro IDE installed and signed in.
  • A web or Node.js project in a Git repository, opened as a Kiro workspace, so you can review and undo Kiro's changes with git diff.
  • An Amplitude account with access to a project, and that project's API key. In Amplitude, go to Settings > Projects > your project > General.

No Amplitude account yet? A free account is enough for this tutorial; nothing here needs a paid Amplitude plan. Sign up for free to get your project API key.

1. Connect Kiro to Amplitude

Kiro reads MCP servers from an mcp.json file at one of two scopes:

  • User scope, ~/.kiro/settings/mcp.json, applies to every workspace you open.
  • Workspace scope, .kiro/settings/mcp.json, applies only to this project. Commit it, and everyone who opens the repository in Kiro gets the same servers.

If both files exist, Kiro merges them and the workspace file wins on any server defined in both. Pick one: open the Command Palette (Cmd+Shift+P on Mac, Ctrl+Shift+P on Windows and Linux) and run Kiro: Open user MCP config (JSON) or Kiro: Open workspace MCP config (JSON).

Add two servers. The first is the authenticated Amplitude MCP server, which reads your projects and tracking plan with your own Amplitude permissions. The second is the public Docs MCP server, which serves current Amplitude documentation and needs no sign-in. The Kiro setup guide and the Docs MCP server page are the sources for both entries.

Paste this into .kiro/settings/mcp.json (or ~/.kiro/settings/mcp.json for user scope). JSON doesn't allow comments, so keep the file exactly in this shape:

.kiro/settings/mcp.json
{
  "mcpServers": {
    "amplitude-mcp": {
      "type": "http",
      "url": "https://mcp.amplitude.com/mcp"
    },
    "amplitude-docs": {
      "url": "https://amplitude.com/docs/api/mcp"
    }
  }
}

If your Amplitude data lives in the EU region, use https://mcp.eu.amplitude.com/mcp for amplitude-mcp.

Save the file. Kiro reconnects servers on save, with no restart. Open the Kiro panel, go to the MCP servers tab, and check that both servers show as connected. When Kiro opens the Amplitude sign-in page in your browser, approve access.

Then check the connection in a new chat:

Prompt for Kiro
What Amplitude projects can I access?

A list of your projects means the Amplitude MCP server is connected and authenticated. Kiro asks you to approve MCP tool calls before they run, unless you've listed them in the server's autoApprove array, so expect approval prompts here and in the steps below.

Why. Neither server entry holds a credential. The Amplitude server authenticates through OAuth and the Docs server is public, so the workspace file is safe to commit. The Amplitude MCP server isn't an ingestion endpoint and never sends your app's events; it's how Kiro reads your taxonomy and checks results. The Docs server is what stops Kiro from writing a package name from training data.

2. Add your API key to the env file

Put the key in your env file yourself, before you prompt Kiro. If you paste the key into the chat, the agent tends to paste it straight into source.

For a Vite app, add this line to .env.local at the project root:

.env.local
VITE_AMPLITUDE_API_KEY=your-project-api-key

Browser code can only read variables with the prefix its framework exposes. Vite uses VITE_. In Next.js, name it NEXT_PUBLIC_AMPLITUDE_API_KEY instead. A Node.js server reads an unprefixed name such as AMPLITUDE_API_KEY.

Why. The project API key is public, and its scope is limited to ingesting data, so it isn't a secret the way a server credential is. Keep it in the env file anyway, since a hardcoded key lives forever in forks and Git history.

3. Run the install prompt in Supervised mode

Kiro starts in Autopilot, which edits files and runs commands without stopping. Switch the chat to Supervised with the autopilot toggle in the chat panel before you send this prompt. In Supervised mode, Kiro stops after each turn that edits files and shows the changes as hunks you accept or reject.

Paste this prompt into the chat. It points Kiro at the Quickstart through the Docs server instead of its memory, and pins the decisions agents most often get wrong.

Prompt for Kiro
Install Amplitude analytics in this project.

Before writing code:
1. Use the amplitude-docs MCP server. Call get_page on
   "get-started/amplitude-quickstart" and use the install path it
   recommends for this project's stack. Do not pick a package from memory.
2. Use the amplitude-mcp MCP server. Call get_amplitude_context, list my
   projects, and ask me which project this app should send to.
3. Show me your plan and wait for my approval before editing files or
   running commands.

Then:
- Read the API key from the environment variable already in my env file
  (VITE_AMPLITUDE_API_KEY in a Vite app, NEXT_PUBLIC_AMPLITUDE_API_KEY in
  Next.js). Never hardcode the key.
- Initialize the SDK exactly once, at app or process startup, outside any
  render path or request handler. If this framework renders pages on the
  server, guard browser init with typeof window !== "undefined".
- For a browser SDK that supports it, set sessionReplay.sampleRate to 1,
  and tell me that session replay is on and how to turn it off.
- In browser code, rely on autocapture for page views. Do not add manual
  page view tracking.
- If the app has a login flow, call setUserId with the signed-in user's ID
  after login and reset() on logout.
- User IDs must be strings of 5 or more characters. If our IDs are integers,
  prefix them, for example "user-" + id, and use the same format on client
  and server.
- In server code, pass user_id or device_id on every track call, and await
  flush().promise before the process exits or a serverless handler returns.
- Do not add any custom events yet.

When you finish, list every file you changed and every command you ran.

Kiro comes back with the docs page it read, a project question, and a plan. Pick the project, approve the plan, then accept or reject each hunk as Kiro edits files.

4. Review what Kiro changed

Run git diff before you start the app, or ask Kiro to walk you through it with #git diff in the chat. Don't rely on the hunk review alone. Kiro's Revert button and its checkpoints only track files the agent edits with its own file tools. Changes made by commands it runs, such as npm install rewriting package.json and your lockfile, aren't tracked, so they don't roll back when you revert.

These are the mistakes that show up most often, and each takes seconds to spot:

  1. Package. For browser apps installed from npm, the Quickstart recommends @amplitude/unified. For Node.js servers, it's @amplitude/analytics-node. Anything else deserves a question.
  2. API key. Search the diff for the literal key. It should appear only in your env file, never in source.
  3. Init location. One initAll or init call, in a module that runs once. Not inside a React useEffect, a component body, or an Express route.
  4. Server rendering. In a framework that renders on the server, such as Next.js, browser init sits behind typeof window !== "undefined".
  5. Duplicate page views. No hand-written track("Page Viewed") next to autocapture, which tracks page views by default.
  6. Server flushing. Every server-side track path ends with await flush().promise before shutdown or before a serverless handler returns.
  7. Session replay. @amplitude/unified records sessions when sessionReplay.sampleRate is above 0. Keep it, or set it to 0 on purpose.

For a Vite browser app, a correct result looks like this. In Next.js, the variable is process.env.NEXT_PUBLIC_AMPLITUDE_API_KEY instead, and the call sits inside the typeof window check.

src/lib/amplitude.ts
import { initAll } from "@amplitude/unified";

initAll(import.meta.env.VITE_AMPLITUDE_API_KEY, {
  sessionReplay: {
    sampleRate: 1, // set to 0 to turn session replay off
  },
});

If something fails the review, ask Kiro to fix it in the same session:

Prompt for Kiro
Move the Amplitude init out of the component into src/lib/amplitude.ts so
it runs once at startup, and read the key from the environment instead of
the literal string. Show me the diff.

5. Add an event that matches your taxonomy

This is where the Amplitude MCP server earns its setup. Ask Kiro to check what already exists, in the code and in Amplitude, before it names anything.

Prompt for Kiro
I want to track when a user exports a report, with the file format they
chose as a property.

1. Find how analytics is already implemented in this repo: import paths,
   helper functions, and event naming style.
2. Use the amplitude-mcp server's get_amp_taxonomy tool to list the
   existing events and event properties in the project we picked.
3. If an event for this already exists, use its exact name and property
   names. If not, propose a name that matches the casing of the existing
   events, and wait for me to confirm it.
4. Add one track call where the export actually completes, after the
   request succeeds, not in an effect or a render.

If your tracking plan uses Title Case with spaces, Kiro should propose Report Exported, not reportExported or report_exported. Once you confirm, it adds a single call in the export handler:

src/features/reports/ExportButton.tsx (inside the click handler, after the export succeeds)
import { track } from "@amplitude/unified";

track("Report Exported", { format });

MCP. Kiro can also add the new event to your tracking plan with manage_amp_events, if your Amplitude role has the Use MCP (write) permission and the Update Tracking Plan permission in Amplitude Data. Ask it to create the event as planned, so the tracking plan knows about Report Exported before the first one arrives.

Verify it worked

Run the app the way you normally do, load a page, export a report, then check in this order:

  1. Network tab or process logs. In the browser, filter the Network tab for api2.amplitude.com and look for a POST to /2/httpapi returning 200. On a server, set the SDK's logLevel to Debug and watch the upload in the terminal.
  2. Ingestion Debugger. In Amplitude, click Data, select Sources, then open the Ingestion Debugger tab. The successful requests and the events and identify counts charts should show your uploads.
  3. User Profiles. Go to Users > User Profiles and search your user ID or device ID. [Amplitude] Page Viewed and Report Exported appear in the event stream within ten seconds to a minute. Click Report Exported to confirm the format value.
  4. Ask Kiro. With the Amplitude MCP server connected, ask it to check the data for you:
Prompt for Kiro
Using the amplitude-mcp server, look up my user profile in this project
and tell me whether "Report Exported" arrived in the last hour and which
format values it has.

Troubleshooting

Kiro says it has no Amplitude tools

Open the Kiro panel's MCP servers tab. If the servers are missing, the JSON didn't parse or wasn't saved; fix any missing comma or bracket and save again. If no servers appear at all, open Settings (Cmd+, or Ctrl+,), search for "MCP", and turn on MCP support. For anything else, open the Kiro panel's Output tab and choose Kiro - MCP Logs.

The OAuth page spins and never finishes

Close the tab after you approve access. Make sure you're signed in to only one Amplitude organization during the flow, since signing in to several can break authentication. If it still fails, right-click amplitude-mcp in the MCP servers tab, choose Reconnect, and sign in again. If a token expires later, use the Re-authenticate button that appears in the MCP panel.

Kiro installed a different package than the Quickstart names

It skipped the docs lookup. Ask it to call get_page on get-started/amplitude-quickstart through amplitude-docs and redo the install from that page.

You reverted Kiro's changes, but the Amplitude package is still installed

Revert and checkpoints don't undo commands Kiro ran, so the npm install changes to package.json and the lockfile stay. Run git diff package.json to confirm, then npm uninstall @amplitude/unified, or restore both files from Git.

Events show in the Network tab but not in the project

The key belongs to a different project than the one you picked, or it's an EU project sending to the US endpoint. Compare the key in your env file with Settings > Projects > your project > General, and set serverZone: "EU" in initAll for EU projects.

User Profiles shows events with no user ID

The ID is shorter than 5 characters, so Amplitude dropped it. Integer database IDs like 42 fail this. Prefix them, for example user-42, and use the same format on the server.

Kiro ignores the steering file

The front matter must be the very first content in the file, with no blank line above the opening ---. If you chat through a custom agent, steering files aren't loaded automatically; add "file://.kiro/steering/**/*.md" to the agent's resources.

Save the rules in .kiro/steering

Steering files are Markdown files Kiro loads as persistent project context. Files in .kiro/steering/ apply to this workspace; files in ~/.kiro/steering/ apply to every workspace, and workspace steering wins when the two conflict. Put the conventions from this page in a workspace file and commit it, so your teammates' Kiro sessions follow the same rules.

You can create the file from the Steering section of the Kiro panel (click +, choose workspace scope) or write it directly as .kiro/steering/analytics.md. The front matter has to be the first content in the file, so there's no filename comment above it:

.kiro/steering/analytics.md
---
inclusion: always
---

# Analytics (Amplitude)

- Look up Amplitude SDK usage with the amplitude-docs MCP server before
  writing analytics code. Never install or import Amplitude packages from
  memory.
- Before adding a track call, list existing events with the amplitude-mcp
  server (get_amp_taxonomy) and reuse existing event and property names.
  Match the existing casing. Ask before creating a new event name.
- The SDK is initialized once in src/lib/amplitude.ts. Never call init or
  initAll anywhere else.
- Read the API key from the environment. Never hardcode it.
- Page views come from autocapture. Never add manual page view tracking.
- User IDs are "user-" + the database ID, the same on client and server.
  Call setUserId after login and reset() on logout.
- Server code passes user_id or device_id on every track call and awaits
  flush().promise before exit or before a serverless handler returns.
- Track user actions in event handlers after the action succeeds, not in
  effects or render paths.
- Ask before creating tracking-plan events.

Current init file: #[[file:src/lib/amplitude.ts]]

The inclusion: always front matter loads it into every interaction, and the #[[file:...]] line pulls in the current contents of the init file, so Kiro reads the real code next to the rules. Change src/lib/amplitude.ts in both places if Kiro chose a different path in step 3. Never put the key itself in a steering file; steering files are part of your codebase.

If you'd rather load the rules only when they're relevant, replace the front matter with inclusion: auto plus a name and a description such as "Amplitude analytics rules. Use when adding or changing tracking code." Kiro then includes the file when a request matches the description.

What this unlocks

  • Session replay, if you kept sampleRate above 0, lets you watch the session where Report Exported fired, and Kiro can pull that replay's interaction timeline through the Amplitude MCP server's session replay tools.
  • Heatmaps, built from those same session replays, show where people clicked on the reports page before they exported.
  • Feature Experiment can test a new export flow with Report Exported as the success metric, and Kiro can create the flag with create_flags.
  • Guides and surveys can nudge people who opened the reports page but never fired Report Exported.

One integration; everything else reads from the same events.

Next steps

Amplitude is the leading all-in-one analytics platform for building better products. Product and engineering teams use Amplitude to connect product analytics and web analytics with session replay, heatmaps, experimentation, feature flags, and guides and surveys in one unified workflow, with AI agents working across all of it. Learn how Amplitude is building self-improving products with Wave, helping teams turn product data into PRs.

Ship the instrumentation, then read the data

Once events are flowing, Amplitude turns them into funnels, retention curves, and session replays without any further setup.