loupe-mcp
The loupe-mcp server lets you manage product feedback comments as a structured task backlog. It exposes three core capabilities:
list_comments— Retrieve all product-feedback comments for a project, optionally filtering by page URL path (e.g./checkout) and/or status (open,in_progress,done).get_comment— Fetch full context for a specific comment by ID, including the PM's original request, the page it was left on, the target element's HTML, and its computed styles — everything needed to implement the change.update_status— Update a comment's status toopen,in_progress, ordoneto close the feedback loop with the PM (e.g. markin_progresswhen starting work,donewhen shipped).
Under the hood, it stores comment data in a Postgres-compatible database, screenshots in object storage, and uses HMAC-based authentication for users alongside an admin key for privileged access.
Provides a Composer package that embeds the Loupe widget into Laravel apps, stores comments in your database, and exposes the backlog to Claude over MCP with your authorization rules.
Loupe
Pin feedback to the live UI. Hand it to Claude.
Loupe lets product managers inspect any element on a running product, pin a comment to it, and capture a screenshot — then hand that feedback straight to Claude Code as an actionable, fully-contextualized backlog. Comments persist and re-anchor across redeploys.
📖 Read the full documentation →
This is a monorepo (npm workspaces). Every piece runs locally with no external
services — the database is embedded Postgres (PGlite), so npm install && npm run build && npm run seed && npm start is the whole setup.
Packages
packages/
shared/ canonical types + normalizeUrl() (built to dist, consumed by all)
sdk/ embeddable browser SDK — inspect, comment (element / region / free note), capture, re-anchor; dockable control panel
demo/ a fake product ("Acme Analytics") to try it on
server/ comment API — node:http, Postgres, object storage, HMAC auth, static hosting
dashboard/ Kanban triage board (reads the API)
mcp/ MCP server — exposes comments to Claude Code
extension/ MV3 browser extension — inspect/comment on ANY site, pixel-perfect capture
laravel/ Loupe for Laravel — composer package: widget + your DB + gating + dashboard + MCPLoupe for Laravel
Prefer to run the whole loop inside your own app? loupekit/laravel
is a Composer package that embeds the widget, stores comments in your database, gates
access with your authorization rules, serves the dashboard on your routes, and
exposes the backlog to Claude over MCP — no separate Node backend. See the
full guide.
composer require loupekit/laravel
php artisan loupe:install && php artisan migrate
# add @loupeWidget to your layout, then open /loupe/dashboardRelated MCP server: Browser Feedback MCP
Run it
npm install
npm run build # shared → sdk → dashboard → extension
npm run seed # creates the demo project; prints its admin key + demo HMAC
npm start # one process on http://localhost:8787 serves API + dashboard + demo + SDKThen open:
Demo product — http://localhost:8787/demo/ (leave feedback; persists to the API)
Triage board — http://localhost:8787/dashboard/?key=<admin key from
npm run seed>
Point Claude Code at the comments:
{
"mcpServers": {
"loupe": {
"command": "node",
"args": ["/absolute/path/to/loupe/packages/mcp/index.ts"],
"env": {
"LOUPE_API": "http://localhost:8787",
"LOUPE_PROJECT_KEY": "pk_demo_acme",
"LOUPE_ADMIN_KEY": "<admin key from npm run seed>"
}
}
}
}Then: "list the open Loupe comments and work through them." Claude calls
list_comments → get_comment (request + element HTML + computed styles + the
screenshot as an image + any screen-recording URL) → rewrites the UI →
propose_change (its modified HTML/CSS, which the dashboard renders as code + a live
before/after preview for the dev team) → update_status.
Architecture notes
Database — server/db.ts is a one-function query() seam. With DATABASE_URL set
it uses node-postgres against real/hosted Postgres; otherwise embedded PGlite on disk.
Same SQL, same $1 params.
Auth — every project has a secret. Writes require X-Loupe-User +
X-Loupe-Hmac = HMAC-SHA256(userId, secret) (the host app's server computes this and
injects it — the demo's value is precomputed by npm run seed). The dashboard and MCP
server authenticate as admin with X-Loupe-Admin = secret. Screenshot blobs are served
by unguessable id (prod: signed URLs).
Object storage — server/blobs.ts is the seam (local disk now, S3 later). The SDK
uploads a screenshot to POST /v1/blobs and stores only the returned URL on the
comment, so lists/reads stay small.
URL normalization — normalizeUrl() in @loupekit/shared strips utm_*, click ids,
and Loupe's dev params, so a comment on /checkout?utm_source=x and one on /checkout
don't fragment. Applied server-side on write and query.
Browser extension
The extension reuses the exact SDK core; its only difference is the screenshot source —
chrome.tabs.captureVisibleTab (real pixels), cropped to the element with redaction,
wired via the SDK's captureScreenshot override. Load it manually:
npm run build:extension # builds packages/extension/content.jschrome://extensions→ enable Developer mode → Load unpacked → selectpackages/extension.Click the Loupe icon → set project key (
pk_demo_acme), user, API base (http://localhost:8787), and (optionally) the demo HMAC → Start Loupe on this tab.
Note: the extension is validated by build + manifest/bundle checks; full in-browser E2E wasn't automated in this repo's headless setup.
Roadmap
Client SDK ✓ — inspect, comment, capture, re-anchor across redeploys.
Backend API ✓ — Postgres, HMAC auth + per-project secrets, object storage, static hosting.
MCP server ✓ — comments as a Claude Code backlog.
Dashboard ✓ — Kanban triage.
Hardening ✓ — monorepo, Postgres, enforced auth, blob storage, URL normalization.
Browser extension ✓ — pixel-perfect capture on any site.
Next: real cloud object storage (S3/R2) + signed URLs, project/team management UI, Postgres migrations tooling, and packaging the SDK/MCP to npm + the extension to the Chrome Web Store.
Author
Loupe is created and maintained by Mohamed Ashraf Elsaed.
💼 LinkedIn: mohamedashrafelsaed
🐙 GitHub: @mohamed-ashraf-elsaed
✉️ Email: m.ashraf.saed@gmail.com
If Loupe is useful to you, a ⭐ on the repo and a connection on LinkedIn are always appreciated. For consulting or collaboration, reach out via any of the links above.
License
MIT © Mohamed Ashraf Elsaed
Available Tools
3 toolsget_commentA
Get the full context for one comment: the request, the page, the target element's HTML, and its computed styles — everything needed to make the change.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The comment id from list_comments. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided; description indicates a read operation returning context. Lacks explicit mention of safety or side effects, but for a read tool this is acceptable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence (20 words) that is front-loaded with the primary action and includes explanatory details without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Simple tool with one param, no output schema. Description sufficiently explains what the return value contains, making it complete for an agent to understand usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 100% coverage with description for 'id'. Tool description adds that id comes from list_comments, providing useful context beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Get the full context for one comment' and lists specific components (request, page, target element HTML, computed styles). Distinct from sibling tools list_comments and update_status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies use after list_comments to retrieve detailed context for a specific comment. No explicit when-not-to-use or alternative mention, but context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_commentsA
List Loupe product-feedback comments for the project as a task backlog. Use this to see what a PM has flagged, then work through the items.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Filter to a single page path, e.g. /checkout. | |
| status | No | Filter by status. Omit for all. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden for behavioral traits. It does not mention read-only nature, side effects, authentication, or rate limits, which are important for safe invocation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two concise sentences with no filler. The purpose is front-loaded in the first sentence, and the use case is in the second.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a list tool with two optional parameters and no output schema, the description gives adequate context about the task backlog usage. However, it could mention return format or ordering for completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The tool description adds no additional parameter detail beyond the schema's own descriptions, so it does not improve parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'List' and resource 'Loupe product-feedback comments for the project as a task backlog'. It differentiates from siblings (get_comment, update_status) by emphasizing it returns a list for review.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides context: 'Use this to see what a PM has flagged, then work through the items.' This implies when to use it, though explicit exclusions or comparisons to siblings are absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_statusA
Update a comment's status. Set to in_progress when you start it and done when the change is shipped — this closes the loop back to the PM.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| status | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided; description only states it updates status and mentions closing the loop. Does not disclose mutation behavior, idempotency, auth requirements, or other side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: first states purpose, second provides usage guidance. No wasted words, front-loaded with key information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple update tool with 2 required params and no output schema, the description covers the main usage. Minor missing details (e.g., behavior when setting to 'open') but sufficient for typical use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% so description must compensate. Adds meaning to the status parameter with concrete use cases ('in_progress when you start it', 'done when shipped') but does not explain the id parameter beyond its type.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Update a comment's status' with specific use cases for each status value, distinguishing from read-only siblings get_comment and list_comments.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly describes when to use 'in_progress' and 'done' statuses, providing context for closing the loop with the PM. No explicit exclusion of other scenarios, but sufficient for typical use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.5.2- First observed
get_comment - First observed
list_comments - First observed
update_status
TDQS
Scored across 3 tools
Each tool targets a distinct operation: retrieving a single comment's full context, listing all comments, and updating a comment's status. There is no functional overlap.
All tool names follow a consistent verb_noun pattern with snake_case: get_comment, list_comments, update_status. Singular/plural usage is correct for each operation.
Three tools is slightly low but appropriate for a focused server that handles comment viewing and status management. The set is concise without being insufficient.
The tools cover listing, detail retrieval, and status updates, which are core for working through feedback. However, creation and deletion of comments are absent, leaving notable lifecycle gaps.
Maintenance
Related MCP Connectors
Comment on AI-generated webpages; feedback flows back to your coding agent. Free, MIT, local-first.
Capture feature requests and bug reports from chat into a searchable, AI-categorized backlog.
UX-review and product-feedback MCP: annotated screenshots and reviews your AI agent can act on.
Human feedback for AI agents: share HTML, get a live review link, read anchored notes as markdown.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables visual annotation on web pages for Claude Code, allowing element selection, comment addition, screenshot capture, and structured UI feedback for code fixes via an MCP server.MIT
- FlicenseAqualityAmaintenanceEnables visual browser feedback collection directly into Claude Code. Users can point at elements in their browser and send annotated feedback that Claude can act on immediately.121-
- FlicenseNot gradedqualityAmaintenanceEnables UI feedback loop by clicking elements, leaving comments, and letting AI coding agents (via MCP) resolve annotations interactively.2-
- AlicenseAqualityAmaintenanceInteractive feedback layer that lets users pin comments on live web apps with auto-captured context (failing requests, console, AI metadata), and coding agents fix issues via MCP, turning pins green upon verification.1022 npmMIT