@flusterduck/mcp-server 0.7.4 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/{chunk-FRDZ4X3Q.js → chunk-ZOOXS6IG.js} +63 -7
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ Configuration is read from environment variables:
|
|
|
29
29
|
|---|---|---|
|
|
30
30
|
| `FLUSTERDUCK_MCP_KEY` | yes | Your Flusterduck MCP key (`fd_mcp_...`). `FLUSTERDUCK_API_KEY` is accepted as an alias. |
|
|
31
31
|
| `FLUSTERDUCK_SITE_ID` | yes | The site (UUID) whose data you want to expose. |
|
|
32
|
-
| `FLUSTERDUCK_ORG_ID` | no | Org ID. Required only for the audit log, degradation,
|
|
32
|
+
| `FLUSTERDUCK_ORG_ID` | no | Org ID. Required only for the audit log, degradation, webhook delivery, and send_feedback tools. |
|
|
33
33
|
| `FLUSTERDUCK_API_URL` | no | Override the Flusterduck query API base URL. Defaults to the hosted Flusterduck API. |
|
|
34
34
|
|
|
35
35
|
Use an MCP key (`fd_mcp_`) or a secret key (`fd_sec_`). Publishable keys (`fd_pub_`) are browser-only and will not authenticate against the query API. Write tools (issue/alert updates, alert-rule and annotation management) require a key with `manage:write` scope.
|
|
@@ -57,6 +57,7 @@ Add to your `claude_desktop_config.json`:
|
|
|
57
57
|
|
|
58
58
|
| Tool | Description |
|
|
59
59
|
|---|---|
|
|
60
|
+
| `whoami` | What this key is: org/site scope and granted scopes |
|
|
60
61
|
| `get_site_context` | Full MCP snapshot for the configured site |
|
|
61
62
|
| `get_scores` | Current page confusion scores |
|
|
62
63
|
| `get_page` | Score history, issues, alerts, and elements for one page |
|
|
@@ -81,7 +82,7 @@ Add to your `claude_desktop_config.json`:
|
|
|
81
82
|
| `get_degradation` | Active backend degradation events (requires org ID) |
|
|
82
83
|
| `get_webhook_deliveries` | Outbound webhook delivery history (requires org ID) |
|
|
83
84
|
|
|
84
|
-
Write tools (require `manage:write` scope): `update_issue`, `update_alert`, `add_annotation`, `create_alert_rule`, `update_alert_rule`, `delete_alert_rule
|
|
85
|
+
Write tools (require `manage:write` scope): `update_issue`, `rate_issue`, `update_alert`, `add_annotation`, `create_alert_rule`, `update_alert_rule`, `delete_alert_rule`, and `send_feedback` (send suggestions or bug reports about Flusterduck itself to the team; needs `FLUSTERDUCK_ORG_ID`).
|
|
85
86
|
|
|
86
87
|
## Resources
|
|
87
88
|
|
|
@@ -135,6 +135,9 @@ var FlusterduckAPI = class {
|
|
|
135
135
|
getGuideStats() {
|
|
136
136
|
return this.request("query/guide-stats");
|
|
137
137
|
}
|
|
138
|
+
whoami() {
|
|
139
|
+
return this.request("query/whoami");
|
|
140
|
+
}
|
|
138
141
|
getAlertDetail(alertId) {
|
|
139
142
|
return this.request(`query/alerts/${assertUuid(alertId, "alert_id")}`, {});
|
|
140
143
|
}
|
|
@@ -150,6 +153,13 @@ var FlusterduckAPI = class {
|
|
|
150
153
|
updateIssue(issueId, update) {
|
|
151
154
|
return this.mutate("PATCH", `manage/issues/${assertUuid(issueId, "issue_id")}`, update);
|
|
152
155
|
}
|
|
156
|
+
rateIssue(issueId, verdict) {
|
|
157
|
+
return this.mutate("PATCH", `manage/issues/${assertUuid(issueId, "issue_id")}`, { feedback_verdict: verdict });
|
|
158
|
+
}
|
|
159
|
+
sendFeedback(kind, message) {
|
|
160
|
+
if (!this.config.orgId) throw new Error("orgId is required to send feedback.");
|
|
161
|
+
return this.mutate("POST", "manage/feedback", { org_id: this.config.orgId, kind, message });
|
|
162
|
+
}
|
|
153
163
|
updateAlert(alertId, status, resolvedReason) {
|
|
154
164
|
const body = { status };
|
|
155
165
|
if (resolvedReason) body.resolved_reason = resolvedReason;
|
|
@@ -340,12 +350,12 @@ Paid product. No free tier. No open-source version.
|
|
|
340
350
|
|
|
341
351
|
| Plan | Monthly | Sessions | Sites | Key features |
|
|
342
352
|
|---|---|---|---|---|
|
|
343
|
-
| Grow | $
|
|
344
|
-
| Scale | $
|
|
345
|
-
| Pro | $
|
|
353
|
+
| Grow | $99 | Up to 50,000 | 1 | Core friction detection, issues, alerts, MCP access, 2 autofixes a month |
|
|
354
|
+
| Scale | $249 | Up to 250,000 | 5 | Everything in Grow, plus team members, Slack integration, 10 autofixes a month |
|
|
355
|
+
| Pro | $499 | Up to 1,000,000 | 10 | Everything in Scale, plus unlimited members, revenue estimates, priority support, 30 autofixes a month |
|
|
346
356
|
| Enterprise | Custom | Custom | Unlimited | Custom volume, SSO, dedicated support, SLA |
|
|
347
357
|
|
|
348
|
-
Session limits are pooled across all sites in the org, not per-site. All plans include a
|
|
358
|
+
Session limits are pooled across all sites in the org, not per-site. All plans include a 3-day free trial with a card on file. You are not charged until the trial ends, and you can cancel any time before then.
|
|
349
359
|
`
|
|
350
360
|
},
|
|
351
361
|
{
|
|
@@ -502,6 +512,13 @@ Session limits are pooled across all sites in the org, not per-site. All plans i
|
|
|
502
512
|
"group": "Product",
|
|
503
513
|
"content": '# Issues\n\nAn issue is what Flusterduck produces when enough users hit the same friction pattern on the same element. Not a raw signal count. A clustered, evidence-backed problem with a specific location, a root cause hypothesis, and a lifecycle that tracks whether it got fixed.\n\nIssues work like tickets. They get statuses, triage notes, assignees, and verification after you ship a fix.\n\n## How issues are created\n\nThe scoring engine watches for signal clusters: the same signal type on the same element, repeated across sessions from different users. When a cluster crosses the confidence threshold, an issue is created.\n\nOne user rage-clicking a button 40 times doesn\'t create an issue. Forty different users rage-clicking the same button over three days does.\n\nThe clustering algorithm weighs:\n- Signal type match (same type, or co-occurring types on the same element)\n- Element selector match (fuzzy-matched to handle minor DOM changes between deploys)\n- Session diversity (signals from distinct sessions, not a single frustrated user)\n- Time window (7 days for initial creation, longer for ongoing patterns)\n\n## Issue fields\n\n| Field | Description |\n|---|---|\n| `id` | Unique identifier with `iss_` prefix |\n| `title` | Generated description of the problem |\n| `page` | Page path where the issue occurs |\n| `selector` | CSS selector of the affected element |\n| `signal_type` | Dominant signal type driving the cluster |\n| `signal_count` | Total signals in the cluster |\n| `severity` | 0-100 score based on signal tier, volume, page importance, and revenue exposure |\n| `status` | Current lifecycle state |\n| `hypothesis` | Engine-generated root cause guess |\n| `sessions` | Session IDs containing this friction pattern |\n| `verifications` | Deploy-correlated verification records |\n\n## Issue lifecycle\n\n**`open`**: the issue exists and nobody has acted on it. New issues land here automatically.\n\n**`triaged`**: someone reviewed it and confirmed it\'s real. Add a note with context before moving it here. "Confirmed on mobile Safari. The submit button is obscured by the cookie banner at 375px." is more useful than just a status change.\n\n**`in_progress`**: someone is actively working a fix. This prevents duplicate effort when multiple engineers are looking at the same issue list.\n\n**`verified`**: the issue was resolved and the scoring engine confirmed the fix held after the next deploy. The friction pattern didn\'t return.\n\n**`regressed`**: the issue was resolved, but the confusion pattern came back. The engine re-opens it automatically. This happens when a fix gets reverted, a related change reintroduces the problem, or the original fix was partial.\n\n**`ignored`**: known issue, won\'t fix. Alert rules won\'t fire for ignored issues, and they won\'t count toward your open issue total. Use this deliberately, not as a way to clear your queue.\n\n### Moving issues forward\n\nVia the API:\n\n```bash\ncurl -X POST https://api.flusterduck.com/v1/issues/iss_xxxxxxxxxxxx \\\n -H "Authorization: Bearer fd_sec_xxxxxxxxxxxx" \\\n -H "Content-Type: application/json" \\\n -d \'{\n "status": "triaged",\n "note": "Confirmed on mobile. Submit button overlaps cookie banner at 375px.",\n "assigned_to": "maya"\n }\'\n```\n\nVia MCP:\n\n```\nTriage the open issues and tell me what to fix first.\nMark issue iss_xxxxxxxxxxxx as in_progress and assign it to alex.\n```\n\n## Severity scoring\n\nSeverity (0-100) reflects how much a specific issue is hurting your users. Higher severity means more sessions affected, higher-tier signals, more revenue exposure.\n\nIt incorporates:\n- Signal tier of the dominant signal type\n- Signal volume and percentage of sessions affected\n- Page importance (checkout and pricing have higher baseline weights)\n- Revenue exposure (whether conversion events were tracked near this element in affected sessions)\n- Recency (signals from the last 48 hours weight more than older ones)\n\nUse severity for relative prioritization within your open issue list. Don\'t treat it as an absolute scale. A severity 40 issue on /checkout probably matters more than a severity 70 issue on your admin changelog page.\n\n## Verification\n\nAfter each deploy, the scoring engine runs verification on all open and recently-resolved issues.\n\nFor **resolved** issues: checks whether the signal cluster has declined. If signals dropped, it marks the issue `verified`. If signals are still at pre-fix levels, it marks it `regressed`.\n\nFor **open** issues: recalculates evidence, updates `signal_count` and `severity`, and checks whether the pattern is intensifying or fading.\n\nVerification needs deploy records to work correctly. Without them, the engine can\'t know when to run the verification cycle. See [Deploy Correlation](./deploy-correlation).\n\n## Evidence sessions\n\nEvery issue includes a `sessions` array: session IDs where the friction pattern appears. These are the most useful thing in an issue for diagnosing root cause.\n\n```bash\ncurl "https://api.flusterduck.com/v1/session?session_id=ses_xxxxxxxxxxxx" \\\n -H "Authorization: Bearer fd_sec_xxxxxxxxxxxx"\n```\n\nThe session endpoint returns the full chronological event timeline: page views, signal types, selectors, timestamps. You can see exactly what the user did before and after the friction moment.\n\nVia MCP:\n\n```\nInvestigate session ses_xxxxxxxxxxxx.\nWhich sessions show rage clicks on the upgrade button?\n```\n\n## Root cause hypotheses\n\nThe engine generates a hypothesis for every issue based on signal type and element context:\n\n- Dead clicks on a button: "Element appears clickable but navigates to an unexpected destination or produces no visible response."\n- Rage clicks on a form field: "Field appears interactive but input is blocked or significantly delayed."\n- Form abandonment at a specific step: "Required information may be unclear, the step label may not match user expectation, or a validation message is obscured."\n\nHypotheses are starting points. They\'re generated from behavioral signals, not from visual inspection of your UI. Confirm or reject them with the session evidence and your own knowledge of the page.\n\n## Getting all issues via the API\n\n```bash\ncurl "https://api.flusterduck.com/v1/issues?status=open" \\\n -H "Authorization: Bearer fd_sec_xxxxxxxxxxxx"\n```\n\n```json\n{\n "issues": [\n {\n "id": "iss_xxxxxxxxxxxx",\n "title": "Dead clicks on complete purchase button",\n "page": "/checkout",\n "selector": "button[type=\'submit\']",\n "signal_type": "dead_click",\n "signal_count": 47,\n "severity": 84,\n "status": "open",\n "created_at": "2026-06-08T11:30:00Z"\n }\n ],\n "total": 1\n}\n```\n\nFilter by any status: `open`, `triaged`, `in_progress`, `verified`, `resolved`, `regressed`, `ignored`.\n\n## Getting full issue detail\n\n```bash\ncurl "https://api.flusterduck.com/v1/issues/iss_xxxxxxxxxxxx" \\\n -H "Authorization: Bearer fd_sec_xxxxxxxxxxxx"\n```\n\nReturns the full issue object including `hypothesis`, `sessions`, and `verifications`.\n\n## What issues don\'t cover\n\nIssues require signal clusters from multiple users. Single-session bugs, one-off failures, and problems that affect a small percentage of users on a specific device or browser may not generate enough signal volume to create an issue automatically.\n\nFor those cases, use `signal()` manually to attach extra metadata to auto-detected signals. The more context you give the engine, the faster it can cluster related signals:\n\n```ts\nsignal(\'error_recovery_loop\', {\n form: \'payment\',\n step: \'card-entry\',\n error_code: \'card_declined\',\n})\n```\n\nCustom metadata gets attached to the issue evidence when a cluster forms.\n'
|
|
504
514
|
},
|
|
515
|
+
{
|
|
516
|
+
"slug": "ai-detection",
|
|
517
|
+
"title": "AI detection",
|
|
518
|
+
"description": "A nightly AI analyst investigates your day of sessions and files receipt-checked issues itself.",
|
|
519
|
+
"group": "Product",
|
|
520
|
+
"content": "# AI detection\n\nAI detection puts an AI analyst on your site. Each night it reads a compressed summary of the day's real sessions, investigates whatever looks off, and files issues itself: pulled sessions, page content, deploy timing, and cursor movement all feed the same investigation a good UX analyst would run by hand.\n\nIt is on by default for every site. Built-in pattern detection remains as the fallback: if a month's AI allowance runs out early, it takes over filing new issues until the 1st. You can opt a site out any time under Settings, then AI.\n\n## What it does differently\n\nBuilt-in detection recognizes friction patterns it has names for: rage clicks, dead clicks, abandoned forms. The AI analyst is not limited to named patterns. It can connect a checkout struggle and an upgrade-flow struggle into one underlying issue, notice sessions that quietly left the money path without tripping any detector, and use a page's actual content to tell exploration from confusion.\n\nEvery issue it files carries receipts. The analyst must cite the sessions it examined, and Flusterduck verifies those citations against your data before anything is written. Claims that do not check out are rejected. One angry session never becomes a critical issue: severity is bounded by how many users the evidence actually shows.\n\n## The analyst remembers your site\n\nThe analyst keeps a working model of each site: what the product is, its money paths, its weak points, and a ledger of hypotheses it is watching. A pattern too thin to file tonight accumulates evidence across nights and gets filed when it clears the bar. Issues it files again update in place rather than duplicating.\n\n## Run history and running on demand\n\nSettings, then AI shows every investigation: when it ran, how many steps it took, and how many issues it filed. Owners and admins also get a Run now button there, so you can watch a run land right after a deploy or a traffic spike instead of waiting for tonight. On-demand runs use the same allowance and the same verification bar as nightly ones.\n\n## Cost and the graceful fallback\n\nAI detection runs on Flusterduck's infrastructure inside your plan's AI allowance. There is nothing to configure and no per-run bill. If a month's allowance runs out early, built-in detection takes over minting new issues for the rest of the month, and the analyst resumes on the 1st. Real-time scores, alerts, and deploy verification are unaffected either way; they never depend on the nightly run.\n\nDuring a trial the analyst runs with a small fixed allowance so you can see it work before subscribing.\n\n## What it never does\n\n- It never records your users. The analyst reads the same behavioral events the SDK already sends: no session replay, no keystrokes, no form values, no PII.\n- It never files an uncited issue. Every issue names the sessions behind it.\n- It never touches your site or your code. Filing issues is the whole job; Autofix stays a separate, separately-permissioned feature.\n"
|
|
521
|
+
},
|
|
505
522
|
{
|
|
506
523
|
"slug": "heatmaps",
|
|
507
524
|
"title": "Heatmaps",
|
|
@@ -542,7 +559,7 @@ Session limits are pooled across all sites in the org, not per-site. All plans i
|
|
|
542
559
|
"title": "MCP integration",
|
|
543
560
|
"description": "Give your AI assistant read access to scores, issues, journeys, and revenue leakage.",
|
|
544
561
|
"group": "Integrations",
|
|
545
|
-
"content": '# MCP Integration\n\nSet this up once and you stop opening the dashboard to check on friction data. Ask your AI assistant:\n\n> "What\'s broken on checkout right now?"\n\nIt calls `get_site_context`, pulls your live scores and open issues, and tells you. Post-deploy checks, issue triage, weekly summaries. All without touching a UI.\n\n## Fastest install\n\nThe hosted server needs no keys and no install. Add the URL and sign in with your Flusterduck account when your client prompts you:\n\n```bash\nclaude mcp add --transport http flusterduck https://mcp.flusterduck.com/mcp\n```\n\nPrefer running the server locally (stdio)? `npx` fetches it on first run. Grab an MCP key and your site ID from the dashboard (Settings \u2192 API keys), then:\n\n```bash\nclaude mcp add flusterduck \\\n --env FLUSTERDUCK_MCP_KEY=fd_mcp_xxxxxxxxxxxx \\\n --env FLUSTERDUCK_SITE_ID=your-site-id \\\n -- npx -y @flusterduck/mcp-server\n```\n\n## Setup\n\n### Claude Desktop\n\nAdd to `~/Library/Application Support/Claude/claude_desktop_config.json` (npx pulls the server automatically, nothing to install first):\n\n```json\n{\n "mcpServers": {\n "flusterduck": {\n "command": "npx",\n "args": ["-y", "@flusterduck/mcp-server"],\n "env": {\n "FLUSTERDUCK_MCP_KEY": "fd_mcp_xxxxxxxxxxxx",\n "FLUSTERDUCK_SITE_ID": "7f2c9d4a-4b5e-4c3a-9b1d-2e6a4f8c7d5b"\n }\n }\n }\n}\n```\n\nRestart Claude Desktop. Tools are available immediately.\n\n### Claude Code CLI\n\n```bash\nclaude mcp add flusterduck \\\n --env FLUSTERDUCK_MCP_KEY=fd_mcp_xxxxxxxxxxxx \\\n --env FLUSTERDUCK_SITE_ID=your-site-id \\\n -- npx -y @flusterduck/mcp-server\n```\n\nOr add directly to `~/.claude/settings.json`:\n\n```json\n{\n "mcpServers": {\n "flusterduck": {\n "command": "npx",\n "args": ["-y", "@flusterduck/mcp-server"],\n "env": {\n "FLUSTERDUCK_MCP_KEY": "fd_mcp_xxxxxxxxxxxx",\n "FLUSTERDUCK_SITE_ID": "7f2c9d4a-4b5e-4c3a-9b1d-2e6a4f8c7d5b"\n }\n }\n }\n}\n```\n\n### Cursor\n\n`~/.cursor/mcp.json` (global) or `.cursor/mcp.json` in the project root:\n\n```json\n{\n "mcpServers": {\n "flusterduck": {\n "command": "npx",\n "args": ["-y", "@flusterduck/mcp-server"],\n "env": {\n "FLUSTERDUCK_MCP_KEY": "fd_mcp_xxxxxxxxxxxx",\n "FLUSTERDUCK_SITE_ID": "7f2c9d4a-4b5e-4c3a-9b1d-2e6a4f8c7d5b"\n }\n }\n }\n}\n```\n\nReload the Cursor window after saving.\n\n### Windsurf\n\n`~/.codeium/windsurf/mcp_config.json`:\n\n```json\n{\n "mcpServers": {\n "flusterduck": {\n "command": "npx",\n "args": ["-y", "@flusterduck/mcp-server"],\n "env": {\n "FLUSTERDUCK_MCP_KEY": "fd_mcp_xxxxxxxxxxxx",\n "FLUSTERDUCK_SITE_ID": "7f2c9d4a-4b5e-4c3a-9b1d-2e6a4f8c7d5b"\n }\n }\n }\n}\n```\n\n### VS Code (GitHub Copilot)\n\n`.vscode/mcp.json` in the workspace:\n\n```json\n{\n "servers": {\n "flusterduck": {\n "type": "stdio",\n "command": "npx",\n "args": ["-y", "@flusterduck/mcp-server"],\n "env": {\n "FLUSTERDUCK_MCP_KEY": "fd_mcp_xxxxxxxxxxxx",\n "FLUSTERDUCK_SITE_ID": "7f2c9d4a-4b5e-4c3a-9b1d-2e6a4f8c7d5b"\n }\n }\n }\n}\n```\n\n### Remote server\n\nPoint your client at `https://mcp.flusterduck.com/mcp`. There is nothing to copy: the first connection opens a consent page, you sign in with your Flusterduck account, and access is granted through OAuth 2.1 with PKCE. Disconnecting from your MCP client revokes access immediately.\n\n## Keys\n\nThe hosted server never needs a key; sign-in handles it. MCP keys (`fd_mcp_`, created under Settings > API Keys) are only for the local stdio server.\n\n## MCP or CLI?\n\nBoth surfaces expose the same data; pick by where the agent runs. MCP is right for interactive assistants (Claude Desktop, Cursor, Claude Code sessions): persistent connection, tools, and the multi-step prompts below. The [CLI](./cli) is right for CI jobs and shell scripts: `npx flusterduck-cli issues --site <id> --json` for reads, `issue resolve|ignore|reopen|start` to manage issues, and `deploy notify` to record deploys. Every command takes `--json`, so agents can parse the output directly.\n\n**Read-only** (`mcp:read`): all query tools and prompts. Can\'t write anything. Start here.\n\n**Read + write** (`mcp:read` + `manage:write`): adds `update_issue`, `update_alert`, `add_annotation`, `create_alert_rule`, `update_alert_rule`, and `delete_alert_rule`. Needed for triage and annotation workflows.\n\n## Prompts\n\nThe prompts are the highest-value part. They\'re multi-step workflows built into the server. The AI calls several tools in sequence and synthesizes the result into a useful answer. Use prompts for the common cases; use raw tools when you need something specific.\n\n### post_deploy_check\n\nFinds your most recent deploy, compares confusion scores before and after, identifies pages where friction spiked, and returns PASS / WARN / FAIL. Writes an annotation automatically on FAIL.\n\nRun this after every deploy. Takes about 30 seconds.\n\n### triage_open_issues\n\nScans open issues by signal count, moves each to the right status (`triaged`, `in_progress`, or `ignored`), adds a triage note to each, and writes a summary annotation. Requires `manage:write`.\n\nMost useful first thing Monday morning before standup.\n\n### diagnose_page\n\nFive-step diagnosis for a specific page. Returns: current friction score, top signal sources by volume, worst-performing element, likely root cause, and one concrete fix recommendation.\n\n```\npage_path: "/settings/billing"\n```\n\n### investigate_session\n\nFull investigation of a single session: event timeline in order, dominant signal types, matching open issues, and a verdict on whether the session represents a recurring pattern or an outlier.\n\n```\nsession_id: "ses_xxxxxxxxxxxx"\n```\n\n### weekly_summary\n\nA weekly UX friction digest formatted for a PM or eng lead: score trends, newly opened issues, open alerts, revenue at risk, top three recommendations. Under 300 words.\n\nGood to run before Monday standup.\n\n## What a real investigation looks like\n\nYou ask: "Did the deploy yesterday break anything on checkout?"\n\nThe AI runs this automatically:\n\n1. `get_deploys`: finds yesterday\'s deploy and its timestamp\n2. `get_page` with `/checkout`: sees the confusion score jumped from 14 to 38 in the hour after\n3. `get_issues` filtered to `open`: two issues opened within 90 minutes of the deploy, a rage click spike on `#place-order` and elevated form abandonment on the payment step\n4. `get_elements` scoped to `/checkout`: `#place-order` has 52 rage clicks in 24 hours, baseline is 5/day\n5. `diagnose_page`: returns root cause. The button appears inactive during payment processing with no visual indication, causing repeated clicking.\n6. `add_annotation`: "Deploy 2026-06-09: /checkout confusion +171%. #place-order rage clicks 10x baseline. Root cause: missing loading state on payment submit."\n\nThe whole sequence runs in about 30 seconds and leaves a permanent timeline marker.\n\n## Read tools\n\nAll require `mcp:read` scope. Start with `get_site_context`. It gives you the full picture in one call and tells you where to dig next.\n\n**Documentation**: the full Flusterduck docs are bundled into the server, so your assistant can read them before acting on data.\n\n- `list_docs`: Lists every documentation page (slug, title, group). Start here to see what\'s available.\n- `search_docs`: Full-text search across all docs. Pass `query`; returns matching pages with excerpts.\n- `get_doc`: Returns a full documentation page by `slug` (e.g. `alerts`, `scoring`, `webhooks`, `react`, `mcp`). Read a feature\'s page before acting. For example, read `alerts` before creating a rule to understand threshold semantics.\n\n**Start here**\n\n- `get_site_context`: Full snapshot of scores, open issues, active alerts, recent deploys, and top recommendations. The right first call for any investigation.\n- `get_scores`: Every tracked page ranked by current confusion score.\n- `get_recommendations`: Prioritized fix list ranked by estimated confusion reduction.\n\n**Issues and alerts**\n\n- `get_issues`: All UX issues. Filter by status: `open`, `triaged`, `in_progress`, `verified`, `resolved`, `regressed`.\n- `get_issue`: Full detail on one issue, including evidence, session links, verification history, and deploy correlation.\n- `get_alerts`: Active and resolved alerts. Filter by `open`, `acknowledged`, or `resolved`.\n- `list_alert_rules`: All configured rules with thresholds, channels, and enabled state. Call this before creating or modifying rules.\n\n**Page deep-dives**\n\n- `get_page`: Score history, active issues, element friction, annotations, and confusion budget for one page. Pass `page: "/checkout"`.\n- `get_elements`: Element-level breakdown showing which buttons, forms, and links generate the most signals. Scope by `page` or pull site-wide.\n- `get_trends`: Confusion score over time. Pass `days` (1-90) and optionally `page`.\n- `compare_pages`: Side-by-side confusion score comparison. Pass `a` and `b` as page paths.\n- `diagnose_journey_friction`: High-friction navigation edges from recent sessions. Filter by `signal_type` or `min_friction_weight`.\n\n**Sessions and raw data**\n\n- `get_session_detail`: Full event timeline for one session in chronological order.\n- `get_heuristics`: The complete signal catalog with all 33 types, scoring weights, and thresholds.\n- `query_raw_rows`: SQL-style access to allowlisted tables (`events`, `signals`, `sessions`, `page_scores`, `score_history`, `ux_issues`, `alerts`, `deploys`).\n- `download_events_csv`: Raw event export as CSV.\n- `explore`: A deterministic, typed query engine over session data. No natural language, no LLM, built explicitly for agents to answer ad-hoc questions the rest of the surface doesn\'t cover directly. Pick a `window_days` (1-90, default 7), up to 12 AND-ed `filters` over `signal`, `page`, `source`, `confused`, `converted`, `event_type` (ops `is` / `is_not` / `contains`, contains only on `page` and `source`), and exactly one `output`: `{mode: "list"}` to pull matching sessions, or `{mode: "measure", metric, group_by?}` to compute `count`, `avg_pageviews`, `conversion_rate`, `avg_dwell_ms`, or `bounce_rate` as a scalar or, with `group_by` (`page`, `source`, `day`, `signal`, `cohort`), a series. See "Explore via MCP" below for a list and a measure example.\n\n**Deploy correlation**\n\n- `get_deploys`: All deploys Flusterduck knows about, with `confusion_before` and `confusion_after` populated for deploys older than 5 minutes.\n- `get_revenue_impact`: Revenue impact estimates for active friction. Only populated when conversion tracking is wired.\n- `get_flows`: Page-to-page navigation edges from recent sessions.\n\n**Conversion impact**\n\n- `get_conversion_insights`: The confused-vs-calm conversion analysis: how much less confused sessions convert than calm ones, broken down by page and traffic source, plus ranked narratable insights. Pass `days` (1-90, default 7). Needs a conversion event wired; see [Conversion trigger](./conversion-trigger).\n\n**Org-level** (requires org-scoped key)\n\n- `get_audit_log`: Organization audit log.\n- `get_degradation`: Active and recent backend degradation events. Also available to site-scoped keys, since degradation is operational health rather than tenant data.\n- `get_webhook_deliveries`: Outbound webhook delivery history and failure details.\n\n## Explore via MCP\n\n`explore` is the odd one out on purpose: everything else in this list is a fixed shape (scores, issues, trends), but `explore` is a small closed query language over session data: a window, up to 12 AND-ed filters, and one output mode. Still fully deterministic and validated against the same allowlists the dashboard uses; there\'s no free-text query and no model in the loop.\n\n**List**: sessions that rage-clicked on `/pricing` in the last 7 days:\n\n```\nwindow_days: 7\nfilters: [\n { "field": "page", "op": "is", "value": "/pricing" },\n { "field": "signal", "op": "is", "value": "rage_click" }\n]\noutput: { "mode": "list", "limit": 20 }\n```\n\nReturns up to 20 matching sessions, most recent first, each with its page list, signal counts, source, and confused/converted flags. Use this to cite concrete example sessions as evidence in a diagnosis.\n\n**Measure**: does confusion actually cost this site conversions?\n\n```\nwindow_days: 30\noutput: { "mode": "measure", "metric": "conversion_rate", "group_by": "cohort" }\n```\n\nReturns conversion rate as a two-point series: the `confused` cohort (sessions with at least one friction signal) versus the `calm` cohort. Swap `group_by` for `page`, `source`, `day`, or `signal` to see the same metric broken down a different way, or drop `group_by` entirely for a single scalar across all matching sessions.\n\n## Write tools\n\nAll require `manage:write` scope.\n\n**`update_issue`**: Change status, add a triage note, or assign an issue.\n\n```\nissue_id: "iss_3a7f2c9d4e1b"\nstatus: "triaged"\nnote: "Confirmed on Safari iOS 17. Disabled-state styling on #place-order doesn\'t communicate that payment is processing."\nassigned_to: "eng-lead"\n```\n\nStatus options: `open`, `triaged`, `in_progress`, `verified`, `resolved`, `ignored`.\n\n**`update_alert`**: Acknowledge, mark investigating, or resolve an alert.\n\n```\nalert_id: "alt_9b5e1f4c2d8a"\nstatus: "resolved"\nresolved_reason: "Deploy 2026-06-09 added a spinner and disabled state to the payment submit button."\n```\n\n**`add_annotation`**: Write a timeline marker visible to the whole team.\n\n```\nmessage: "Redesigned billing flow launched. Monitoring confusion score on /settings/billing."\n```\n\n**`create_alert_rule`**: Create a new alert rule.\n\n```\nname: "Checkout rage click spike"\ntrigger_type: "spike"\nthreshold: 25\ncooldown_minutes: 60\nchannels: ["email", "slack"]\npage_pattern: "/checkout*"\n```\n\n**`update_alert_rule`**: Update an existing rule. Use `enabled: false` to silence it temporarily rather than deleting.\n\n**`delete_alert_rule`**: Permanently remove a rule. Can\'t be undone.\n\n## Questions that work well\n\n- What\'s broken on checkout right now?\n- Did the last deploy make things worse?\n- Which page has the most dead clicks this week?\n- Triage the open issues and tell me what to fix first.\n- Write a friction summary for the PM standup.\n- Which sessions show rage clicks on the upgrade button?\n- How does this week\'s confusion score compare to last week?\n- Create a spike alert for the pricing page and notify Slack.\n- What\'s the revenue impact of the current open issues?\n- Which elements on `/onboarding` are generating the most friction?\n'
|
|
562
|
+
"content": '# MCP Integration\n\nSet this up once and you stop opening the dashboard to check on friction data. Ask your AI assistant:\n\n> "What\'s broken on checkout right now?"\n\nIt calls `get_site_context`, pulls your live scores and open issues, and tells you. Post-deploy checks, issue triage, weekly summaries. All without touching a UI.\n\n## Fastest install\n\nThe hosted server needs no keys and no install. Add the URL and sign in with your Flusterduck account when your client prompts you:\n\n```bash\nclaude mcp add --transport http flusterduck https://mcp.flusterduck.com/mcp\n```\n\nPrefer running the server locally (stdio)? `npx` fetches it on first run. Grab an MCP key and your site ID from the dashboard (Settings \u2192 API keys), then:\n\n```bash\nclaude mcp add flusterduck \\\n --env FLUSTERDUCK_MCP_KEY=fd_mcp_xxxxxxxxxxxx \\\n --env FLUSTERDUCK_SITE_ID=your-site-id \\\n -- npx -y @flusterduck/mcp-server\n```\n\n## Setup\n\n### Claude Desktop\n\nAdd to `~/Library/Application Support/Claude/claude_desktop_config.json` (npx pulls the server automatically, nothing to install first):\n\n```json\n{\n "mcpServers": {\n "flusterduck": {\n "command": "npx",\n "args": ["-y", "@flusterduck/mcp-server"],\n "env": {\n "FLUSTERDUCK_MCP_KEY": "fd_mcp_xxxxxxxxxxxx",\n "FLUSTERDUCK_SITE_ID": "7f2c9d4a-4b5e-4c3a-9b1d-2e6a4f8c7d5b"\n }\n }\n }\n}\n```\n\nRestart Claude Desktop. Tools are available immediately.\n\n### Claude Code CLI\n\n```bash\nclaude mcp add flusterduck \\\n --env FLUSTERDUCK_MCP_KEY=fd_mcp_xxxxxxxxxxxx \\\n --env FLUSTERDUCK_SITE_ID=your-site-id \\\n -- npx -y @flusterduck/mcp-server\n```\n\nOr add directly to `~/.claude/settings.json`:\n\n```json\n{\n "mcpServers": {\n "flusterduck": {\n "command": "npx",\n "args": ["-y", "@flusterduck/mcp-server"],\n "env": {\n "FLUSTERDUCK_MCP_KEY": "fd_mcp_xxxxxxxxxxxx",\n "FLUSTERDUCK_SITE_ID": "7f2c9d4a-4b5e-4c3a-9b1d-2e6a4f8c7d5b"\n }\n }\n }\n}\n```\n\n### Cursor\n\n`~/.cursor/mcp.json` (global) or `.cursor/mcp.json` in the project root:\n\n```json\n{\n "mcpServers": {\n "flusterduck": {\n "command": "npx",\n "args": ["-y", "@flusterduck/mcp-server"],\n "env": {\n "FLUSTERDUCK_MCP_KEY": "fd_mcp_xxxxxxxxxxxx",\n "FLUSTERDUCK_SITE_ID": "7f2c9d4a-4b5e-4c3a-9b1d-2e6a4f8c7d5b"\n }\n }\n }\n}\n```\n\nReload the Cursor window after saving.\n\n### Windsurf\n\n`~/.codeium/windsurf/mcp_config.json`:\n\n```json\n{\n "mcpServers": {\n "flusterduck": {\n "command": "npx",\n "args": ["-y", "@flusterduck/mcp-server"],\n "env": {\n "FLUSTERDUCK_MCP_KEY": "fd_mcp_xxxxxxxxxxxx",\n "FLUSTERDUCK_SITE_ID": "7f2c9d4a-4b5e-4c3a-9b1d-2e6a4f8c7d5b"\n }\n }\n }\n}\n```\n\n### VS Code (GitHub Copilot)\n\n`.vscode/mcp.json` in the workspace:\n\n```json\n{\n "servers": {\n "flusterduck": {\n "type": "stdio",\n "command": "npx",\n "args": ["-y", "@flusterduck/mcp-server"],\n "env": {\n "FLUSTERDUCK_MCP_KEY": "fd_mcp_xxxxxxxxxxxx",\n "FLUSTERDUCK_SITE_ID": "7f2c9d4a-4b5e-4c3a-9b1d-2e6a4f8c7d5b"\n }\n }\n }\n}\n```\n\n### Remote server\n\nPoint your client at `https://mcp.flusterduck.com/mcp`. There is nothing to copy: the first connection opens a consent page, you sign in with your Flusterduck account, and access is granted through OAuth 2.1 with PKCE. Disconnecting from your MCP client revokes access immediately.\n\n## Keys\n\nThe hosted server never needs a key; sign-in handles it. MCP keys (`fd_mcp_`, created under Settings > API Keys) are only for the local stdio server.\n\n## MCP or CLI?\n\nBoth surfaces expose the same data; pick by where the agent runs. MCP is right for interactive assistants (Claude Desktop, Cursor, Claude Code sessions): persistent connection, tools, and the multi-step prompts below. The [CLI](./cli) is right for CI jobs and shell scripts: `npx flusterduck-cli issues --site <id> --json` for reads, `issue resolve|ignore|reopen|start` to manage issues, and `deploy notify` to record deploys. Every command takes `--json`, so agents can parse the output directly.\n\n**Read-only** (`mcp:read`): all query tools and prompts, including `whoami` (introspect the key\'s scope and permissions). Can\'t write anything. Start here.\n\n**Read + write** (`mcp:read` + `manage:write`): adds `update_issue`, `rate_issue`, `update_alert`, `add_annotation`, `create_alert_rule`, `update_alert_rule`, `delete_alert_rule`, and `send_feedback`. Needed for triage and annotation workflows.\n\n## Prompts\n\nThe prompts are the highest-value part. They\'re multi-step workflows built into the server. The AI calls several tools in sequence and synthesizes the result into a useful answer. Use prompts for the common cases; use raw tools when you need something specific.\n\n### post_deploy_check\n\nFinds your most recent deploy, compares confusion scores before and after, identifies pages where friction spiked, and returns PASS / WARN / FAIL. Writes an annotation automatically on FAIL.\n\nRun this after every deploy. Takes about 30 seconds.\n\n### triage_open_issues\n\nScans open issues by signal count, moves each to the right status (`triaged`, `in_progress`, or `ignored`), adds a triage note to each, and writes a summary annotation. Requires `manage:write`.\n\nMost useful first thing Monday morning before standup.\n\n### diagnose_page\n\nFive-step diagnosis for a specific page. Returns: current friction score, top signal sources by volume, worst-performing element, likely root cause, and one concrete fix recommendation.\n\n```\npage_path: "/settings/billing"\n```\n\n### investigate_session\n\nFull investigation of a single session: event timeline in order, dominant signal types, matching open issues, and a verdict on whether the session represents a recurring pattern or an outlier.\n\n```\nsession_id: "ses_xxxxxxxxxxxx"\n```\n\n### weekly_summary\n\nA weekly UX friction digest formatted for a PM or eng lead: score trends, newly opened issues, open alerts, revenue at risk, top three recommendations. Under 300 words.\n\nGood to run before Monday standup.\n\n## What a real investigation looks like\n\nYou ask: "Did the deploy yesterday break anything on checkout?"\n\nThe AI runs this automatically:\n\n1. `get_deploys`: finds yesterday\'s deploy and its timestamp\n2. `get_page` with `/checkout`: sees the confusion score jumped from 14 to 38 in the hour after\n3. `get_issues` filtered to `open`: two issues opened within 90 minutes of the deploy, a rage click spike on `#place-order` and elevated form abandonment on the payment step\n4. `get_elements` scoped to `/checkout`: `#place-order` has 52 rage clicks in 24 hours, baseline is 5/day\n5. `diagnose_page`: returns root cause. The button appears inactive during payment processing with no visual indication, causing repeated clicking.\n6. `add_annotation`: "Deploy 2026-06-09: /checkout confusion +171%. #place-order rage clicks 10x baseline. Root cause: missing loading state on payment submit."\n\nThe whole sequence runs in about 30 seconds and leaves a permanent timeline marker.\n\n## Read tools\n\nAll require `mcp:read` scope. Start with `get_site_context`. It gives you the full picture in one call and tells you where to dig next.\n\n**Documentation**: the full Flusterduck docs are bundled into the server, so your assistant can read them before acting on data.\n\n- `list_docs`: Lists every documentation page (slug, title, group). Start here to see what\'s available.\n- `search_docs`: Full-text search across all docs. Pass `query`; returns matching pages with excerpts.\n- `get_doc`: Returns a full documentation page by `slug` (e.g. `alerts`, `scoring`, `webhooks`, `react`, `mcp`). Read a feature\'s page before acting. For example, read `alerts` before creating a rule to understand threshold semantics.\n\n**Start here**\n\n- `get_site_context`: Full snapshot of scores, open issues, active alerts, recent deploys, and top recommendations. The right first call for any investigation.\n- `get_scores`: Every tracked page ranked by current confusion score.\n- `get_recommendations`: Prioritized fix list ranked by estimated confusion reduction.\n\n**Issues and alerts**\n\n- `get_issues`: All UX issues. Filter by status: `open`, `triaged`, `in_progress`, `verified`, `resolved`, `regressed`.\n- `get_issue`: Full detail on one issue, including evidence, session links, verification history, and deploy correlation.\n- `get_alerts`: Active and resolved alerts. Filter by `open`, `acknowledged`, or `resolved`.\n- `list_alert_rules`: All configured rules with thresholds, channels, and enabled state. Call this before creating or modifying rules.\n\n**Page deep-dives**\n\n- `get_page`: Score history, active issues, element friction, annotations, and confusion budget for one page. Pass `page: "/checkout"`.\n- `get_elements`: Element-level breakdown showing which buttons, forms, and links generate the most signals. Scope by `page` or pull site-wide.\n- `get_trends`: Confusion score over time. Pass `days` (1-90) and optionally `page`.\n- `compare_pages`: Side-by-side confusion score comparison. Pass `a` and `b` as page paths.\n- `diagnose_journey_friction`: High-friction navigation edges from recent sessions. Filter by `signal_type` or `min_friction_weight`.\n\n**Sessions and raw data**\n\n- `get_session_detail`: Full event timeline for one session in chronological order.\n- `get_heuristics`: The complete signal catalog with all 33 types, scoring weights, and thresholds.\n- `query_raw_rows`: SQL-style access to allowlisted tables (`events`, `signals`, `sessions`, `page_scores`, `score_history`, `ux_issues`, `alerts`, `deploys`).\n- `download_events_csv`: Raw event export as CSV.\n- `explore`: A deterministic, typed query engine over session data. No natural language, no LLM, built explicitly for agents to answer ad-hoc questions the rest of the surface doesn\'t cover directly. Pick a `window_days` (1-90, default 7), up to 12 AND-ed `filters` over `signal`, `page`, `source`, `confused`, `converted`, `event_type` (ops `is` / `is_not` / `contains`, contains only on `page` and `source`), and exactly one `output`: `{mode: "list"}` to pull matching sessions, or `{mode: "measure", metric, group_by?}` to compute `count`, `avg_pageviews`, `conversion_rate`, `avg_dwell_ms`, or `bounce_rate` as a scalar or, with `group_by` (`page`, `source`, `day`, `signal`, `cohort`), a series. See "Explore via MCP" below for a list and a measure example.\n\n**Deploy correlation**\n\n- `get_deploys`: All deploys Flusterduck knows about, with `confusion_before` and `confusion_after` populated for deploys older than 5 minutes.\n- `get_revenue_impact`: Revenue impact estimates for active friction. Only populated when conversion tracking is wired.\n- `get_flows`: Page-to-page navigation edges from recent sessions.\n\n**Conversion impact**\n\n- `get_conversion_insights`: The confused-vs-calm conversion analysis: how much less confused sessions convert than calm ones, broken down by page and traffic source, plus ranked narratable insights. Pass `days` (1-90, default 7). Needs a conversion event wired; see [Conversion trigger](./conversion-trigger).\n\n**Org-level** (requires org-scoped key)\n\n- `get_audit_log`: Organization audit log.\n- `get_degradation`: Active and recent backend degradation events. Also available to site-scoped keys, since degradation is operational health rather than tenant data.\n- `get_webhook_deliveries`: Outbound webhook delivery history and failure details.\n\n## Explore via MCP\n\n`explore` is the odd one out on purpose: everything else in this list is a fixed shape (scores, issues, trends), but `explore` is a small closed query language over session data: a window, up to 12 AND-ed filters, and one output mode. Still fully deterministic and validated against the same allowlists the dashboard uses; there\'s no free-text query and no model in the loop.\n\n**List**: sessions that rage-clicked on `/pricing` in the last 7 days:\n\n```\nwindow_days: 7\nfilters: [\n { "field": "page", "op": "is", "value": "/pricing" },\n { "field": "signal", "op": "is", "value": "rage_click" }\n]\noutput: { "mode": "list", "limit": 20 }\n```\n\nReturns up to 20 matching sessions, most recent first, each with its page list, signal counts, source, and confused/converted flags. Use this to cite concrete example sessions as evidence in a diagnosis.\n\n**Measure**: does confusion actually cost this site conversions?\n\n```\nwindow_days: 30\noutput: { "mode": "measure", "metric": "conversion_rate", "group_by": "cohort" }\n```\n\nReturns conversion rate as a two-point series: the `confused` cohort (sessions with at least one friction signal) versus the `calm` cohort. Swap `group_by` for `page`, `source`, `day`, or `signal` to see the same metric broken down a different way, or drop `group_by` entirely for a single scalar across all matching sessions.\n\n## Write tools\n\nAll require `manage:write` scope.\n\n**`update_issue`**: Change status, add a triage note, or assign an issue.\n\n```\nissue_id: "iss_3a7f2c9d4e1b"\nstatus: "triaged"\nnote: "Confirmed on Safari iOS 17. Disabled-state styling on #place-order doesn\'t communicate that payment is processing."\nassigned_to: "eng-lead"\n```\n\nStatus options: `open`, `triaged`, `in_progress`, `verified`, `resolved`, `ignored`.\n\n**`rate_issue`**: Rate a detected issue\'s accuracy. `confirmed` means it described a real problem, `rejected` means it was a false positive or noise. Ratings feed the detection accuracy metric without changing the issue\'s status. Pass `null` to clear a previous rating.\n\n```\nissue_id: "iss_3a7f2c9d4e1b"\nverdict: "confirmed"\n```\n\n**`send_feedback`**: Send product feedback about Flusterduck itself to the Flusterduck team. Use `suggestion` for a missing capability, confusing tool output, or data you wished you had; use `bug` when a tool or surface misbehaved. This is how you (or your AI assistant, mid-workflow) tell us what to build next.\n\n```\nkind: "suggestion"\nmessage: "get_issue cites session ids but there is no way to fetch two sessions side by side. A compare_sessions tool would save a round trip."\n```\n\n**`update_alert`**: Acknowledge, mark investigating, or resolve an alert.\n\n```\nalert_id: "alt_9b5e1f4c2d8a"\nstatus: "resolved"\nresolved_reason: "Deploy 2026-06-09 added a spinner and disabled state to the payment submit button."\n```\n\n**`add_annotation`**: Write a timeline marker visible to the whole team.\n\n```\nmessage: "Redesigned billing flow launched. Monitoring confusion score on /settings/billing."\n```\n\n**`create_alert_rule`**: Create a new alert rule.\n\n```\nname: "Checkout rage click spike"\ntrigger_type: "spike"\nthreshold: 25\ncooldown_minutes: 60\nchannels: ["email", "slack"]\npage_pattern: "/checkout*"\n```\n\n**`update_alert_rule`**: Update an existing rule. Use `enabled: false` to silence it temporarily rather than deleting.\n\n**`delete_alert_rule`**: Permanently remove a rule. Can\'t be undone.\n\n## Questions that work well\n\n- What\'s broken on checkout right now?\n- Did the last deploy make things worse?\n- Which page has the most dead clicks this week?\n- Triage the open issues and tell me what to fix first.\n- Write a friction summary for the PM standup.\n- Which sessions show rage clicks on the upgrade button?\n- How does this week\'s confusion score compare to last week?\n- Create a spike alert for the pricing page and notify Slack.\n- What\'s the revenue impact of the current open issues?\n- Which elements on `/onboarding` are generating the most friction?\n'
|
|
546
563
|
},
|
|
547
564
|
{
|
|
548
565
|
"slug": "api",
|
|
@@ -823,14 +840,21 @@ function createFlusterduckMCPServer(config) {
|
|
|
823
840
|
group_by: exploreGroupBy.optional()
|
|
824
841
|
})
|
|
825
842
|
]);
|
|
826
|
-
server.tool("
|
|
843
|
+
server.tool("whoami", "Introspect this connection: key type, the org and site it is scoped to (with names), and its granted scopes (mcp:read for reads, manage:write for write tools). Call this once at the start of a session to learn your permission envelope instead of discovering it by failed calls.", {}, readOnly, async () => {
|
|
844
|
+
try {
|
|
845
|
+
return toolResult(await api.whoami());
|
|
846
|
+
} catch (error) {
|
|
847
|
+
return toolError(error);
|
|
848
|
+
}
|
|
849
|
+
});
|
|
850
|
+
server.tool("get_site_context", "Get the full Flusterduck MCP snapshot for the configured site: scores, open issues, active alerts, deploys, and recommendations. Start here for any investigation. Score fields: score is the baseline-normalized confusion score (0-100, higher = more confusion, dampened for tiny samples); raw_score is the pre-normalization weighted signal total; baseline 0 with deviation 0 means the page has no learned baseline yet.", {}, readOnly, async () => {
|
|
827
851
|
try {
|
|
828
852
|
return toolResult(await api.getContext());
|
|
829
853
|
} catch (error) {
|
|
830
854
|
return toolError(error);
|
|
831
855
|
}
|
|
832
856
|
});
|
|
833
|
-
server.tool("get_scores", "Get current confusion scores for every tracked page, sorted by friction intensity.", {}, readOnly, async () => {
|
|
857
|
+
server.tool("get_scores", "Get current confusion scores for every tracked page, sorted by friction intensity. score is baseline-normalized (0-100, higher = more confusion, dampened for tiny samples); raw_score is the pre-normalization weighted signal total; baseline 0 with deviation 0 means the page has no learned baseline yet.", {}, readOnly, async () => {
|
|
834
858
|
try {
|
|
835
859
|
return toolResult(await api.getScores());
|
|
836
860
|
} catch (error) {
|
|
@@ -1072,6 +1096,38 @@ function createFlusterduckMCPServer(config) {
|
|
|
1072
1096
|
}
|
|
1073
1097
|
}
|
|
1074
1098
|
);
|
|
1099
|
+
server.tool(
|
|
1100
|
+
"rate_issue",
|
|
1101
|
+
"Rate a detected issue's accuracy: confirmed means it described a real problem, rejected means it was a false positive or noise. Feeds the detection accuracy metric without changing the issue's status. Pass verdict null to clear a previous rating. Requires manage:write scope on the API key.",
|
|
1102
|
+
{
|
|
1103
|
+
issue_id: z.string().uuid(),
|
|
1104
|
+
verdict: z.enum(["confirmed", "rejected"]).nullable()
|
|
1105
|
+
},
|
|
1106
|
+
mutateHint,
|
|
1107
|
+
async ({ issue_id, verdict }) => {
|
|
1108
|
+
try {
|
|
1109
|
+
return toolResult(await api.rateIssue(issue_id, verdict));
|
|
1110
|
+
} catch (error) {
|
|
1111
|
+
return toolError(error);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
);
|
|
1115
|
+
server.tool(
|
|
1116
|
+
"send_feedback",
|
|
1117
|
+
'Send product feedback about Flusterduck itself to the Flusterduck team. Use kind "suggestion" for a missing capability, confusing tool output, or data you wished you had while working; use kind "bug" when a Flusterduck tool or surface misbehaved. Say which tool you were using, what you expected, and what happened. Requires manage:write scope on the API key and orgId in local MCP config.',
|
|
1118
|
+
{
|
|
1119
|
+
kind: z.enum(["suggestion", "bug"]),
|
|
1120
|
+
message: z.string().min(1).max(4e3)
|
|
1121
|
+
},
|
|
1122
|
+
writeHint,
|
|
1123
|
+
async ({ kind, message }) => {
|
|
1124
|
+
try {
|
|
1125
|
+
return toolResult(await api.sendFeedback(kind, message));
|
|
1126
|
+
} catch (error) {
|
|
1127
|
+
return toolError(error);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
);
|
|
1075
1131
|
server.tool(
|
|
1076
1132
|
"update_alert",
|
|
1077
1133
|
"Acknowledge, mark as investigating, or resolve an alert. Resolving stops all channel delivery including PagerDuty. Optionally include a resolved_reason when closing. Requires manage:write scope on the API key.",
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -86,6 +86,7 @@ declare class FlusterduckAPI {
|
|
|
86
86
|
getElementHeatmap(page: string, selector: string): Promise<unknown>;
|
|
87
87
|
getPageHeatmap(page: string): Promise<unknown>;
|
|
88
88
|
getGuideStats(): Promise<unknown>;
|
|
89
|
+
whoami(): Promise<unknown>;
|
|
89
90
|
getAlertDetail(alertId: string): Promise<unknown>;
|
|
90
91
|
getDeployDetail(deployId: string): Promise<unknown>;
|
|
91
92
|
getAlertRules(): Promise<unknown>;
|
|
@@ -103,6 +104,8 @@ declare class FlusterduckAPI {
|
|
|
103
104
|
note?: string | null;
|
|
104
105
|
assigned_to?: string | null;
|
|
105
106
|
}): Promise<unknown>;
|
|
107
|
+
rateIssue(issueId: string, verdict: 'confirmed' | 'rejected' | null): Promise<unknown>;
|
|
108
|
+
sendFeedback(kind: 'suggestion' | 'bug', message: string): Promise<unknown>;
|
|
106
109
|
updateAlert(alertId: string, status: 'acknowledged' | 'investigating' | 'resolved', resolvedReason?: string): Promise<unknown>;
|
|
107
110
|
addAnnotation(message: string): Promise<unknown>;
|
|
108
111
|
createAlertRule(rule: {
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flusterduck/mcp-server",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "MCP server for UX friction data. Connect Claude, Cursor, Windsurf, Copilot, Cline to rage click and dead click analytics. Model Context Protocol.",
|
|
5
5
|
"mcpName": "com.flusterduck/mcp-server",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.md",
|