loopback
The Loopback server provides a feedback management bus where AI coding agents can collect, triage, fix, and close product feedback from live web apps. It enables a tight feedback loop between user-reported issues and automated resolution.
Core capabilities:
Submit feedback: File new items with rich context (project, type, severity, title, body, console logs, network requests, repro steps, DOM selector, screenshots, replay URL, LLM metadata).
List feedback: Query and paginate the queue, filterable by project, status, type, severity, source, assignee, route; ordered by severity and recency.
Get feedback: Retrieve full item details including context, audit trail, and linked changes.
Claim feedback: Atomically assign an item to an agent (status →
in_progress), preventing duplicate work, with optional forced takeover.Update status: Move items through
open → triaged → in_progress → fixed → verified | wontfix, adding optional notes.Comment: Append investigation notes, questions, or reasoning to the discussion trail.
Link code change: Attach repository, branch, commit, PR URL, and diff summary to track the fix.
Resolve: Close items as
verifiedorwontfixwith optional closing note.Queue stats: Get aggregate counts by project and status for orientation and reporting.
Additional interfaces:
Embeddable widget: JavaScript snippet for web apps that captures UI context, lets users pinpoint issues, and shows live status updates.
HTTP ingestion: Accepts feedback from external systems (CI/CD, error trackers) via a JSON POST endpoint.
Dashboard UI: Web-based view (
/queue) for human triage, filtering, editing, commenting, and file attachments.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@loopbackwork the feedback queue for acme-demo"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Loopback
Pin feedback on the app you're building. Any coding agent claims it. The pin turns green when the fix is verified.
Loopback is the interactive feedback layer between real product usage and your
coding agents: one script tag makes the app you're running locally commentable
(Vercel-toolbar-style toolbar, element-anchored pins; deployed public sites go
via the /ingest rails instead — see surface compatibility), every pin auto-captures
the functional context — failing requests with response bodies, console
trail, the route journey that led there, LLM run metadata, typed repro steps —
and lands in one project-tagged queue that Claude
Code, Codex, and Gemini CLI all work over MCP. When an agent's fix is
verified, the pin turns green on the page, live.
https://github.com/user-attachments/assets/1e1b2f9f-0130-4b1d-a0dd-3aff8d801d5a
![The loop, closed: a green verified pin on the form claude-code fixed (PR linked), an amber open pin on the AI answer, and the Loopback panel listing both]
Seeded demo capture (generated by scripts/screenshot.mjs): the contact form's
backend bug pinned, claimed by claude-code, marked fixed with a linked change,
verified — pin and badge green. The wrong AI answer is still amber/open.
Why
Coding agents can fix anything you can describe — but the loop back from real usage is missing. You notice a broken flow, screenshot it, re-describe it in a prompt, paste console output, explain which project it belongs to. Every time, for every agent. Vercel's comments have no public API; Claude Design's anchored comments are artifact-scoped; error trackers don't know your queue.
Loopback is that missing loop, built as a hub:
One instance, all projects. Every item is tagged with a
projectslug in one shared SQLite DB (~/.loopback/loopback.db). Agents registered once per machine; consuming repos add only a widget tag and a slug.One queue, all agents. MCP is the interface, so Claude Code, Codex, and Gemini CLI are peers — same tools, same playbook, same audit trail.
A pin is an anchor, not a scope. Pin a "broken" contact form and the agent gets the failing
POSTwith its 500 response body — a frontend pin carries the backend root cause. Pin an AI answer and the run metadata (run_id,model,trace_url) rides along.
CAPTURE THE HUB AGENTS
┌───────────────────────────┐ ┌─────────────────────────────┐ ┌─────────────────────────┐
│ widget pin on any app │──►│ loopback-mcp-server │◄──│ Claude Code │
│ · console + network ride │ │ one shared SQLite DB │ │ Codex (peers) │
│ · 500 bodies captured │ │ ~/.loopback/loopback.db │ │ Gemini CLI │
│ · AI run context │ │ │ └────────────┬────────────┘
├───────────────────────────┤ │ stdio (per-agent spawn) │ │
│ POST /ingest │──►│ --http on 127.0.0.1:7077 │ list → claim → fix →
│ · CI hooks, cron, │ │ (required for widgets) │ link change → fixed →
│ Sentry/PostHog pollers │ │ │ verify → resolve
└───────────────────────────┘ └──────────────┬──────────────┘ │
│ │
pins turn green on the page ◄─────┴───── status write-back ◄──────┘Run it per-invocation over stdio (each agent spawns it; same DB = same
queue) or as one long-running --http service on 127.0.0.1:7077
(required for widgets — keep it alive with pm2/launchd/systemd:
integrations/keep-alive.md).
Related MCP server: Lens
Quickstart (see the whole loop in 2 minutes)
Requires Node ≥ 22.13 (built-in node:sqlite — zero native deps).
git clone https://github.com/joshidikshant/loopback && cd loopback
npm install # prepare script builds dist/
node dist/index.js --http # the hub, on 127.0.0.1:7077
node demo/serve.mjs # demo app on 127.0.0.1:5173 (broken backend + wrong AI answer)Open http://127.0.0.1:5173 → submit the form (it fails politely) → ✦ Loopback → Pin feedback on an element → click the submit button → Send. The form shows the captured failed request. Then tell any connected agent "work the feedback queue for acme-demo" — or watch the item at http://127.0.0.1:7077/queue and be the agent yourself over MCP. When it's resolved, the open page announces it and the pin goes green.
Install once per machine
Register the MCP server + instructions once per agent; after this, new projects
are a two-minute init. The copy-paste version — Claude Code (.mcp.json in
your project, or ~/.claude.json for all projects):
{
"mcpServers": {
"loopback": {
"command": "npx",
"args": ["-y", "loopback-mcp-server"]
}
}
}Codex and Gemini CLI take the same command/args in their own config — the
server is the same binary over stdio. All three are equal citizens — full
per-agent pages in integrations/:
Agent | MCP registration | Instructions/skill channel |
Claude Code |
|
|
Codex |
| AGENTS.md read natively + native SKILL.md at |
Gemini CLI |
| AGENTS.md via |
All three also accept the long-running instance over streamable HTTP
(http://127.0.0.1:7077/mcp) instead of spawning — see the per-agent pages.
Integrate a new project (2 minutes)
Central instance running (once per machine):
loopback-mcp-server --http, kept alive per keep-alive.md.Paste the widget tag into the app, with your slug (template):
<script src="http://127.0.0.1:7077/widget.js" data-project="my-app" data-endpoint="http://127.0.0.1:7077"></script>From the repo root:
npx loopback-mcp-server init --project my-app --writeOne canonical playbook (integrations/instructions-src.md) is rendered into every agent's native mechanism: the AGENTS.md queue section (canonical; Codex + Gemini read it natively),
@AGENTS.mdimports in CLAUDE.md and GEMINI.md, the same SKILL.md installed for Claude (.claude/skills/) and Codex (.agents/skills/), MCP registration for all three (.mcp.json,.gemini/settings.json,.codex/config.toml), and a/loopbackGemini command. Merges are non-destructive and idempotent — re-run it anytime.In any of the three agents, say: "work the feedback queue for my-app" — or say nothing: the skill descriptions and AGENTS.md section make feedback-ish requests trigger the loop on their own.
Using it day to day
With the hub running (loopback-mcp-server --http), everything happens on two
surfaces and one sentence to an agent:
I want to… | Do this |
Report something on a page with the widget | Click ✦ Loopback → Pin feedback on an element, click the thing, describe it. Failing requests, console, and AI run context attach themselves. |
See the queue |
|
Read everything on one item | Click its id → |
Comment or change status myself | On the item view — plain forms, no agent needed |
Get it fixed | In the repo, tell any agent: "work the feedback queue for |
Watch it close | The pin on your page turns green and announces itself; the item shows the commit/PR |
File from a script or CI |
|
Writes that change an item (comment, status) are same-origin only — see Security below.
Giving feedback about Loopback
Loopback is its own reference integration — it eats its own dog food, and so can you. Four ways in, from most to least convenient:
Pin it on the queue page. With the hub running, open
http://127.0.0.1:7077/queue— the capture widget is embedded there withdata-project=loopback. Click ✦ Loopback → Pin feedback on an element, click whatever is wrong, describe it. Same loop as any other project.Tell an agent. In this repo (self-onboarded with its own
init), say "file feedback for loopback: <what's wrong>" — the skill and AGENTS.md section are already installed for Claude, Codex, and Gemini.curlit from anywhere:curl -X POST http://127.0.0.1:7077/ingest -H 'Content-Type: application/json' \ -d '{"project":"loopback","type":"ux","severity":"p2", "title":"…","body":"what happened / what you expected"}'GitHub issues for anything a stranger should see: https://github.com/joshidikshant/loopback/issues.
Then work it like any queue: "work the feedback queue for loopback". Every Loopback defect in this repo's history was filed and closed exactly this way.
The dashboard
/queue is a React + shadcn app (dashboard/, built with the real shadcn
CLI). Filter by clicking status tiles or any project / severity / type cell —
filters compose and live in the URL, so every view is linkable. Open an item to
read everything captured, edit it (title, body, severity, type — every change
lands on the audit trail), comment, change status, and attach files.
Attachments declare why they exist, because that decides what an agent does:
Intent | Meaning |
| Context for the fix — a screenshot, a spec, a "make it look like this". Read it, then leave it. It never ships. |
| A deliverable. The blob store is a transfer buffer: the item carries a |
Blobs live in ~/.loopback/blobs/<item>/, beside the DB rather than inside it,
and agents get an absolute local path so they copy the file instead of
decoding it out of the protocol.
The build output is committed to public/dashboard/, so
npx loopback-mcp-server still needs no React, no Tailwind and no build step —
the hub just serves files. npm run dashboard:build after changing
dashboard/src; dashboard-gate fails CI if the committed build has drifted.
Design system (shadcn-compatible, zero dependencies)
Both surfaces — widget and /queue — are built from one token set in vanilla
CSS that speaks shadcn/ui's contract (oklch variables, .dark, the
multiplicative radius scale). No React, no Tailwind, no build step; drop
design/tokens.css into any shadcn/v0 project and it themes from that
project's palette. Full rationale and the shadow-DOM isolation rules:
design/README.md.
Loopback also publishes a shadcn registry, so React projects can install its pieces and the shadcn MCP can discover them:
npx shadcn@latest add https://raw.githubusercontent.com/joshidikshant/loopback/main/public/r/loopback-theme.json
npx shadcn@latest add https://raw.githubusercontent.com/joshidikshant/loopback/main/public/r/loopback-components.json
npx shadcn@latest add https://raw.githubusercontent.com/joshidikshant/loopback/main/public/r/loopback-widget.jsonThree items:
loopback-themeships the FULL shadcn theme contract (background, foreground, primary, muted, ring, radius…) alongside the--lb-*feedback status/severity tokens, so installing it replaces your palette. If you only want the Loopback-specific tokens, copy the--lb-*block out ofdesign/tokens.cssinstead.loopback-components— vanilla CSS recipes for the shadcn component vocabulary (lb-btn,lb-badge,lb-card…), for surfaces that want the look without React.loopback-widgetdrops the capture widget intopublic/.
Register "@loopback" in your components.json to install by name and let an
agent with the shadcn MCP browse the registry.
Where it works (surfaces)
The queue is transport-agnostic — the widget is just its richest producer. Full matrix, native snippets (Swift/Kotlin/C#/shell), and the honest edges: docs/05-surface-compatibility.md.
Surface | Status |
Web apps in local dev (any framework) · browser extensions (bundle the widget file — MV3 forbids remote scripts) · Electron/Tauri · WebViews | ✅ widget: pins + auto-context + green write-back |
Deployed public sites | ✖ Chrome 142+ blocks a public page from reaching |
Native macOS/Windows apps · CLIs · CI/cron · agents/automations | ✅ |
iOS/Android simulators & emulators | ✅ shared loopback / |
iOS/Android physical devices on LAN | ✅ |
iOS/Android production | ✅ via Sentry/PostHog rails (their SDKs capture; bridge to the queue) |
The widget
~58KB (19KB gzipped) of dependency-free vanilla JS in a shadow-DOM host — it never fights your app's CSS or framework.
Capture: pin mode highlights elements on hover; a click opens a viewport-clamped form (title / what happened / what you expected / type / severity). Type is pre-guessed:
backendwhen failed requests exist,usagewhen AI context is present.Functional context, always on: ring buffers from page load keep the last 30 console lines (log/warn/error + window errors + unhandled rejections) and the last 30 fetch/XHR calls (url/method/status/ms); a filed report carries the most recent 15 of each, plus — for failures (status ≥ 400 or network error) — up to 2KB of response body into
extra.failed_responses. Calls to Loopback itself are never recorded.AI/automation context: the nearest ancestor with
data-loopback-context='{"run_id":...}'is parsed intoextra.context.Selector + element: stable CSS selector (
#id/[data-testid]preferred,nth-of-typefallback, depth-capped) + outerHTML snippet + viewport + UA.SPA-aware: client-side route changes (
pushState/popstate) refresh pins immediately — no stale pins from the previous route.Live status pins: hydrate from
GET /feedbackon load and every 10s — amberopen, deeper ambertriaged, bluein_progress, pale greenfixed(an agent says it is done), full greenverified(confirmed against the running app), graywontfix. The two greens are deliberately different: the pin earning its full colour only atverifiedis the whole point, sofixedreads as provisional. Click a pin for id/status/assignee/PR.The loop closes visibly: when a status changes under an open page, the widget announces it — toast ("… open → verified by claude-code · PR linked"), pulsing pin, and a 🔔 tab-title flash if you're on another tab (adapted from make-pages-interactive's reload walkthrough, MIT).
Page API:
window.__loopback={ pins, refresh(), project, endpoint, version }(adapted from DOM-Review's__domReviewAPI, MIT) — used by the E2E suite, usable by any agent driving a browser.
The MCP bus — 10 tools
Tool | What it does |
| File an item: project, type |
| Filter (project/route/status/type/severity/source/assignee) + paginate ( |
| Full item: all context + linked change + comment trail |
| Correct an item after filing: title, body, severity, type, project, or route — re-rank a severity, fix a mis-guessed type, move it to the right project |
| Atomic claim; a conflict names the holder; |
|
|
| Root-cause notes, questions, reasoning trail |
| Merge repo/branch/commit/pr_url/diff_summary onto the item |
| Close as |
| project × status counts |
Responses are markdown (default) or JSON via response_format, always with
structuredContent; long output truncates at 25k chars with guidance.
HTTP surface (--http, port 7077 / LOOPBACK_HTTP_PORT / --port)
Endpoint | Purpose |
| Stateless MCP streamable HTTP (fresh server per request; GET/DELETE → 405) |
| Plain-JSON submit — widgets, CI hooks, cron ingestors (201 + item; 400 with field-level issues) |
| List/filter (widget pin hydration) |
| Full item view — all captured context + comment/status actions |
| Human triage writes (same-origin only) |
| One item with its full trail, as JSON |
| Attach a screenshot or asset to an item ( |
| Fetch one attachment's bytes |
| Remove an attachment |
| The embeddable widget |
| Liveness |
Security: the trust boundary is not "localhost" — a loopback port is reachable from every page open in your browser. So:
CORS is granted to
POST /ingest,GET /feedbackandGET /widget.jsonly — the three things the widget genuinely needs from a foreign origin.Cross-origin reads get the pin projection (id, status, title, assignee, selector, PR link).
extra— captured response bodies, which routinely contain auth headers — is never served cross-origin.Everything that reads full context or changes state, including
/mcp, requires an origin pinned at startup from the bind config. Local tooling that sends noOrigin(curl, MCP clients) still works.URLs on items are rendered as links only when they are
http(s)— enforced bysafeHref()in the dashboard, which resolves the URL and reads its protocol.data:,vbscript:andfile:render as plain text.
A non-loopback bind requires a token. On 127.0.0.1 there is none — it
would protect nothing the OS does not already protect. The moment --host /
LOOPBACK_HOST widens the bind, the server generates one (or takes
LOOPBACK_TOKEN) and prints a ?token=… URL; the token is accepted once from
the query string, moved into an HttpOnly cookie, and stripped from the URL so
it does not persist in history or referrers. Tools send
Authorization: Bearer <token>. Comparison is constant-time over a digest, so
neither the value nor its length leaks through timing.
Four endpoints stay open on a LAN bind, deliberately:
Open | Why |
| The widget runs on a phone against an arbitrary host page and has nowhere to keep a secret. Intake is append-only and rate-limited (60/min per IP, 429 past that): a LAN caller can file noise, not read or change anything, and not fill the disk. |
| Anything embedded in a served script is readable by anyone who can fetch it. |
| The minimum needed to draw pins and show one turn green. A strict projection — no body, console, network, repro steps, comments or attachments — of what is already visible on the page. |
| Liveness only — |
Everything else — the dashboard, full reads, every write, and /mcp, which
exposes all ten tools — refuses an unauthenticated caller with 401. The split
is asserted in scripts/e2e.mjs in both directions, and
npm run canary proves that assertion fails when the check is disabled.
This is a shared secret on a trusted network, not a substitute for real auth. Before exposing Loopback beyond a LAN, put it behind a reverse proxy.
Publishing to the MCP Registry
Loopback carries the identity the official MCP Registry uses to prove package ownership:
Where | Field | Value |
|
|
|
|
|
|
The registry fetches the published npm version metadata and requires
mcpName to equal server.json's name exactly; GitHub-based authentication
additionally requires the io.github.<username>/ prefix. server.json stays in
the repo and out of the npm tarball — the package only needs to carry mcpName.
Because npm versions are immutable, a mismatch costs a version number rather
than a retry. npm run smoke therefore asserts all six coupled fields (three
versions, the name pair, the npm identifier) and npm run canary proves that
assertion fails when they drift.
To release and submit:
npm publish --otp=<code> # 2FA code from your authenticator
mcp-publisher validate # checks server.json against the live registry
mcp-publisher login github # opens a browser
mcp-publisher publish # reads server.json
npm run verify:release # proves all three channels from a clean dirRun validate before publish — it checks the manifest against the real
registry without spending an attempt. Run verify:release after, and read what
it prints: it installs the published tarball into a clean directory, renders
init from it, speaks real MCP to the result, confirms the registry listing
resolves to the version you just shipped, and runs the plugin's own registered
command from an empty directory. Every one of those steps has caught a real bug
that the source-side gates could not see. description is capped at 100
characters and is rejected, not truncated, past it, so npm run smoke
asserts that limit locally as well.
Tests
npm run build
npm run smoke # real MCP client over stdio: 10 tools, full loop, atomic-claim conflict
npm run e2e # Playwright: pin capture → 500-body & run-context assertions → agent over MCP-HTTP → green pins
npm run init-gate # init renderings ×3 agents, byte-level idempotence, merge safety
npm run registry-gate # the published shadcn registry still resolves and installs
npm run dashboard-gate # the committed dashboard build matches dashboard/src
npm run impeccable-gate # design anti-patterns in the shipped UI (canary-verified)
npm run widget-token-gate # the widget's inlined tokens still equal design/tokens.css
npm run a11y-gate # contrast, target size, names, landmarks, motion — measured in a browserCI runs all of them on every push (LOOPBACK_E2E_CHROMIUM overrides the
browser binary if needed).
Several of these are built to resist passing for the wrong reason, because the
underlying tools fail open: a stale dashboard build serves happily with no error
anywhere, and impeccable detect exits 0 when it scans nothing. So
dashboard-gate rebuilds and compares rather than trusting mtimes, and
impeccable-gate scans a canary fixture that is required to trip before it
will believe a clean result.
a11y-gate and widget-token-gate exist because the two things they check —
accessibility and cross-surface token parity — regressed silently more than
once. The widget inlines its own copy of the tokens (it ships as one file and
cannot @import them) and had already drifted; components.css hardcoded a
near-white pin colour that broke the moment a status token went pale. Every gate
here has had both of its failure paths verified by deliberately breaking them.
Companions (borrow, don't rebuild)
Loopback is deliberately only the bus + capture layer. Pair it with the mature MCP-native pieces — the build-vs-borrow memo is the full analysis:
chrome-devtools-mcp / playwright-mcp — the agent sees and verifies the running app (the "verify" step of the loop)
Sentry MCP — production errors (incl. mobile) →
POST /ingestwithsource: "sentry"PostHog MCP — analytics/replays/surveys →
source: "posthog",replay_urlattached
Design decisions
The full history lives in docs/ (original spec, build-vs-borrow memo, interaction-layer analysis, technical path). Calls made in this build:
node:sqlite, never better-sqlite3 — native builds fail in clean environments; zero native deps is the feature.stdio + stateless streamable HTTP only, no SSE — the exact transport intersection of Claude Code, Codex, and Gemini CLI (SSE is deprecated in Claude Code and absent in Codex).
AGENTS.md is canonical — Codex and Gemini read it natively; Claude imports it via
@AGENTS.md(imports beat symlinks for Windows safety). One playbook source renders into every native mechanism; no agent is "the default".Codex gets project-scoped
.codex/config.toml— verified supported (loads once you trust the repo);initalso prints the global block.initwrites a repo-relative path when the server lives inside the onboarded repo,npx loopback-mcp-servereverywhere else — committed configs must work on every clone; a machine path works on exactly one. (Originally: absolute path for stable checkouts,npx github:for ephemeral runs — both retired once the package was on npm.)/ingestaccepts unknown extra fields (no.strict()) — older hubs must not reject newer widgets; forward compatibility beats strictness at the ingestion boundary.Widget is 58KB / 19KB gzipped, not the ~10KB sketch — ring buffers, failure-body capture, live pins, repro steps, the route journey and the walkthrough earn their bytes; still zero deps, one file, served pre-compressed with an ETag.
Marker-based merges —
initre-runs are byte-idempotent; files a human has taken over (generated marker removed) are left untouched.Interaction patterns adapted with attribution (MIT): make-pages-interactive's visible-closure walkthrough; DOM-Review's page API.
Repo map
src/ the bus: server (10 tools) · store (node:sqlite) · http · init
widget/ loopback-widget.js — the embeddable capture layer
dashboard/ React + shadcn source for /queue (built output in public/dashboard)
demo/ intentionally broken playground app
design/ shared tokens.css — one design system for widget, dashboard, registry
public/ built dashboard + the published shadcn registry (public/r)
skills/ CANONICAL loopback SKILL.md — every other copy is rendered from it
integrations/ canonical playbook + per-agent setup + widget embed + keep-alive
plugin/ Claude Code plugin (skill + MCP registration); repo doubles as its marketplace
scripts/ e2e.mjs · the seven gates · canary-all.mjs · screenshot.mjs
release-preflight.mjs (pre-publish) · release-verify.mjs (post-publish) · bump-version.mjs
docs/ the decision history (spec → memo → paths → technical path) + ROADMAP
assets/ the README screenshot (generated by scripts/screenshot.mjs)
.github/ ci.yml · canary.yml · readme-checks.yml · issue and PR templates
.impeccable/ design-detector config (the skill itself is not vendored — see .gitignore)
CONTRIBUTING.md how to run the gates, and why a new gate needs a canary case
SECURITY.md the trust boundary, what is deliberately open, and what is out of scope
CHANGELOG.md every release, with the reasoning that produced itTwo manifests at the root do different jobs: registry.json publishes the
shadcn components, and server.json is the MCP Registry entry (see
Publishing to the MCP Registry).
The root also carries agent config that init itself writes — the repo
onboards itself, so these are working proof the command produces what it
claims, and init-gate re-renders them on every CI run to prove they have not
drifted:
AGENTS.md · CLAUDE.md · GEMINI.md the queue playbook, per agent
.claude/ .agents/ the loopback skill for Claude Code / Codex
.codex/ .gemini/ per-agent MCP + command registration
.mcp.json MCP server registration for this repo.claude-plugin/ is the one root dot-directory init does not write: it is
the marketplace manifest for the plugin this repo hosts, maintained by hand and
bumped by npm run bump. init-gate asserts its version matches rather than
re-rendering it.
MIT © Dikshant Joshi
Available Tools
10 toolsloopback_add_commentComment on feedbackA
Append a comment to a feedback item's discussion trail. Use for investigation notes, questions back to the reporter, or reasoning worth preserving.
Args: id, author, body (markdown ok).
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' | |
| body | Yes | Comment text (markdown ok) | |
| author | Yes | Comment author, e.g. 'claude-code' or 'dj' |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' |
| url | No | |
| body | Yes | |
| type | Yes | |
| extra | Yes | Free-form captured context. Read `extra.failed_responses` for failing requests with up to 2KB of response body, and `extra.context` for LLM/automation run metadata (run_id, model, trace_url). |
| links | Yes | Repo/branch/commit/PR of the fix |
| route | No | |
| title | Yes | |
| source | Yes | |
| status | Yes | |
| console | Yes | Console lines captured at report time |
| network | Yes | Network calls captured at report time |
| project | Yes | |
| comments | No | Full audit trail |
| reporter | Yes | |
| severity | Yes | |
| created_at | Yes | |
| replay_url | No | |
| resolution | No | |
| updated_at | Yes | |
| attachments | No | Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`. |
| repro_steps | Yes | |
| dom_selector | No | |
| assignee_agent | No | Agent currently holding the claim |
| screenshot_path | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=false. The description adds the 'append' semantics but does not disclose further behavioral traits like potential side effects (e.g., notifications, permanence of comments) or prerequisites. It is consistent with annotations but adds only modest behavioral context beyond them.
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 exceptionally concise, using two sentences to establish purpose and use cases, followed by a compact args line. Every sentence earns its place with no redundant filler.
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?
The tool is simple, an output schema exists, and the description covers purpose and usage adequately. It does not mention idempotency (repeated calls create multiple comments) or error cases, but these are not essential given the low complexity and available structured information.
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 100%, with each parameter having clear descriptions and examples. The description's 'Args: id, author, body (markdown ok)' simply repeats schema information without adding new meaning, so it adds no value beyond the structured 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?
The description clearly states a specific action ('Append a comment') and resource ('feedback item's discussion trail'), which distinguishes it from sibling tools like update_feedback or update_status. It is unambiguous and immediately understandable.
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 concrete use cases ('investigation notes, questions back to the reporter, or reasoning worth preserving'), giving clear context for when to use the tool. However, it does not explicitly mention when not to use it or name alternative tools, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
loopback_claim_feedbackClaim feedback itemAIdempotent
Atomically claim a feedback item for an agent before working on it. Prevents two agents from fixing the same thing.
Args: id, agent (your name, e.g. 'claude-code', 'codex', 'gemini'), force (default false).
On success the item's assignee_agent is set and status moves to 'in_progress' (from open/triaged). If another agent already holds the claim, this fails with a message naming the holder — pass force=true only if you intend to take over.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' | |
| agent | Yes | Name of the claiming agent, e.g. 'claude-code', 'codex', 'gemini' | |
| force | No | Take over even if another agent already claimed the item |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' |
| url | No | |
| body | Yes | |
| type | Yes | |
| extra | Yes | Free-form captured context. Read `extra.failed_responses` for failing requests with up to 2KB of response body, and `extra.context` for LLM/automation run metadata (run_id, model, trace_url). |
| links | Yes | Repo/branch/commit/PR of the fix |
| route | No | |
| title | Yes | |
| source | Yes | |
| status | Yes | |
| console | Yes | Console lines captured at report time |
| network | Yes | Network calls captured at report time |
| project | Yes | |
| comments | No | Full audit trail |
| reporter | Yes | |
| severity | Yes | |
| created_at | Yes | |
| replay_url | No | |
| resolution | No | |
| updated_at | Yes | |
| attachments | No | Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`. |
| repro_steps | Yes | |
| dom_selector | No | |
| assignee_agent | No | Agent currently holding the claim |
| screenshot_path | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses the atomic claim behavior, the exact state changes (assignee_agent set, status moves to 'in_progress'), and the failure condition with a message naming the holder. It also explains the semantics of force=true. This is rich behavioral context that annotations alone do not provide.
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 three short paragraphs, with the key action in the first sentence. Every sentence adds necessary detail: the purpose, the parameters, and the outcome/failure. There is no redundant or filler text; it is appropriately sized for the tool's complexity.
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?
The description covers what the tool does, when to use it, parameter semantics, success state changes, and failure behavior. Given that an output schema exists (though not shown), the description need not detail return values. For a claim tool with concurrency concerns, this is complete and self-sufficient.
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 100%, so baseline is 3. The description adds value by explaining the parameter roles in context (agent as 'your name', force with its default and implication), and by tying them to the success/failure behavior. This exceeds the schema's plain descriptions, justifying a 4.
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 opens with a specific verb+resource: 'Atomically claim a feedback item for an agent before working on it.' This clearly distinguishes the tool from siblings like update or resolve, and the atomicity detail adds unique purpose. The wording prevents any ambiguity about what operation is performed.
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 states when to use it ('before working on it') and explains the failure mode and force option, giving practical usage guidance. It does not explicitly name alternative tools for similar tasks, but the context makes the appropriate scenario obvious. The guidance is clear enough to be effectively 4.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
loopback_get_feedbackGet feedback itemARead-onlyIdempotent
Fetch one feedback item with full context: description, repro steps, console lines, network entries, screenshot/replay links, linked change (commit/PR), and the complete comment trail.
Args: id (fb_...), response_format (markdown|json).
Read this before starting a fix — it contains everything captured at report time.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' | |
| response_format | No | 'markdown' for human-readable, 'json' for machine-readable | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' |
| url | No | |
| body | Yes | |
| type | Yes | |
| extra | Yes | Free-form captured context. Read `extra.failed_responses` for failing requests with up to 2KB of response body, and `extra.context` for LLM/automation run metadata (run_id, model, trace_url). |
| links | Yes | Repo/branch/commit/PR of the fix |
| route | No | |
| title | Yes | |
| source | Yes | |
| status | Yes | |
| console | Yes | Console lines captured at report time |
| network | Yes | Network calls captured at report time |
| project | Yes | |
| comments | No | Full audit trail |
| reporter | Yes | |
| severity | Yes | |
| created_at | Yes | |
| replay_url | No | |
| resolution | No | |
| updated_at | Yes | |
| attachments | No | Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`. |
| repro_steps | Yes | |
| dom_selector | No | |
| assignee_agent | No | Agent currently holding the claim |
| screenshot_path | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is clear. The description adds valuable behavioral context by enumerating the full content (description, repro steps, console lines, network entries, links, linked change, comment trail) and advises reading it before a fix. This enriches the agent's understanding beyond annotations.
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 concise and well-structured: a one-sentence purpose with a detailed list of contents, a brief args line, and a final usage directive. Every sentence earns its place, and it is front-loaded with the core purpose and immediate value.
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?
With an output schema present, annotations covering safety, and a description that explains purpose, contents, and usage, the description is fully complete for a GET tool. It tells the agent exactly what to expect and how to use it, leaving no significant gaps.
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%, and the description repeats the two parameters (id, response_format) with brief format notes (fb_..., markdown|json). The schema already provides examples and defaults, so the description adds minimal additional semantic value beyond reinforcing the id format. Baseline 3 is appropriate given full schema coverage.
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 uses a specific verb ('Fetch'), a clear resource ('one feedback item'), and enumerates the full context returned, distinguishing it from sibling tools like loopback_list_feedback (which lists items) and loopback_get_stats (which returns stats). It clearly communicates the tool's scope and uniqueness.
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 explicit usage context: 'Read this before starting a fix' and states it contains everything captured at report time. This clearly signals when to use, though it does not explicitly name alternatives or when-not-to-use scenarios. It gives strong situational guidance without directly comparing to siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
loopback_get_statsQueue statsARead-onlyIdempotent
Overview of the feedback queue: counts by project and status. Use to orient before picking work, or to report queue health.
Args: project (optional — omit for all projects).
Returns { total, projects: [{ project, by_status, total }] }.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | Limit stats to one project; omit for all projects |
Output Schema
| Name | Required | Description |
|---|---|---|
| total | Yes | |
| projects | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint. The description adds return format details, which is helpful beyond annotations.
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?
Three concise sentences, front-loaded with purpose, no wasted words. Efficiently communicates usage, parameter, and return structure.
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 stats tool with one optional parameter and clear output described, the description is fully complete, aided by annotations and sibling context.
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 covers the parameter completely. The description restates the parameter's purpose without adding new semantics, meeting the baseline for 100% coverage.
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 it provides an overview of the feedback queue with counts by project and status, distinguishing it from action-oriented siblings like loopback_submit_feedback.
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 says 'Use to orient before picking work, or to report queue health,' giving clear context for when to use this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
loopback_link_changeLink code changeAIdempotent
Attach the fix to a feedback item so the loop is auditable: which repo/branch/commit/PR addressed it and a one-paragraph diff summary.
Args: id, plus any of repo, branch, commit, pr_url, diff_summary. Provided fields merge into existing links.
Call this right after committing the fix, before updating status to 'fixed'.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' | |
| repo | No | Repository, e.g. 'dj/appbroda-web' | |
| branch | No | Branch name of the fix | |
| commit | No | Commit SHA of the fix | |
| pr_url | No | Pull request URL | |
| diff_summary | No | One-paragraph summary of what changed |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' |
| url | No | |
| body | Yes | |
| type | Yes | |
| extra | Yes | Free-form captured context. Read `extra.failed_responses` for failing requests with up to 2KB of response body, and `extra.context` for LLM/automation run metadata (run_id, model, trace_url). |
| links | Yes | Repo/branch/commit/PR of the fix |
| route | No | |
| title | Yes | |
| source | Yes | |
| status | Yes | |
| console | Yes | Console lines captured at report time |
| network | Yes | Network calls captured at report time |
| project | Yes | |
| comments | No | Full audit trail |
| reporter | Yes | |
| severity | Yes | |
| created_at | Yes | |
| replay_url | No | |
| resolution | No | |
| updated_at | Yes | |
| attachments | No | Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`. |
| repro_steps | Yes | |
| dom_selector | No | |
| assignee_agent | No | Agent currently holding the claim |
| screenshot_path | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses the write operation and merge behavior ('Provided fields merge into existing links') and clarifies a non-destructive update with idempotentHint true. This goes beyond annotations by revealing the upsert semantics and its place in the audit flow. No contradiction.
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?
Three concise sentences cover purpose, args, and invocation timing. No fluff. The second paragraph lists args efficiently and the third gives a crisp trigger condition.
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 small, well-annotated tool with a complete schema and output schema, the description supplies the essential workflow placement and merge semantics. Nothing needed beyond what's given; the output schema exists, so return-value detail isn't required.
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 already covers all parameters with examples and 100% coverage. The description adds the merge behavior, telling the agent that partial field updates are allowed and that fields combine with existing links. That contextualizes usage beyond schema descriptions.
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 opens with 'Attach the fix to a feedback item so the loop is auditable' – a specific verb-target-purpose. It names the exact fields (repo, branch, commit, pr_url, diff_summary) and differentiates from sibling tools like loopback_update_status by defining the unique link-record operation.
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 states when to call: 'right after committing the fix, before updating status to fixed'. Provides clear workflow context, implying this tool precedes status updates. No explicit alternatives, but the timing instruction is strong guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
loopback_list_feedbackList feedbackARead-onlyIdempotent
List feedback items, filtered and paginated. This is the entry point for "work the queue".
Args (all optional): project, status (open|triaged|in_progress|fixed|verified|wontfix), type (ui|backend|usage|ux), severity (p0-p3), source, assignee_agent, limit (default 20), offset (default 0), response_format (markdown|json).
Returns items ordered most-severe first, then newest. Pagination metadata: total, count, offset, has_more, next_offset.
Typical agent flow: loopback_list_feedback(project='X', status='open') → loopback_claim_feedback → fix → loopback_link_change → loopback_update_status(status='fixed').
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Filter by feedback type | |
| limit | No | Maximum results to return | |
| route | No | Filter by app route where observed, e.g. '/checkout' | |
| offset | No | Number of results to skip (pagination) | |
| source | No | Filter by source | |
| status | No | Filter by status | |
| project | No | Filter by project slug; omit for all projects | |
| severity | No | Filter by severity | |
| assignee_agent | No | Filter by claiming agent, e.g. 'claude-code' | |
| response_format | No | 'markdown' for human-readable, 'json' for machine-readable | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | Items in this response |
| items | Yes | |
| total | Yes | Total matching the filters |
| offset | Yes | |
| has_more | Yes | |
| next_offset | No | Pass as offset for the next page |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true. The description adds meaningful behavioral details: results are 'ordered most-severe first, then newest' and pagination metadata includes total, count, offset, has_more, next_offset. No contradictions with annotations.
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 structured into clear segments: purpose, args list, return behavior, and typical flow. It is slightly longer than necessary due to repeating schema parameter details, but each section earns its place and there is no fluff.
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?
The description is highly complete: it explains the tool's role, all major filtering dimensions, ordering and pagination behavior, and provides a concrete workflow example. Output schema exists, but the description adds practical context that helps an agent decide when and how to invoke this tool.
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 the baseline is 3. The description summarizes the parameters with defaults and enum values, but does not add any semantic meaning beyond what the schema already provides for each parameter.
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 states 'List feedback items, filtered and paginated' with a specific verb and resource, and distinguishes itself from siblings by positioning as 'the entry point for work the queue'. This clearly separates it from tools like loopback_get_feedback or loopback_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?
Gives explicit usage context as the entry point for the queue and provides a typical agent flow: list → claim → fix → link → update status. However, it does not explicitly state when not to use it or mention alternatives, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
loopback_resolve_feedbackResolve feedbackAIdempotent
Close a feedback item with a final outcome.
Args: id, resolution ('verified' = the fix was confirmed against the running app, tests, or the relevant metric/replay; 'wontfix' = intentionally not addressing), note (optional closing comment), agent (YOUR name — this is the write that turns the reporter's pin full green, and omitting it records the generic default instead of you).
Prefer verifying before resolving: re-check the UI via your browser tools, or confirm the error/metric cleared, then call this.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' | |
| note | No | Optional closing note recorded as a comment | |
| agent | No | Who is resolving — your agent name. Recorded on the trail; defaults to 'agent'. This is the write that turns the reporter's pin green, so name yourself. | |
| resolution | Yes | 'verified' = fix confirmed against the running app/metric; 'wontfix' = intentionally not addressing |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' |
| url | No | |
| body | Yes | |
| type | Yes | |
| extra | Yes | Free-form captured context. Read `extra.failed_responses` for failing requests with up to 2KB of response body, and `extra.context` for LLM/automation run metadata (run_id, model, trace_url). |
| links | Yes | Repo/branch/commit/PR of the fix |
| route | No | |
| title | Yes | |
| source | Yes | |
| status | Yes | |
| console | Yes | Console lines captured at report time |
| network | Yes | Network calls captured at report time |
| project | Yes | |
| comments | No | Full audit trail |
| reporter | Yes | |
| severity | Yes | |
| created_at | Yes | |
| replay_url | No | |
| resolution | No | |
| updated_at | Yes | |
| attachments | No | Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`. |
| repro_steps | Yes | |
| dom_selector | No | |
| assignee_agent | No | Agent currently holding the claim |
| screenshot_path | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful context beyond the annotations: it's a write that 'turns the reporter's pin full green' and explains the consequence of omitting the agent parameter. It also clarifies the semantics of 'verified' and 'wontfix'. Annotations already indicate a non-read-only, idempotent write, and the description enriches this without contradiction.
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 concise and well-structured: purpose first, then parameter explanations, then a usage guideline. Every sentence adds essential information, with no filler or 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?
The description covers purpose, parameters, usage guidance, and side effects (turning pin green). The output schema exists (though not shown) so return values are handled. Minor gaps: it doesn't state whether a closed item can be reopened or how this affects statistics, but these are not critical for correct invocation.
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 100%, so parameters are well-defined. The description adds extra nuance for 'agent' (records generic default if omitted) and reinforces the meaning of the resolution enum, providing value beyond the 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?
The description opens with a specific verb+resource ('Close a feedback item with a final outcome') that clearly distinguishes this from siblings like loopback_update_feedback or loopback_update_status. The notion of a 'final outcome' (verified/wontfix) uniquely identifies the tool's role.
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?
Explicit guidance is given: 'Prefer verifying before resolving' and re-checking the UI or metrics before calling. This implies when to use the tool (after verification) and sets a behavioral expectation, though it doesn't explicitly state alternative tools for non-final updates.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
loopback_submit_feedbackSubmit feedbackA
Create a new feedback item in the Loopback bus.
Use this to file any observation about a running product: a UI defect, a backend error, a usage insight, or a UX papercut. Every item is tagged to a project so the right agent picks it up later.
Args: project (slug), type (ui|backend|usage|ux), title, and optionally body, severity (p0-p3, default p2), source, reporter, route, url, dom_selector, screenshot_path, replay_url, console[], network[], repro_steps[].
Returns the created item as JSON, including its generated id (fb_...). New items start with status 'open'.
Example: file "Pay button dead on iOS Safari" with project='shop-web', type='ui', severity='p1', route='/checkout'.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Full URL where observed | |
| body | No | Full description of the feedback/observation | |
| type | Yes | Feedback dimension: 'ui' (visual/design), 'backend' (errors/API), 'usage' (analytics/behavior), 'ux' (flow/experience) | |
| extra | No | Free-form context object: LLM run ids/model/trace URLs for AI features, automation run metadata, viewport, element HTML snippet, etc. | |
| route | No | App route where observed, e.g. '/checkout' | |
| title | Yes | Short summary, e.g. 'Checkout button dead on mobile Safari' | |
| source | No | Where this feedback came from | manual |
| console | No | Recent console log lines relevant to the issue | |
| network | No | Relevant network requests (url, method, status, ms) | |
| project | Yes | Project/repo slug this feedback belongs to, e.g. 'appbroda-web' | |
| reporter | No | Who reported it | human |
| severity | No | p0=critical, p1=high, p2=normal, p3=nice-to-have | p2 |
| replay_url | No | Session replay link (e.g. PostHog replay URL) | |
| repro_steps | No | Steps to reproduce | |
| dom_selector | No | CSS selector of the affected element | |
| screenshot_path | No | Path or URL of a screenshot |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' |
| url | No | |
| body | Yes | |
| type | Yes | |
| extra | Yes | Free-form captured context. Read `extra.failed_responses` for failing requests with up to 2KB of response body, and `extra.context` for LLM/automation run metadata (run_id, model, trace_url). |
| links | Yes | Repo/branch/commit/PR of the fix |
| route | No | |
| title | Yes | |
| source | Yes | |
| status | Yes | |
| console | Yes | Console lines captured at report time |
| network | Yes | Network calls captured at report time |
| project | Yes | |
| comments | No | Full audit trail |
| reporter | Yes | |
| severity | Yes | |
| created_at | Yes | |
| replay_url | No | |
| resolution | No | |
| updated_at | Yes | |
| attachments | No | Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`. |
| repro_steps | Yes | |
| dom_selector | No | |
| assignee_agent | No | Agent currently holding the claim |
| screenshot_path | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations carry no useful hints (all false), so the description carries the burden. It discloses that new items start with status 'open', returns a JSON with generated id, and mentions tagging to a project. It does not mention permissions or idempotency, but for a create operation the main side effect is explicit from 'Create'.
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 front-loaded with the core action, then follows with use case, parameter list, return behavior, and an example. Each section earns its place without padding; the example is especially valuable and the overall length is appropriate for a 16-parameter tool.
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?
Given the complexity (nested objects, 16 params) and that an output schema exists, the description still adds necessary context: usage scenarios, parameter listing, return format, and a concrete example. It does not explicitly discuss idempotency or failure modes, but these are partially covered by annotations and the schema.
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 100%, giving a baseline of 3. The description adds a concise parameter summary and a concrete example ('Pay button dead on iOS Safari' with project='shop-web', type='ui', severity='p1', route='/checkout') that clarifies how to combine parameters and the expected value formats.
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 opens with 'Create a new feedback item in the Loopback bus', clearly using a specific verb and resource, and differentiates from siblings by focusing on creation ('file any observation'). The sentence 'Every item is tagged to a project' adds scope specificity beyond the tool name/title.
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?
It provides a clear use case ('Use this to file any observation about a running product') and enumerates feedback types, but does not explicitly name alternatives or state when not to use it (e.g., existing items should be updated rather than re-submitted). The context is clear enough to avoid obvious misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
loopback_update_feedbackEdit feedback itemAIdempotent
Correct an item after it was filed: title, body, severity, type, project, or route.
Feedback is filed fast and imprecisely on purpose — that is what makes people file it at all. Use this to re-rank a severity you now understand, fix a mis-guessed type, correct a typo, or move an item to the right project.
Args: id, plus any of title, body, severity (p0-p3), type (ui|backend|usage|ux), project, route. Also author (default 'human') — use your agent name so the trail says who re-triaged it.
Every change is recorded as a comment naming the old and new value; nothing is silently rewritten. Fields you omit are left alone.
This is for correcting the REPORT. To record progress use loopback_update_status, and to record the fix use loopback_link_change.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' | |
| body | No | Corrected description | |
| type | No | Corrected dimension | |
| route | No | Corrected route | |
| title | No | Corrected summary | |
| author | No | Who is making the edit — recorded on the audit trail | human |
| project | No | Move to another project slug | |
| severity | No | Re-ranked severity |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' |
| url | No | |
| body | Yes | |
| type | Yes | |
| extra | Yes | Free-form captured context. Read `extra.failed_responses` for failing requests with up to 2KB of response body, and `extra.context` for LLM/automation run metadata (run_id, model, trace_url). |
| links | Yes | Repo/branch/commit/PR of the fix |
| route | No | |
| title | Yes | |
| source | Yes | |
| status | Yes | |
| console | Yes | Console lines captured at report time |
| network | Yes | Network calls captured at report time |
| project | Yes | |
| comments | No | Full audit trail |
| reporter | Yes | |
| severity | Yes | |
| created_at | Yes | |
| replay_url | No | |
| resolution | No | |
| updated_at | Yes | |
| attachments | No | Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`. |
| repro_steps | Yes | |
| dom_selector | No | |
| assignee_agent | No | Agent currently holding the claim |
| screenshot_path | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that every change is recorded as a comment naming old and new values, that nothing is silently rewritten, and that omitted fields are left alone. It also explains the author parameter's role in the audit trail. These go beyond the annotations, which only state readOnly=false, destructive=false, idempotent=true.
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 well-organized into purpose, usage, args, and behavior, but it is slightly longer than necessary. The rationale sentence ('Feedback is filed fast and imprecisely on purpose') is contextual but not essential. Still, every sentence earns its place and the front-loading is excellent.
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?
With an output schema present and 100% parameter coverage, the description only needed to add use-case clarity and behavioral notes, which it does thoroughly. It covers correction semantics, audit trail, partial updates, and sibling tool differentiation, making it complete for an agent to invoke correctly.
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 100%, so the baseline is 3. The description adds extra meaning by summarizing the args, explaining the author default ('use your agent name so the trail says who re-triaged it'), and clarifying that fields can be omitted and left unchanged. This adds genuine value beyond the 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?
The description opens with 'Correct an item after it was filed' and enumerates the editable fields (title, body, severity, type, project, route), making the verb and resource explicit. It also distinguishes itself from siblings like loopback_update_status (progress) and loopback_link_change (fix) by explicitly stating 'This is for correcting the REPORT.'
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?
It gives concrete when-to-use examples ('re-rank a severity you now understand, fix a mis-guessed type, correct a typo, or move an item to the right project') and explicitly names the alternatives: 'To record progress use loopback_update_status, and to record the fix use loopback_link_change.' This fully clarifies use vs alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
loopback_update_statusUpdate feedback statusAIdempotent
Move a feedback item through the workflow: open → triaged → in_progress → fixed → verified | wontfix.
Args: id, status, note (optional — recorded as a comment for the audit trail), author (default 'agent').
Use 'fixed' after making the change; use loopback_resolve_feedback for final verified/wontfix closure.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' | |
| note | No | Optional note recorded as a comment alongside the change | |
| author | No | Who is making the change (for the audit trail) | agent |
| status | Yes | New status. Workflow: open → triaged → in_progress → fixed → verified | wontfix |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Feedback id, e.g. 'fb_mabc12_3f9a1c' |
| url | No | |
| body | Yes | |
| type | Yes | |
| extra | Yes | Free-form captured context. Read `extra.failed_responses` for failing requests with up to 2KB of response body, and `extra.context` for LLM/automation run metadata (run_id, model, trace_url). |
| links | Yes | Repo/branch/commit/PR of the fix |
| route | No | |
| title | Yes | |
| source | Yes | |
| status | Yes | |
| console | Yes | Console lines captured at report time |
| network | Yes | Network calls captured at report time |
| project | Yes | |
| comments | No | Full audit trail |
| reporter | Yes | |
| severity | Yes | |
| created_at | Yes | |
| replay_url | No | |
| resolution | No | |
| updated_at | Yes | |
| attachments | No | Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`. |
| repro_steps | Yes | |
| dom_selector | No | |
| assignee_agent | No | Agent currently holding the claim |
| screenshot_path | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, and idempotentHint=true. The description adds valuable behavioral context: the note is recorded as a comment for the audit trail, the author defaults to 'agent', and status changes follow a defined workflow. This goes beyond what annotations provide.
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 three concise, front-loaded sentences. The first sentence immediately states the core action, the second lists arguments compactly, and the third gives targeted guidance for when to use this tool versus the resolve sibling. No unnecessary words.
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?
Given the rich schema, clear annotations, and presence of an output schema, the description fully covers what an agent needs to select and invoke the tool. It explains the workflow, audit trail behavior, and how to avoid misusing it for final closure.
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 the schema already documents each parameter fully. The description adds minor usage nuance (e.g., 'Use fixed after making the change') but largely repeats schema-provided information about the note and author defaults.
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 opens with a specific verb and resource ('Move a feedback item through the workflow') and enumerates the exact state transitions. It clearly differentiates from the sibling 'loopback_resolve_feedback' by reserving that tool for final verified/wontfix closure.
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 clear context: it maps the workflow order, directs to use 'fixed' after making the change, and names loopback_resolve_feedback as the tool for final closure. It does not explicitly exclude other sibling tools like loopback_update_feedback, but the workflow framing gives enough guidance for most cases.
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. Dates show when Glama detected each change.
9 tool updates
v0.9.3- Changed
loopback_add_comment1 field changed- added
Output schema / properties / attachmentsAdded value: +{ + "description": "Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`.", + "items": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "string" + }, + "intent": { + "description": "'reference' = context only; 'asset' = a deliverable to copy into the repo", + "enum": [ + "reference", + "asset" + ], + "type": "string" + }, + "mime": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "description": "Absolute path on this machine — read or copy it directly", + "type": "string" + }, + "size": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "target_path": { + "description": "For assets: the repo-relative path this file should end up at", + "type": "string" + }, + "url": { + "description": "Hub URL, for humans and browsers", + "type": "string" + } + }, + "required": [ + "id", + "created_at", + "name", + "mime", + "size", + "intent", + "path", + "url" + ], + "type": "object" + }, + "type": "array" +}
- Changed
loopback_claim_feedback1 field changed- added
Output schema / properties / attachmentsAdded value: +{ + "description": "Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`.", + "items": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "string" + }, + "intent": { + "description": "'reference' = context only; 'asset' = a deliverable to copy into the repo", + "enum": [ + "reference", + "asset" + ], + "type": "string" + }, + "mime": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "description": "Absolute path on this machine — read or copy it directly", + "type": "string" + }, + "size": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "target_path": { + "description": "For assets: the repo-relative path this file should end up at", + "type": "string" + }, + "url": { + "description": "Hub URL, for humans and browsers", + "type": "string" + } + }, + "required": [ + "id", + "created_at", + "name", + "mime", + "size", + "intent", + "path", + "url" + ], + "type": "object" + }, + "type": "array" +}
- Changed
loopback_get_feedback1 field changed- added
Output schema / properties / attachmentsAdded value: +{ + "description": "Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`.", + "items": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "string" + }, + "intent": { + "description": "'reference' = context only; 'asset' = a deliverable to copy into the repo", + "enum": [ + "reference", + "asset" + ], + "type": "string" + }, + "mime": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "description": "Absolute path on this machine — read or copy it directly", + "type": "string" + }, + "size": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "target_path": { + "description": "For assets: the repo-relative path this file should end up at", + "type": "string" + }, + "url": { + "description": "Hub URL, for humans and browsers", + "type": "string" + } + }, + "required": [ + "id", + "created_at", + "name", + "mime", + "size", + "intent", + "path", + "url" + ], + "type": "object" + }, + "type": "array" +}
- Changed
loopback_link_change1 field changed- added
Output schema / properties / attachmentsAdded value: +{ + "description": "Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`.", + "items": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "string" + }, + "intent": { + "description": "'reference' = context only; 'asset' = a deliverable to copy into the repo", + "enum": [ + "reference", + "asset" + ], + "type": "string" + }, + "mime": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "description": "Absolute path on this machine — read or copy it directly", + "type": "string" + }, + "size": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "target_path": { + "description": "For assets: the repo-relative path this file should end up at", + "type": "string" + }, + "url": { + "description": "Hub URL, for humans and browsers", + "type": "string" + } + }, + "required": [ + "id", + "created_at", + "name", + "mime", + "size", + "intent", + "path", + "url" + ], + "type": "object" + }, + "type": "array" +}
- Changed
loopback_list_feedback1 field changed- added
Output schema / properties / items / items / properties / attachmentsAdded value: +{ + "description": "Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`.", + "items": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "string" + }, + "intent": { + "description": "'reference' = context only; 'asset' = a deliverable to copy into the repo", + "enum": [ + "reference", + "asset" + ], + "type": "string" + }, + "mime": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "description": "Absolute path on this machine — read or copy it directly", + "type": "string" + }, + "size": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "target_path": { + "description": "For assets: the repo-relative path this file should end up at", + "type": "string" + }, + "url": { + "description": "Hub URL, for humans and browsers", + "type": "string" + } + }, + "required": [ + "id", + "created_at", + "name", + "mime", + "size", + "intent", + "path", + "url" + ], + "type": "object" + }, + "type": "array" +}
- Changed
loopback_resolve_feedback2 fields changed- added
Input schema / properties / agentAdded value: +{ + "description": "Who is resolving — your agent name. Recorded on the trail; defaults to 'agent'. This is the write that turns the reporter's pin green, so name yourself.", + "maxLength": 80, + "type": "string" +} - added
Output schema / properties / attachmentsAdded value: +{ + "description": "Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`.", + "items": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "string" + }, + "intent": { + "description": "'reference' = context only; 'asset' = a deliverable to copy into the repo", + "enum": [ + "reference", + "asset" + ], + "type": "string" + }, + "mime": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "description": "Absolute path on this machine — read or copy it directly", + "type": "string" + }, + "size": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "target_path": { + "description": "For assets: the repo-relative path this file should end up at", + "type": "string" + }, + "url": { + "description": "Hub URL, for humans and browsers", + "type": "string" + } + }, + "required": [ + "id", + "created_at", + "name", + "mime", + "size", + "intent", + "path", + "url" + ], + "type": "object" + }, + "type": "array" +}
- Changed
loopback_submit_feedback1 field changed- added
Output schema / properties / attachmentsAdded value: +{ + "description": "Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`.", + "items": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "string" + }, + "intent": { + "description": "'reference' = context only; 'asset' = a deliverable to copy into the repo", + "enum": [ + "reference", + "asset" + ], + "type": "string" + }, + "mime": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "description": "Absolute path on this machine — read or copy it directly", + "type": "string" + }, + "size": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "target_path": { + "description": "For assets: the repo-relative path this file should end up at", + "type": "string" + }, + "url": { + "description": "Hub URL, for humans and browsers", + "type": "string" + } + }, + "required": [ + "id", + "created_at", + "name", + "mime", + "size", + "intent", + "path", + "url" + ], + "type": "object" + }, + "type": "array" +}
- Added
loopback_update_feedback - Changed
loopback_update_status1 field changed- added
Output schema / properties / attachmentsAdded value: +{ + "description": "Files attached to this item. `intent` decides what you do with each: 'reference' is context for the fix and never ships; 'asset' is a deliverable — copy it from `path` to `target_path` in the repo, commit it, and record that with loopback_link_change. Read files from `path` directly rather than fetching `url`.", + "items": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "string" + }, + "intent": { + "description": "'reference' = context only; 'asset' = a deliverable to copy into the repo", + "enum": [ + "reference", + "asset" + ], + "type": "string" + }, + "mime": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "description": "Absolute path on this machine — read or copy it directly", + "type": "string" + }, + "size": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "target_path": { + "description": "For assets: the repo-relative path this file should end up at", + "type": "string" + }, + "url": { + "description": "Hub URL, for humans and browsers", + "type": "string" + } + }, + "required": [ + "id", + "created_at", + "name", + "mime", + "size", + "intent", + "path", + "url" + ], + "type": "object" + }, + "type": "array" +}
9 tool updates
v0.7.1- First observed
loopback_add_comment - First observed
loopback_claim_feedback - First observed
loopback_get_feedback - First observed
loopback_get_stats - First observed
loopback_link_change - First observed
loopback_list_feedback - First observed
loopback_resolve_feedback - First observed
loopback_submit_feedback - First observed
loopback_update_status
TDQS
Each tool has a distinct purpose: create, list, get, claim, update status, add comment, link change, resolve, and get stats. No two tools overlap in functionality.
All tools follow a 'loopback_verb_noun' pattern with snake_case, but some include 'feedback' (submit_feedback, list_feedback) while others omit it (update_status, add_comment). Mostly consistent but a minor deviation.
9 tools cover the full feedback management lifecycle without bloat. Each tool earns its place for creating, reading, updating, and resolving feedback items, plus statistics.
Core CRUD and workflow (claim, comment, link fix, resolve) are covered. Missing a tool to edit feedback details like title or severity, but that may be intentional for audit trail. Minor gap.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Comment on AI-generated webpages; feedback flows back to your coding agent. Free, MIT, local-first.
UX-review and product-feedback MCP: annotated screenshots and reviews your AI agent can act on.
91Visual website feedback your coding agent applies: pin change requests on the live site over MCP.
Human feedback for AI agents: share HTML, get a live review link, read anchored notes as markdown.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceHuman-to-AI code review bridge. Annotate UI elements in the browser with review comments, and AI agents read the feedback via MCP to fix code automatically — with full element context (CSS selector, styles, DOM path, accessibility info). 10 MCP tools, framework-agnostic Web Component, zero-config install via uvx.9-
- AlicenseNot gradedqualityDmaintenanceMCP server for visual feedback, video direction, and QA assertions on web pages, enabling AI agents to read, reply, and resolve annotations in real time.4MIT
- AlicenseAqualityDmaintenanceVisual feedback as agent work packets: stakeholders pin on your live app and your AI coding agent reads each pin (selector, screenshot, DOM, thread, acceptance criteria) via MCP and ships the fix.392081MIT
- FlicenseNot gradedqualityAmaintenanceEnables UI feedback loop by clicking elements, leaving comments, and letting AI coding agents (via MCP) resolve annotations interactively.2-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/joshidikshant/loopback'
If you have feedback or need assistance with the MCP directory API, please join our Discord server