Skip to main content
Glama

Why bugcap

Reviewing an app for bugs usually leaves you with two disconnected things: a screenshot and a mental note. By the time you file the issue, the context is gone. Once the screenshot is attached to a GitHub issue, it becomes unreadable to an API token. The CDN only resolves in a browser session, so an agent using gh can read the text but never the picture that explains the bug.

bugcap keeps the whole loop in one place:

πŸ“Έ Capture at the moment

Annotated screenshots through flameshot, satty or screencapture. No new annotation UI.

πŸ—‚οΈ Local record

A SQLite index and PNGs on disk. Nothing depends on GitHub being reachable.

πŸ€– Agent-readable

A stdio MCP server hands reports, images included, to Claude Code and other agents.

πŸ” Sync when ready

Push to a GitHub issue with the usual inline image, plus a plain copy agents can read.

🎞️ Record what happens

Short screen recordings as animated GIF, video or keyframes, with size caps.

πŸ–₯️ Triage in a browser

A local dashboard on 127.0.0.1 to browse, filter and set statuses.

πŸͺŸ Live mode

An always-on-top window (top-right) to capture or record, stage several items (open or remove any of them), then file a new bug, add to an existing one, or log a note-only bug.

Related MCP server: Lific

Quick start

# install from PyPI
pipx install 'bugcap[mcp]'

bugcap setup --yes                      # detects or installs a capture tool
cd ~/code/myproject && bugcap init      # scope reports to this repo

bugcap capture --title "Login fails" --note "Error toast after submit" --tag auth
bugcap list
bugcap dashboard --open                 # browse and triage in the browser

The usage guide covers every command: images and labels, recording, live mode, @ references, GitHub pull and sync, and the MCP tools.

If a report ID is not found, the error suggests bugcap list --all to see report IDs across all repos.

Connect your agent (MCP)

Requires the mcp extra. Then give your agent access to the reports:

claude mcp add bugcap -- bugcap mcp-serve

Or in a project's .mcp.json:

{ "mcpServers": { "bugcap": { "command": "bugcap", "args": ["mcp-serve"] } } }

The server exposes six tools: list_reports, get_report (returns the screenshot), request_screenshot, pull_issues, attach_image, attach_file and update_notes. Logs go to logs/mcp-server.log in the data directory, never to stdout.

Ask your agent something like "list the open bugcap reports for this repo and fix the one with the error toast". It can read the picture because it's a local file, not a CDN link.

How it works

 capture ──► local store (SQLite + images/) ──► MCP / dashboard / CLI   (read by agents and you)
                       β”‚
                       └──► sync ──► GitHub issue  +  committed image copy  (readable with gh api)
  • capture / attach / record write to the store.

  • mcp-serve, dashboard, list, show read from it.

  • sync is the only thing that talks to a tracker, and only when you run it.

Status

Working. Roadmap items 1–5, 7 and 8 are implemented and tested, along with spec 002 (images, @ references, recording, live mode and the dashboard). S3/R2 object storage (item 6) and other trackers (item 9) are deferred. The Destination seam is in place, so they can be added without changing the CLI. See ROADMAP.md.

Installation

Requires Python 3.10 or newer. The core CLI uses only the standard library (plus tomli before Python 3.11). The MCP server is an optional extra.

pipx install 'bugcap[mcp]'   # recommended
uv tool install 'bugcap[mcp]'
pip install -e '.[dev,mcp]'                                             # development

Supported capture backends: flameshot (cross-platform, recommended), satty with grim (Linux/Wayland), and screencapture (macOS). Run bugcap setup to see what's detected. You can always import an existing image with bugcap capture --image PATH.

Documentation

Full guide: amenalahassa.github.io/bugcap/usage.html covers capture, images, recording, live mode, triage, @ references, the dashboard, GitHub pull and sync, MCP, and where data lives per OS.

Notes on the more involved behaviour:

  • References. In a note, @i1 is image 1, @v2 a video, @g3 an animated GIF, @f4 a frame set, @d5 an attached file (attach --file, any type), and @login-error a labelled item. #3 points at report 3 (a missing one is kept as text with a warning). Media references are validated on save, and relabelling or removing a referenced item needs --force.

  • Repo values (init, sync, config repo set) are checked for format and, with gh, for existence. Changing the repo identity offers to move existing reports.

  • Media sync over [sync] max_upload_mb (default 25) is skipped with a warning.

Contributing

Contributions are welcome. Read CONTRIBUTING.md for the workflow and project rules, and the Code of Conduct. Report security issues privately, see SECURITY.md.

