Agents
The vision §3 names three primary personas: the end user submitting feedback, the host developer installing the widget, and the AI agent. The agent is not a UI shortcut. It's a buyer, an installer, and a consumer of feedback in its own right.
What this changes architecturally
Every capability in the dashboard is also an MCP tool. Same auth model, same scopes, same atomic operations. The dashboard is one of many clients.
| Dashboard surface | MCP equivalent |
|---|---|
| Sign up | OAuth Dynamic Client Registration |
| Create team / project | create_team, create_project |
| Inbox list | list_feedback |
| Detail page | get_feedback |
| Status workflow | resolve_feedback |
| Comment thread | list_comments |
| Integrations setup | suggest_integrations → connect_integration → test_integration |
| Project context | set_project_context / get_project_context |
| Project settings | rotate_api_key |
See MCP for the full registry + schemas.
How a coding agent installs Earshot
> add user feedback to my app
Pulls the Agent Skill (skills/earshot/SKILL.md in the repo). The skill walks the agent through:
- Detect framework (Next, Remix, SvelteKit, Vue, Nuxt, vanilla).
- Run OAuth DCR against
https://earshot.dev/oauth/.well-known/oauth-authorization-server. - Open the consent page so the user picks a team + the MCP tools the client may use.
- Call
create_project, store thepk_*API key in.env.local. - Drop the snippet into the framework-appropriate location.
- Wire
Earshot.identify()into the auth callback. - Offer to wire integrations via the
earshot-integrationsskill. - Submit a test recording and verify it lands.
Wall-clock target: under 5 minutes.
How a triage agent reads + acts
const fb = await mcp.call('get_feedback', {
id: 'fb_abc123',
include: ['console', 'network', 'identity', 'federation'],
});
// fb.title, fb.summary, fb.voice_transcript, fb.context, fb.federation[*].replayUrl …
The title + summary are LLM-derived at ingest, grounded in the project brief + captured browser context. Agents read those as the structured starting point and drill into the raw voice_transcript / context only when they need more.
When the fix lands:
await mcp.call('resolve_feedback', {
id: 'fb_abc123',
resolution_note: 'Fixed in PR #4421 — race condition in onAuth handler.',
});
This stamps resolved_at, mirrors a comment to the linked Linear issue, and emails the submitter (if their identity is captured + Resend is configured).
How a build-time agent provisions Earshot for someone else
The Stripe Projects catalog + MCP registry play. An agent building a new SaaS for a non-developer customer can register an OAuth client, run consent against a fresh user account, create the team/project, embed the snippet, and never expose Earshot to the end user. Deferred-identity claim makes this work even without a real user account at install time.
Three skills available
| Skill | Triggers on |
|---|---|
earshot |
"add user feedback", "bug reports", "voice feedback widget", "Usersnap replacement" |
earshot-context |
"compile earshot context", "push earshot context", "earshot ground", "refresh earshot brief" |
earshot-integrations |
"set up earshot integrations", "connect posthog to earshot", "review earshot integrations" |
All three are plain Markdown — copy into your agent's skills directory or install via the plugin marketplace.
Per-host install
| Host | Setup |
|---|---|
| Claude Code | claude plugin marketplace add earshot/earshot, then > add user feedback to my app |
| Cursor | Paste .cursor/mcp.json snippet + drop .cursor/rules/earshot.mdc — full walkthrough at Cursor |
| Codex / generic MCP host | Add the MCP server with Authorization: Bearer pk_* and load the skill manually — see Quickstart |
Agent-readable docs
/llms.txtat the docs root indexes every page with title + description + URL.- Every page has a raw
.mdmirror — append/raw.mdto any docs URL. - MCP tool descriptions are LLM-optimized: snake_case names, atomic operations, predictable schemas, descriptive parameter docs,
next_callhelpers on tools that naturally chain.