---
title: "How to add product analytics to your app with Devin Desktop"
description: "Connect Devin Desktop (formerly Windsurf) to Amplitude's MCP servers, have its agent install the SDK, review the diff, and save rules in .devin/rules."
canonical: "https://amplitude.com/en-us/build/devin-desktop-product-analytics"
---

# How to add product analytics to your app with Devin Desktop

Connect Devin Desktop (formerly Windsurf) to Amplitude's MCP servers, have its agent install the SDK, review the diff, and save rules in .devin/rules.

Source: https://amplitude.com/en-us/build/devin-desktop-product-analytics

---

# How to add product analytics to your app with Devin Desktop

Connect Devin Desktop to Amplitude's MCP servers with one project config file, hand its agent one prompt that installs the SDK the docs recommend for your stack, review the diff for the mistakes agents make, and save the rules as a workspace rule. About 15 minutes, all copy-paste.

- Devin Desktop
- Formerly Windsurf
- Amplitude MCP
- .devin/rules
- 15 min

Chris Tam · Last updated 6 October 2026

Devin Desktop, the AI IDE formerly called Windsurf, runs a Devin Local agent that can add [product analytics](https://amplitude.com/amplitude-analytics) to your app in one session, as long as it reads current docs and your real event names instead of guessing.

In this tutorial, you'll [connect Devin Desktop to Amplitude](https://amplitude.com/mcp), add your API key, have the agent install the SDK, review its diff, and save the rules in `.devin/rules`.

## What you'll build

A Devin Desktop project connected to the Amplitude MCP server and the Docs MCP server through a committed `.devin/mcp_config.json`, an app instrumented with the SDK the Quickstart recommends for its stack, one `Report Exported` event named to match your existing taxonomy, and a workspace rule that keeps the agent on those conventions. By the end you'll see live events in your Amplitude project.

## Prerequisites

- A current Devin Desktop release. Windsurf was renamed Devin Desktop on June 2, 2026, and its Cascade agent was removed in September 2026, so this page uses Devin Local, the only agent left. On Enterprise plans, an admin has to turn on the Devin Local Agent team setting before it appears. Setup guides that mention Cascade or the Cascade panel's MCP menu no longer match what you see.
- A web or Node.js project open as a workspace, in a Git repository, so you can review and revert the agent'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](https://app.amplitude.com/signup) to get your project API key.

## 1. Connect Devin Desktop to Amplitude

Add two MCP 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. Devin Local supports remote Streamable HTTP servers with OAuth, which is what Amplitude's MCP server uses; the [setup guide for MCP clients](https://amplitude.com/docs/amplitude-ai/amplitude-mcp/other-clients) has the full reference. The [Docs MCP server page](https://amplitude.com/docs/amplitude-ai/docs-mcp-server) is the source for the second URL.

Devin Local reads MCP servers from config files that it shares with Devin CLI, not from the Cascade `mcp_config.json` older Windsurf guides describe. Create `.devin/mcp_config.json` at your repository root with this content (JSON allows no comments, so the filename stays out of the file):

.devin/mcp\_config.json

```json
{
  "mcpServers": {
    "amplitude": {
      "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`. This is the project scope in [Devin's MCP configuration docs](https://docs.devin.ai/cli/extensibility/mcp/configuration), so you can commit it and your teammates get the same two servers. Neither entry holds a credential: the Amplitude server signs in with OAuth and stores its tokens on each person's machine, and the Docs server is public. To use the servers in every project instead, put the same `mcpServers` block in `~/.config/devin/mcp_config.json` (`%APPDATA%\devin\mcp_config.json` on Windows).

Then authenticate. Open **Open customizations** from the new-tab menu in the agent space, find `amplitude` under MCP servers, and click **Authenticate** if it shows **Needs auth**. A browser window opens for the Amplitude OAuth flow. If you skip this, the agent prompts you the first time it uses the server.

Check the connection by starting a new Devin Local session in the workspace and asking:

Prompt for Devin Desktop

```text
What Amplitude projects can I access?
```

Devin Local asks for approval before it calls any MCP tool. Approve the call; you can allow a single tool or every tool on that server, for the session or permanently. A list of your projects means the Amplitude MCP server is connected and authenticated.

**Why.** The Amplitude MCP server isn't an ingestion endpoint and never sends your app's events. It's how the agent reads your taxonomy and checks results. The SDK still does the sending. The Docs server is what stops the agent from writing a package name from training data.

## 2. Add your API key to your env file

Add the key yourself, before you run the install prompt. Devin Desktop's **Gitignore access** setting is off by default, so the agent may not be able to read files your `.gitignore` excludes, and `.env.local` usually is one of them. That's fine: the agent only needs the variable's name, and keeping the value out of its reach means it can't paste the literal key into source.

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

.env.local

```sh
VITE_AMPLITUDE_API_KEY=your-project-api-key
```

Devin Desktop doesn't pick your stack, so use the name your framework exposes to the browser. In Next.js it's `NEXT_PUBLIC_AMPLITUDE_API_KEY`. A Node.js server reads a plain `AMPLITUDE_API_KEY`.

**Why.** The project API key is public and its scope is limited to the minimum needed to ingest 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

Paste this prompt into a Devin Local session. If you want to approve a written plan before any file changes, switch the session to Plan mode first; Devin Local researches read-only, writes the plan, and waits for your approval. The prompt points the agent at the Quickstart through the Docs server instead of its memory, and pins the decisions agents most often get wrong.

Prompt for Devin Desktop

```text
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 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.

Then:
- Read the API key from the environment variable I already added
  (VITE_AMPLITUDE_API_KEY, or the prefixed name this framework needs to
  expose it to the browser). Never hardcode it, and do not create or edit
  any .env file. Tell me if the variable name needs to change.
- Initialize the SDK exactly once, at app or process startup, outside any
  render path or request handler. If pages render on the server, guard
  browser init with typeof window !== "undefined".
- 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.
- 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.
- Do not add any custom events yet.

When you finish, list every file you changed and why.
```

The agent comes back with the docs page it read, a project question, and a plan. Approve the MCP calls, pick the project, approve the plan, and let it apply the change.

## 4. Review what the agent changed

Devin Desktop shows each edit as a diff zone in the editor, with accept and reject controls on every hunk. Review those, then run `git diff` before you start the app. 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 Next.js or another framework that renders on the server, `initAll` sits behind a `typeof window !== "undefined"` check, or the server tries to run browser-only code.
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 goes inside the `typeof window` check.

src/lib/amplitude.ts

```typescript
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, reject the hunk or ask the agent to fix it in the same session:

Prompt for Devin Desktop

```text
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 MCP server earns its setup. Ask the agent to check what already exists, in the code and in Amplitude, before it names anything.

Prompt for Devin Desktop

```text
I want to track when a user exports a report, with the file format 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, the agent 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)

```typescript
import { track } from "@amplitude/unified";

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

**MCP.** The agent 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. Devin Local asks before that write call too, so keep write tools on approval even if you allow the read tools permanently.

## 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.** Open the app in your browser, filter the DevTools 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 the agent.** With the Amplitude MCP server connected, ask it to check the data for you:

Prompt for Devin Desktop

```text
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

### The agent says it has no Amplitude tools

The config file isn't where Devin Local looks, or the session started before you added it. Confirm the file is `.devin/mcp_config.json` at the workspace root, with servers under `mcpServers`, then check that `amplitude` and `amplitude-docs` appear under MCP servers in **Open customizations** and start a new session. An entry in an old Windsurf `mcp_config.json` from the Cascade days isn't the same file.

### The server shows Needs auth, or the OAuth page spins and never finishes

Click **Authenticate** next to `amplitude` in the MCP server list, and close the browser tab after you approve access. Sign in to only one Amplitude organization during the flow, since signing in to several can break authentication. Each MCP client keeps its own OAuth session, so signing in from another editor doesn't carry over.

### The agent 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.

### The agent says the API key is missing, or created a new .env file

It can't see your gitignored env file, so it guessed. Delete any env file it created, keep the line from step 2 in your own `.env.local`, and tell the agent the variable's name. Only turn on **Gitignore access** (Devin Settings > Devin Local > Configuration) if you want the agent to read those files.

### 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.

### The MCP server returns a permission error on taxonomy writes

Your role lacks **Use MCP (write)** or the Update Tracking Plan permission in Amplitude Data. Reads still work in that case. If reads fail too, your org admin may have blocked MCP access under Settings > Content Access > MCP. Ask an admin for write access, or make the tracking-plan change in the Amplitude UI.

## Save the rules in .devin/rules

Devin Local loads workspace rules from `.devin/rules/` at the start of every session, so the conventions from this page apply the next time you ask it to track something, without the long prompt. Rules already in `.windsurf/rules/` keep working; `.devin/rules/` is the preferred location. Create `.devin/rules/amplitude-analytics.md` with this content, starting with the `---` line, and commit it so your teammates' sessions follow the same rules:

.devin/rules/amplitude-analytics.md

```markdown
---
trigger: always_on
---

# 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, and never
  create or edit .env files.
- 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.
```

The `trigger: always_on` frontmatter keeps the rule in every session. Change `src/lib/amplitude.ts` to the file the agent created in step 3 if it chose a different path. Keep the rule short, since an always-on rule loads into every session. If your repository already has an `AGENTS.md` at the root, you can paste the same bullets there instead; Devin Local reads it as an always-on rule too.

## What this unlocks

- [Session replay](https://amplitude.com/session-replay), if you kept `sampleRate` above 0, lets you watch the session where `Report Exported` fired, or the one where someone opened the export menu and gave up.
- [Heatmaps](https://amplitude.com/heatmaps), built from those same session replays, show where people clicked on the reports page before they exported.
- [Feature Experiment](https://amplitude.com/amplitude-experiment) can test a new export flow with `Report Exported` as the success metric, and the agent can create the flag through the Amplitude MCP server with `create_flags`.
- [Guides and surveys](https://amplitude.com/guides-and-surveys) can point people who open reports but never fire `Report Exported` to the export button.

One integration; everything else reads from the same events.

## Next steps

[Web frameworksAdd product analytics to a React appWhat the correct browser install looks like, file by file, so you can check the agent's work against it.](/build/react-product-analytics)[Web frameworksAdd product analytics to a Node.js backendServer-side identity and flushing, the two things agents most often get wrong.](/build/nodejs-product-analytics)[AI coding toolsAdd analytics to your app with Codex CLIThe same workflow in OpenAI's Codex CLI, with the rules saved in AGENTS.md.](/build/codex-cli-analytics)

Reference docs

[Connect Amplitude MCP to other MCP clients →](https://amplitude.com/docs/amplitude-ai/amplitude-mcp/other-clients)[Amplitude MCP server →](https://amplitude.com/docs/amplitude-ai/amplitude-mcp)[Docs MCP server →](https://amplitude.com/docs/amplitude-ai/docs-mcp-server)[Amplitude Quickstart →](https://amplitude.com/docs/get-started/amplitude-quickstart)[Browser Unified SDK →](https://amplitude.com/docs/sdks/analytics/browser/browser-unified-sdk)[Debug analytics →](https://amplitude.com/docs/analytics/debug-analytics)

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

For agents

[View raw .md](/build/devin-desktop-product-analytics.md)[llms.txt](/llms.txt)

## 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.

[Create a free account](https://app.amplitude.com/signup)[Browse all Build tutorials](https://amplitude.com/build)