Development

See DEVELOPMENT.md. Run the tests with:

uv run --extra dev --extra mcp pytest -q

Architecture

Module map (src/bugcap/):

Module

Responsibility

paths.py

Per-OS data/config dirs; BUGCAP_HOME override.

capture.py

Import or capture images (flameshot/satty+grim/screencapture); has_display().

backends.py

Capture-tool detection, per-OS install commands, manual guidance.

store.py

SQLite store (reports, media, media_frames; schema v2), PRAGMA user_version migrations, report API, transaction().

service.py

Shared rules used by the CLI, MCP, dashboard and live mode: media add/relabel/remove, notes validation, reference rewrite, queries. Raises ServiceError.

ingest.py

Path/glob/URL inputs: magic-byte validation, size/timeout/redirect limits, atomic copy into images/.

refs.py

@ reference parsing (code/email aware), validation, rewrite, display.

recorder.py

ffmpeg/wf-recorder argv per OS, stop/caps watchdogs, animated/frames post-processing.

live.py + live_session.py + drafts.py

Tk control window (thin) over a pure state machine; drafts (and the autosaved bug in progress) on disk.

screens.py + targets.py

Monitors and windows per OS (Win32 via ctypes, xrandr/wmctrl, wlr-randr/swaymsg), what each platform can capture, and the remembered capture target.

shortcuts.py + opener.py

Live mode's shortcut table (bindings, button hints, F1 help); opening a staged item in the OS default app.

dashboard/

http.server UI + JSON API (loopback, Host/Origin checks, write token, Range media, static allowlist).

repo.py + tomlio.py

.bugcap.toml discovery/read/write (tag, github slug, [sync]).

config.py

Global config.toml: [sync] defaults, [consent] for image commits, [log].

validation.py

Format checks for repo slugs, images path and branch names.

logs.py

mcp-serve logging (rotating file + stderr, never stdout).

ghcli.py

Thin gh wrapper (argv lists; large payloads via stdin). Transport.

sync.py

Destination protocol, GitHubDestination, pull_issues, sync_report. Policy.

agent_api.py

SDK-free tool logic for the six MCP tools.

mcp_server.py

Lazy-imports the mcp SDK; registers the agent_api tools over stdio.

cli.py

All subcommands.

The store is the one shared surface. Capture writes to it; the CLI, the MCP server, and the sync layer only read/update it β€” nothing talks to a tracker except sync.py (via ghcli.py), and nothing requires a tracker to exist for capture to be useful.

Extension seam (roadmap 6 & 9): sync.py depends only on the small Destination protocol (ensure_ready, repo_visibility, get_file, put_file, create_issue, comment, supports_attach) and on the report's synced_refs. A future object store or tracker implements that protocol β€” the CLI and store don't change. Refs are namespaced per destination:

  • github.issue β†’ owner/repo#N

  • github.comment_hash β†’ sha256 of the last synced content (so re-sync comments only on change)

  • github.image.<basename> / github.media.<basename> β†’ owner/repo:path@commit (so each file is committed at most once)

  • github.frame.<idx>.<n> and github.frames.<idx> β†’ keyframes of a recording (one commit per frame; GitHub's contents API commits one file at a time)

These refs also make pull and sync idempotent and resumable: each step is persisted as it succeeds, so a re-run skips what is already recorded.

Roadmap

See ROADMAP.md.

Design notes / deliberate non-goals

  • No cloud storage by default, no vendor account. The store is plain files on your disk. Sync (GitHub, and optionally an S3/R2 object store) is opt-in and explicit, per report.

  • Not a GitHub attachment replacement. The CDN-attached image stays for humans browsing the issue normally; the repo-committed copy exists purely so agents can read it. Both are written on sync, deliberately redundant.

  • Not using Git LFS for synced copies. GitHub's Contents API returns LFS pointer files, not the real bytes, for LFS-tracked paths β€” which would silently defeat the entire point of committing the copy. Plain commits are used instead; if screenshot volume ever outgrows that, the right next step is an external object store with its own token-authable download URLs, not LFS.

  • Annotation UI is not reinvented. bugcap is glue around an existing capture/annotate tool, not a new one.

License

MIT β€” see LICENSE.

Available Tools

7 tools
attach_fileAttach files to a reportA

Add files of any type (logs, stack traces, HAR captures, videos, configs) to a bug report as supporting evidence. Use attach_image for pictures so they are returned as images by get_report. Copies each file into bugcap's local store (URLs are downloaded) and appends it to the report; existing media is kept. Attached files are never uploaded to GitHub. Notes can then refer to a file as @d or @label. Returns {"added": [...], "rejected": [{source, reason}]}: one bad source does not stop the others.

NameRequiredDescriptionDefault
idYesNumeric report id, as returned by list_reports (e.g. 12).
labelsNoOptional short names, one per entry in `sources` and in the same order; use null to leave one unlabeled. A label lets notes refer to the item as @label.
sourcesYes1 to 20 files to add: local file paths, glob patterns (e.g. 'logs/*.txt') or http(s) URLs to download.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing that files are copied into a local store, URLs are downloaded, existing media is preserved, and nothing is uploaded to GitHub β€” important context given openWorldHint=true. It also documents partial-failure semantics ('one bad source does not stop the others'), which annotations never convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose and the sibling exclusion, then layers behavior. Dense but nearly every clause earns its place; the return-shape sentence partially duplicates the output schema, a minor redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and annotations covering safety profile, the description supplies the remaining essentials: storage behavior, GitHub exclusion, and partial-success handling. An agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema by explaining that labels let notes refer to items as @label and that failures are reported per source. It doesn't restate the 1-to-20 source limit or glob syntax, which the schema already covers.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Add files ... to a bug report as supporting evidence') and enumerates the file types accepted. It explicitly distinguishes itself from the sibling attach_image and its output target (get_report).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit routing rule: use attach_image for pictures so they are returned as images by get_report, implying this tool for everything else. The @d<n>/@label referencing note also tells the agent how attachments are consumed downstream.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

attach_imageAttach images to a reportA

Add existing images (PNG, JPEG, GIF or WebP) to a bug report, for example a screenshot you saved or a diagram from a URL. Use attach_file instead for logs, videos or other non-image files, and request_screenshot when the user has to take the picture. Copies each image into bugcap's local store (URLs are downloaded) and appends it to the report; existing media is kept. Notes can then refer to it as @i or @label. Returns {"added": [{index, label, kind, size_bytes, source}], "rejected": [{source, reason}]}: one bad source does not stop the others.

NameRequiredDescriptionDefault
idYesNumeric report id, as returned by list_reports (e.g. 12).
labelsNoOptional short names, one per entry in `sources` and in the same order; use null to leave one unlabeled. A label lets notes refer to the item as @label.
sourcesYes1 to 20 images to add: local file paths, glob patterns (e.g. 'shots/*.png') or http(s) URLs to download.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, openWorldHint=true), and the description adds real behavior beyond them: images are copied into a local store, URLs are downloaded, existing media is preserved, and partial failure is tolerated. It also discloses the reference convention (@i<n> or @label) that the agent needs for later note updates.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and alternatives, then behavior β€” good ordering with no filler sentences. Slightly over-packed because it spells out the full return JSON shape, which the output schema already provides.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With annotations covering safety, full schema coverage, and an output schema present, the description supplies everything else an agent needs: accepted formats, source kinds, mutation semantics, partial-failure behavior, and the labeling convention. Nothing required for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents id, labels and sources. The description still adds value by explaining how labels are consumed downstream (notes referring to @label) and that source failures are per-item rather than all-or-nothing, though it does not restate the 1-20 item or glob limits.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (add/attach) and resource (existing images) with the accepted formats and scope (into a bug report). It explicitly distinguishes itself from attach_file and request_screenshot, so an agent can pick correctly among siblings without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names both alternatives and the exact condition that selects each: attach_file for logs/videos/non-image files, request_screenshot when the user must take the picture. No exclusions are left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_reportGet a bug reportA
Read-only

Read one bug report in full: title, body, notes, status, tags, linked GitHub issue and the list of attached media, followed by every screenshot as image content so you can see it. Use this after list_reports to understand a bug before fixing it. Notes refer to media as @i1, @d1 or @label; resolved_references maps each of those tokens to its media index. Read-only and local. Returns {"error": ...} when no report has this id.

NameRequiredDescriptionDefault
idYesNumeric report id, as returned by list_reports (e.g. 12).

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds substantial behavioral detail beyond the readOnlyHint/openWorldHint annotations: screenshots are returned as image content, notes use @i1/@d1/@label references, resolved_references maps those tokens, and an {"error": ...} object is returned when the id is missing. It also states the tool is 'Read-only and local,' confirming the annotations rather than contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded with the core action and return contents, followed by the workflow hint and the token-mapping detail. Every sentence contributes useful information, and there is no redundant restatement of the title or schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although there is no output schema, the description explains the returned report fields, embedded image behavior, token-to-media mapping, and the error shape for a missing id. For a one-parameter read tool with readOnlyHint and openWorldHint=false annotations, this is complete enough to call correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 100% description coverage for the single id parameter, including its numeric type and example. The description adds only the missing-id error behavior, not additional syntax or format detail beyond the schema. Baseline 3 is appropriate when the schema already documents the parameter fully.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Read one bug report in full,' then enumerates exactly what is returned, including title, body, notes, status, tags, linked GitHub issue, attached media, and embedded screenshots. It also distinguishes the tool's role from list_reports by positioning this as the follow-up read after listing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear usage guidance: 'Use this after list_reports to understand a bug before fixing it.' This establishes the intended workflow and timing. It does not explicitly name when not to use it or mention alternative sibling tools such as request_screenshot, so it falls short of full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_reportsList bug reportsA
Read-only

List bug reports stored by bugcap, newest first. Use this to find a report id; it returns only summaries (id, title, status, tags, repo, created_at, linked GitHub issue) and no notes or images, so call get_report for the full report. Read-only and local: no network access. Returns a JSON array, empty when nothing matches.

NameRequiredDescriptionDefault
allNofalse (default): only reports filed for the repo the server runs in. true: every repo.
limitNoReturn at most this many reports, newest first.
statusNoKeep only reports with this status. Default: every status.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true and openWorldHint=false, and the description largely restates that ('read-only and local: no network access') rather than adding new safety facts. It does add genuinely new behavior, though: it enumerates the exact summary fields returned, warns that notes and images are omitted, and states that an empty JSON array is returned when nothing matches.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, front-loaded with the purpose, then the return shape, the alternative, and the safety note. Nothing is buried and no sentence is filler, aside from a mild restatement of read-only.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, yet the description still summarizes the returned summary fields and the empty-result case, and it points to get_report for full detail. Combined with full parameter coverage in the schema, an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all three parameters (all, limit, status) are already fully documented in the schema. The description only echoes the ordering implied by 'limit' ('newest first') and says nothing about the repo-scope flag 'all' or status filtering, so it adds little beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List bug reports stored by bugcap') plus ordering ('newest first'). It also carves out exactly what the sibling get_report does instead, so the agent can distinguish the two without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says the intended use is 'to find a report id' and names the alternative ('call get_report for the full report') with the condition that selects it (need notes/images). This is a clear when-to-use plus when-to-use-something-else routing statement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pull_issuesImport GitHub issuesA
Idempotent

Import open GitHub issues into bugcap as reports, so you can read them with get_report and attach screenshots to them. Use this when the bug you need lives in GitHub rather than in bugcap yet. Calls the GitHub API through the user's gh login. Safe to repeat: an issue that is already imported only has its title and body refreshed, never its notes, tags or status. Returns {"created", "updated", "unchanged"} counts, or {"error": ...} when no repo is given or configured, or gh is not signed in.

NameRequiredDescriptionDefault
repoNoGitHub repo as 'owner/name'. Defaults to the repo configured in .bugcap.toml.
limitNoMaximum number of issues to fetch (default 30).
labelsNoOnly import issues carrying all of these labels, e.g. ['bug'].

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: it discloses the auth dependency (GitHub API via the user's `gh` login), the precise idempotency semantics (existing imports refresh only title and body, never notes/tags/status), and the return/error shape including the no-repo and not-signed-in failure modes. The idempotentHint is confirmed and fleshed out rather than repeated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the action and scope in the first clause, then layers the when-to-use, auth mechanism, idempotency guarantee, and return shape in a tight sequence with no filler sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, prerequisites (gh auth, repo config), repeat-safety, and error conditions; an output schema exists but the description still summarizes the count/error shape, which is sufficient for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so repo fallback to .bugcap.toml, the limit default, and label AND-filtering are already documented in the schema. The description adds only the repo-default behavior, which is duplicative; limit and labels go unmentioned. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Import open GitHub issues into bugcap as reports") and immediately clarifies the resulting object type is readable via get_report, distinguishing it from the read-only siblings like list_reports and get_report.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit selection condition: "Use this when the bug you need lives in GitHub rather than in bugcap yet," plus the follow-on path (read imported issues with get_report, attach screenshots to them). That routes the agent between this importer and the report-reading siblings without inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

request_screenshotAsk the user for a screenshotA

Ask the human at the machine to take a screenshot (for example to show a bug, or to check a fix) and attach it to a report. Use this when you need visual evidence you cannot produce yourself; to attach an image file that already exists, use attach_image. Opens the user's capture tool and blocks until they finish, cancel or timeout_seconds passes. Adds the image to the report (and creates a report for issue if needed). Returns {"status": "captured", "report_id"} plus the screenshot as image content, or a status of "cancelled", "error" or "non_interactive" (no desktop available, e.g. over SSH or in a container) with a message.

NameRequiredDescriptionDefault
noteNoText appended to the report's notes and tied to the new screenshot, e.g. 'after the fix'.
issueNoGitHub issue to attach it to instead, as 'owner/repo#123' or '123' for the repo configured in .bugcap.toml. A report is created for the issue if none exists yet.
messageNoWhat you want the user to capture, shown to them before the capture tool opens.
report_idNoReport to attach the screenshot to. Give this or `issue`; this wins if both are set.
timeout_secondsNoHow long to wait for the user before giving up, in seconds (default 300).

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare safe non-destructive mutation; the description adds substantial behavior: it opens the user's capture tool, blocks until completion/cancel/timeout, may create a report for an issue, and lists exact return statuses including 'non_interactive' for SSH/container environments. That goes well beyond annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then usage, blocking behavior, side effects, and return values. Each sentence contributes distinct information and there is no repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers all the hard parts: blocking semantics, side effects, alternative tool, environmental failure mode, and return shape. With no output schema, the description fully explains outcomes.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all parameters are already documented in detail. The description adds only high-level references to timeout and report creation, which the schema already states; baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('ask the human... to take a screenshot') and explicitly distinguishes it from the sibling attach_image. Examples of when the resource is useful reinforce the purpose without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use it ('when you need visual evidence you cannot produce yourself') and names the alternative ('to attach an image file that already exists, use attach_image'). No inference required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_notesReplace a report's notesA
DestructiveIdempotent

Overwrite a bug report's notes with new text, for example to record a diagnosis, steps to reproduce or what a fix changed. The previous notes are replaced, not appended to: read them with get_report first and include whatever should be kept. Every @ reference must match media attached to the report; an unknown one is rejected with an error and nothing is saved. #12 links another report; one that does not exist is kept and listed in warnings. Local only. Returns {"report_id", "notes", "references", "warnings"}.

NameRequiredDescriptionDefault
idYesNumeric report id, as returned by list_reports (e.g. 12).
notesYesThe complete new notes, in Markdown. Refer to attachments as @i1, @d1 or @label.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint/readOnlyHint/openWorldHint, but the description still adds materially non-obvious behavior: replace-not-append semantics, atomic rejection on unknown @ references versus tolerant handling of unknown #report links, where warnings appear, and the 'Local only' constraint. It does not contradict any annotation β€” 'Local only' is consistent with openWorldHint=false.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense and front-loaded: the destructive semantics come first, followed by reference rules, then constraints. The only wasted sentence is the explicit return-shape listing, which duplicates the existing output schema and could be dropped.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers what an agent needs before a destructive overwrite: read first, what counts as a valid reference, atomicity on failure, and local-only scope. With an output schema present, the return-value recap is redundant but not misleading, and no call-critical gap remains.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the schema already documents id and notes including @i1/@d1/@label syntax, so the baseline is 3. The description adds real meaning beyond that: the @ must match media attached to the report, `#12` links another report, and invalid link handling is explained β€” but it never clarifies `label` resolution or whether `id` accepts anything other than the list_reports form.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource+scope: "Overwrite a bug report's notes with new text", then distinguishes the operation from its sibling by naming get_report for reading. The example use cases (diagnosis, repro steps, fix changes) pin down intent without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to get_report before calling and explains why (previous notes are replaced, not appended). It also states the consequence of a bad @ reference (rejected, nothing saved) versus a bad #report link (kept, surfaced in warnings), which is prescriptive guidance rather than bare description.

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.

  1. 7 tool updatesv0.7.2
    • Changedattach_file3 fields changed
      • addedInput schema / properties / id / description
        Added value: +"Numeric report id, as returned by list_reports (e.g. 12)."
      • addedInput schema / properties / labels / description
        Added value: +"Optional short names, one per entry in `sources` and in the same order; use null to leave one unlabeled. A label lets notes refer to the item as @label."
      • addedInput schema / properties / sources / description
        Added value: +"1 to 20 files to add: local file paths, glob patterns (e.g. 'logs/*.txt') or http(s) URLs to download."
    • Changedattach_image3 fields changed
      • addedInput schema / properties / id / description
        Added value: +"Numeric report id, as returned by list_reports (e.g. 12)."
      • addedInput schema / properties / labels / description
        Added value: +"Optional short names, one per entry in `sources` and in the same order; use null to leave one unlabeled. A label lets notes refer to the item as @label."
      • addedInput schema / properties / sources / description
        Added value: +"1 to 20 images to add: local file paths, glob patterns (e.g. 'shots/*.png') or http(s) URLs to download."
    • Changedget_report1 field changed
      • addedInput schema / properties / id / description
        Added value: +"Numeric report id, as returned by list_reports (e.g. 12)."
    • Changedlist_reports4 fields changed
      • addedInput schema / properties / all / description
        Added value: +"false (default): only reports filed for the repo the server runs in. true: every repo."
      • addedInput schema / properties / limit / description
        Added value: +"Return at most this many reports, newest first."
      • changedInput schema / properties / status / anyOf
        Previous value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "enum": [
        +      "open",
        +      "in-progress",
        +      "resolved",
        +      "closed",
        +      "wontfix"
        +    ],
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / status / description
        Added value: +"Keep only reports with this status. Default: every status."
    • Changedpull_issues3 fields changed
      • addedInput schema / properties / labels / description
        Added value: +"Only import issues carrying all of these labels, e.g. ['bug']."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum number of issues to fetch (default 30)."
      • addedInput schema / properties / repo / description
        Added value: +"GitHub repo as 'owner/name'. Defaults to the repo configured in .bugcap.toml."
    • Changedrequest_screenshot5 fields changed
      • addedInput schema / properties / issue / description
        Added value: +"GitHub issue to attach it to instead, as 'owner/repo#123' or '123' for the repo configured in .bugcap.toml. A report is created for the issue if none exists yet."
      • addedInput schema / properties / message / description
        Added value: +"What you want the user to capture, shown to them before the capture tool opens."
      • addedInput schema / properties / note / description
        Added value: +"Text appended to the report's notes and tied to the new screenshot, e.g. 'after the fix'."
      • addedInput schema / properties / report_id / description
        Added value: +"Report to attach the screenshot to. Give this or `issue`; this wins if both are set."
      • addedInput schema / properties / timeout_seconds / description
        Added value: +"How long to wait for the user before giving up, in seconds (default 300)."
    • Changedupdate_notes2 fields changed
      • addedInput schema / properties / id / description
        Added value: +"Numeric report id, as returned by list_reports (e.g. 12)."
      • addedInput schema / properties / notes / description
        Added value: +"The complete new notes, in Markdown. Refer to attachments as @i1, @d1 or @label."
  2. 7 tool updatesv0.1.0
    • First observedattach_file
    • First observedattach_image
    • First observedget_report
    • First observedlist_reports
    • First observedpull_issues
    • First observedrequest_screenshot
    • First observedupdate_notes

TDQS

A4.6/5.0

Scored across 7 tools

Disambiguation5/5

Each tool targets a distinct resource+action: listing vs reading reports, importing issues, requesting a screenshot, attaching images vs files, and updating notes. The only potentially confusable pair (attach_image/attach_file) is explicitly cross-referenced in both descriptions, and request_screenshot is clearly differentiated by requiring human action.

Naming Consistency5/5

All seven tools follow a consistent verb_noun snake_case pattern: list_reports, get_report, request_screenshot, pull_issues, attach_image, attach_file, update_notes. No deviations in style or casing.

Tool Count5/5

Seven tools is well-scoped for a bug-report capture server, and each tool earns its place in a distinct workflow step (browse, read, import, capture, attach, annotate). No redundant or filler tools.

Completeness3/5

Core read/import/attach/annotate flow is covered, but status and tags are surfaced in list/get yet no tool can set them, and there is no delete/remove-media operation nor an explicit create_report (only implicitly via request_screenshot). These triage gaps are notable dead ends for a bug-tracking domain.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    A local-first MCP server that gives AI coding agents runtime visibility and AI-managed debug logging. It replaces blind print() debugging by turning runtime execution into causal chains, allowing agents to instantly locate bugs by finding missing .success events in Python and TypeScript code. Single binary with MCP, CLI, and HTTP interfaces.
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    An MCP server that watches for screen recordings, transcribes spoken feedback locally, and attaches each comment to the relevant frame, enabling coding agents to see and fix the issues you mention.
    5
    MIT