Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

shotbox

PYPI · SHOTBOX

Sealed X11/Wayland sessions to see, drive and check real GUI programs: a11y, pictures, sound.

Available components

+16 this week 78 Trust /100

Last scanned (6 hours ago)

Scores higher than 74% of PyPI servers

Category Browser Automation

Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security100
  • No malware found by supply-chain analysis.Pass
  • No known CVEs affecting this package version or its production dependencies.Pass
  • Runs setuptools.build_meta at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
  • No production dependencies, so there is no dependency health to assess. View diagnostics → Pass
Provenance & Transparency100
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to mishan/shotbox). View diagnostics → Pass
  • Clear OSI-approved license (MIT).Pass
  • Actively maintained (last published 0 days ago).Pass
  • Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability57
  • AI-judged instruction clarity (good).Pass
  • Context-footprint check failed: tool/resource definitions use about 5243 tokens (~275/item across 19 items; 19 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management0
  • Stability check failed: the tool surface changed between 0.6.0 and 0.10.0: 12 tool removals, 0 breaking changes, 14 additions. See how to fix → Fail
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • We read all 19 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
  • An AI judge read all 20 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a current MCP spec version (2026-07-28).Pass
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 24 Oct 26 +15
    • Malware scan: unverified → pass ▲ security
  • 23 Oct 26 −16
    • Malware scan: pass → unverified ▼ security
    • Schema quality: 236 → 275 ▼ functional
    • Package version: 0.9.0 → 0.10.0 functional
  • 20 Oct 26 +15
    • Malware scan: unverified → pass ▲ security
  • 19 Oct 26 −15
    • Malware scan: pass → unverified ▼ security
    • Package version: 0.8.0 → 0.9.0 functional
  • 18 Oct 26 +17
    • Stability: 0.03 → unverified ▼ security
    • Tool safety: pass → unverified ▼ security
    • Stability: 0.03 → fail ▼ security
    • Malware scan: unverified → pass ▲ security
    • Schema quality: 202 → 234 ▼ functional
    • Capabilities: fail → unverified ▼ functional
    • Tool coverage: 100 → unverified ▼ functional
    • MCP protocol: fail → pass ▲ functional
    • Security disclosure: fail → pass ▲ functional
    • First check of Schema quality: unverified functional
    • Package version: 0.7.1 → 0.8.0 functional
  • 17 Oct 26 +2
    • Tool safety: pass → unverified ▼ security
    • Malware scan: unverified → pass ▲ security
    • Stability: Stability not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet. security
    • Schema quality: 183 → 202 ▼ functional
    • Schema quality: 183 → 208 ▼ functional
    • Capabilities: fail → unverified ▼ functional
    • Tool coverage: 100 → unverified ▼ functional
    • Tool coverage: 56% → 100% ▲ functional
    • Stability: unverified → 0.03 ▲ functional
    • First check of Schema quality: unverified functional
    • Package version: 0.6.0 → 0.7.1 functional
    • Package version: 0.6.0 → 0.7.0 functional
  • 16 Oct 26 60

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 24 Oct 2026 · Analysed pypi/shotbox@0.10.0

Provenance Verified

A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.

Result Verified
Ecosystem pypi
Reason Verified
Discovered via Registry attestation endpoint
Source repo mishan/shotbox
Certificate issuer https://token.actions.githubusercontent.com
Certificate SAN https://github.com/mishan/shotbox/.github/workflows/release.yml@refs/tags/v0.10.0
Rekor log index 3420709888
Predicate type PyPI publish attestation https://docs.pypi.org/attestations/publish/v1
Subject digest sha256:5529374481e2b9d7d386fec7fc6aa6caeb9639cbb12aa02ea72a87b63161f4c6

Background: How many MCP packages publish verified provenance →

Install scripts 1 script
Hook Tier Command
build_backend allowlisted setuptools.build_meta

Background: Why install scripts are a supply-chain risk →

Dependencies 0 packages
Packages resolved 0
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 19 exposed · ~4,986 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
check_accessible_names ~139

Lint the accessibility tree for nodes a screen reader has no name to say for: controls, images (not inside a named control) and anything else that takes the focus. The answer: a tree line each, with bounds, then what's wrong; or "No problems.". Use it to check labels after a change; for colors, use check_contrast.

NameTypeReqDescription
ignorearray–Regexes for lines that can't be fixed yet
sessionstringyesIts name, from start_session
windowstring–A window's title, exactly or a regex matched in full, or app=RE for its app id

No output schema declared.

No examples provided.

check_contrast ~363

Check that text, buttons, links and images stand out from their background: WCAG's 4.5:1 for text (3 for large text) and 3:1 for images unless text_ratio and graphics say otherwise, and with edges, a button's or field's edge too. It raises the window and measures a picture of the screen in each node's bounds. The answer: each node that fails, a tree line with bounds, its ratio and colors, or "No problems."; with passes, then each that passes, the same; then what it couldn't measure, which doesn't fail unless strict (too small, off the screen, or GTK 4.14+'s, whose positions are wrong: of that, only text is measured, where it's found near them), then what's behind a modal dialog, not measured, which doesn't fail even with strict (check it with the dialog closed), and why. A window where nothing can be measured is an error, not a pass. Switches, sliders, check boxes, disabled nodes and what's scrolled out of view are skipped. For missing names, use check_accessible_names.

NameTypeReqDescription
edgesnumber–Least for edges (unchecked)
graphicsnumber–Least for images (3)
ignorearray–Regexes for lines that can't be fixed yet
passesboolean–Also what passes, with its ratio
sessionstringyesIts name, from start_session
strictboolean–What it couldn't measure fails too
text_rationumber–Least for text (4.5)
windowstring–A window's title, exactly or a regex matched in full, or app=RE for its app id

No output schema declared.

No examples provided.

check_focus_order ~349

Check the keyboard focus order in one call: press Tab, or key, until the focus comes back round, and list where it went, a tree line each, after a "began in" line. Then the controls the key never reached, and how it ended: round again (fine), stuck (a trap, or a text view nothing leaves), not round after most presses, lost (no node has the focus), stopped (a text view closed as it was left), never in the page (with document, a page with controls), left the page (a web editor that keeps Tab, left by F6, and Tab never back), or nothing focused to begin with (click the window with click_element first). With visible, "focus not shown on N" counts stops that don't show it. A text view that takes Tab is left as a person would, with ctrl+Tab, shift+Tab, Escape or F6. The focus stays where it ended. To press a few keys yourself, use press_keys.

NameTypeReqDescription
documentboolean–Only what's in a browser window's web page: Tab still goes through the browser's own controls, but they aren't listed
ignorearray–Regexes for unreached controls to leave out
keystring–The chord to press (Tab)
mostinteger–Presses at most (50)
sessionstringyesIts name, from start_session
visibleboolean–Also check each place it lands shows it has the focus
windowstring–A window's title, exactly or a regex matched in full, or app=RE for its app id

No output schema declared.

No examples provided.

click_element ~503

Click an element by its accessible name, or a point by x and y, on the screen or inside a window. By name is the one to use: it waits up to timeout seconds for the node to show, be placed and enabled, hold still and be uncovered (else it says which it isn't), raises its window and clicks its middle, and the answer gives the node and its bounds. When two nodes match it lists them, with where they are; when none does, the nearest names. A click gives a window the keyboard, which nothing else does on X11. hold and state, by x and y, hold the button as press_keys holds keys.

NameTypeReqDescription
actionstring–By name, do the node's accessible action of this name in place of a click, for a node a click won't reach. Its names and what they do are its toolkit's: a click that can't place a node lists them, as…
buttoninteger–1 left, 2 middle, 3 right
changesboolean–Also say what this changed in the accessible tree once the screen holds still (not a field's text, nor where things are): tree lines, + added, - gone, ~ changed
doubleboolean–Click twice, as a double click
forceboolean–By name, don't wait for the node to be enabled, still and uncovered (with action, enabled): to check a disabled one does nothing
holdnumber–Seconds to keep it down before letting go
namestring–A node's name, as get_accessible_tree gives it: exactly, or a regex matched in full
rolestring–Narrows name: exactly, or a regex
sessionstringyesIts name, from start_session
statestring–Only press, leaving it down until a call with up; or only let go
timeoutnumber–By name, seconds to wait for the node (10)
windowstring–A window's title, exactly or a regex matched in full, or app=RE for its app id
xinteger–Pixels from the left: of the window, with window
yinteger–Pixels from the top: of the window, with window

No output schema declared.

No examples provided.

get_accessible_tree ~159

Read what a screen reader would find: every visible node, a line each, indented, with its role, name, description and the states a screen reader says (focusable, focused, checked...). The cheapest way to see what's on screen and what can be clicked by name. A node with an empty name ("") is one a screen reader can say nothing for. Use take_screenshot for how it looks.

NameTypeReqDescription
boundsboolean–Add @x,y WIDTHxHEIGHT to each line, in click_element's x,y
sessionstringyesIts name, from start_session
windowstring–A window's title, exactly or a regex matched in full, or app=RE for its app id

No output schema declared.

No examples provided.

get_program_output ~141

Read the last lines (40, or lines) a spawned program wrote to stdout and stderr, after a line saying whether it's still running or exited, with its status. It works after the program has exited, until the session stops; for a program spawned more than once, it reads the latest. Use it when a window never comes up or a program seems to have crashed; to wait for a line in a log file, use wait_for line.

NameTypeReqDescription
linesinteger–How many lines from the end (40)
programstringyesIts name in the allow list
sessionstringyesIts name, from start_session

No output schema declared.

No examples provided.

get_speech ~189

Hear what Orca, a real screen reader, says as the focus moves: it starts Orca in the session, presses Tab until the focus comes round (or keys, in turn), and answers a (start) line, then a line a press: the focused node's tree line, then what Orca said. Tab stops before a text view, which would take it as typing. Use it over get_accessible_tree when what's heard matters (labels, mnemonics, states, silent stops). Orca takes seconds to start.

NameTypeReqDescription
keysarray–Chords to press in turn, instead of Tab
mostinteger–Tab presses at most (50)
sessionstringyesIts name, from start_session
windowstring–A window's title, exactly or a regex matched in full, or app=RE for its app id

No output schema declared.

No examples provided.

list_announcements ~138

List what programs in the session have announced to a screen reader since it started, oldest first, a line each with its politeness: "polite: Saved", "assertive: Error". That's GTK's announcements, a browser's live regions, alerts and info bars as they appear (GTK 3's, Qt's, libadwaita's) and the focus renamed. Reading doesn't clear them; "Nothing announced yet." means none so far. Use it to check what a screen reader user heard after an action; to wait for one, use wait_for announcement.

NameTypeReqDescription
sessionstringyesIts name, from start_session

No output schema declared.

No examples provided.

press_keys ~211

Press keys in turn, each a chord: Tab, Return, Escape, ctrl+s, alt+shift+Tab, F6. They go to whatever has the keyboard; click a window first with click_element if nothing does. hold presses them all together and keeps them down that long (walking while running); state down leaves them down, across calls, until a call with state up (move or click while a key is held). The answer says what it pressed.

NameTypeReqDescription
changesboolean–Also say what this changed in the accessible tree once the screen holds still (not a field's text, nor where things are): tree lines, + added, - gone, ~ changed
holdnumber–Seconds to keep it down before letting go
keysarrayyesChords, pressed one after another
sessionstringyesIts name, from start_session
statestring–Only press, leaving it down until a call with up; or only let go

No output schema declared.

No examples provided.

record_audio ~173

Record a session's sound and say how it was: call with action start, have the program play, then call with action stop. The session must have been started with audio. stop answers with the sound's length, its peak and RMS level in dBFS, the samples clipped, and each gap of silence between the first sound and the last (what a program that falls behind leaves), then any problem found. The sound itself isn't returned or kept; to keep it, use record_video with sound. Raise gap when the program is meant to fall silent between sounds, as between two beeps.

NameTypeReqDescription
actionstringyesstart, then stop
gapnumber–The shortest silence, in milliseconds, reported as a gap (1)
sessionstringyesIts name, from start_session

No output schema declared.

No examples provided.

record_video ~323

Record a video of the screen, or of one window, and save it as an .mp4: in the session's scratch directory, gone when the session stops, or at path. The answer is the saved path, how long the clip is, and up to 8 frames from it RETURNED AS ONE IMAGE, with the times they show: you can't play the clip, but a person or another tool can. A clip stops at 100 MB. sound also says what it heard, as record_audio does. until_line ends it at an event instead; the answer gives the line. For a few moments of motion, take_screenshot's burst is cheaper.

NameTypeReqDescription
cropstring–WIDTHxHEIGHT+X+Y, inside what's taken
filestring–until_line's, by its path from the allow file's directory
pathstring–Where to save it, a new .mp4, by its path from the allow file's directory
secondsnumber–How long; with until_line, the most (60)
sessionstringyesIts name, from start_session
soundboolean–What plays too, in a session started with audio
tailnumber–Seconds to go on after the line (0)
until_linestring–A regex: stop tail seconds after a line matching it is written to file
windowstring–A window's title, exactly or a regex matched in full, or app=RE for its app id

No output schema declared.

No examples provided.

scroll_wheel ~313

Turn the mouse wheel over a node by its name, found as click_element finds it (waiting for it, its window raised), or at a point by x and y, leaving the pointer there. Use it for what's past a list's, a page's or a window's edge, then wait_for stable and look again; to move the keyboard focus, use press_keys.

NameTypeReqDescription
changesboolean–Also say what this changed in the accessible tree once the screen holds still (not a field's text, nor where things are): tree lines, + added, - gone, ~ changed
dxinteger–Clicks right; negative, left
dyinteger–Clicks down; negative, up
forceboolean–By name, don't wait for the node to be enabled, still and uncovered (with action, enabled): to check a disabled one does nothing
namestring–A node's name, as get_accessible_tree gives it: exactly, or a regex matched in full
rolestring–Narrows name: exactly, or a regex
sessionstringyesIts name, from start_session
windowstring–A window's title, exactly or a regex matched in full, or app=RE for its app id
xinteger–Pixels from the left: of the window, with window
yinteger–Pixels from the top: of the window, with window

No output schema declared.

No examples provided.

spawn_program ~95

Start one of the programs the person allowed this server to run, by its name, in a session; nothing else can run. The answer gives its pid. Then wait_for its window, by the program's name, before looking at it. If it doesn't come up, get_program_output says why.

NameTypeReqDescription
programstringyesIts name in the allow list
sessionstringyesIts name, from start_session

No output schema declared.

No examples provided.

start_session ~419

Start a sealed session: a display of its own (X11 under Xvfb, or Wayland under a headless sway), its own D-Bus and accessibility bus, and a scratch home. Nothing in it reaches the desktop of the person you're working for, and nothing of theirs reaches it. The answer gives its name, display and size, the programs spawn_program can start in it, and anything it couldn't seal. It lasts until stop_session.

NameTypeReqDescription
a11yboolean–An accessibility bus (default true)
audioboolean–A sound server whose sink plays to nowhere
clockstring–ISO 8601, 2026-09-26T18:40:00, in tz or UTC: where its wall clock starts and runs on from, so dates in pictures don't change (needs libfaketime)
darkboolean–GTK and libadwaita's dark style
gamepadsinteger–Virtual Xbox 360 pads, for use_gamepad
high_contrastboolean–Their high contrast style
identitystring–USER@HOST: who and where its programs are, for whoami, hostname, ls -l and $USER
namestring–What to call it (s1, s2... by default)
netstring–A network its programs share and nothing else is on: nothing reaches in or out
screenstring–WIDTHxHEIGHT (1280x800), up to 7680x4320
text_scalenumber–Their text size, 1.25 for 125%
tzstring–Its time zone, Europe/Berlin (UTC)
usageboolean–Say, when it's stopped, what its programs used: peak memory and CPU time
waylandboolean–Wayland, not X11
xwaylandboolean–Wayland, with Xwayland for X programs

No output schema declared.

No examples provided.

stop_session ~105

Stop a session start_session made, when you're done with it: every program in it is killed, unsaved work and all, and its scratch directory is deleted, with any clip record_video saved there (one saved at a path is kept). In a session started with usage, the answer says its programs' peak memory and CPU time. You needn't stop sessions before the server ends: they all stop with it.

NameTypeReqDescription
sessionstringyesIts name, from start_session

No output schema declared.

No examples provided.

take_screenshot ~373

Take a picture of the screen, or of one window, RETURNED AS AN IMAGE for you to look at: the only way to see colors, layout and what's drawn. Pictures cost far more than get_accessible_tree; take the window rather than the screen, and crop when you need a part; zoom enlarges one to read small text. vision checks nothing is told apart by color alone; burst, as one image, is for motion, an animation or a transition. labels numbers each named node's box on it, to click by name what you see. The answer gives its size, if it's scaled or a part how an x,y on it maps to click_element's, and with labels each number's tree line.

NameTypeReqDescription
burstinteger–Pictures to take
cropstring–WIDTHxHEIGHT+X+Y, cut to what's taken
everynumber–With burst, seconds between them
labelsboolean–Number each named node's box on it, and list each number's tree line
parkboolean–Move the pointer away first, so nothing shows its hover
sessionstringyesIts name, from start_session
visionstring–protanopia (no red cones), deuteranopia (no green), tritanopia (no blue), or gray (no color)
windowstring–A window's title, exactly or a regex matched in full, or app=RE for its app id
zoomarray–[x0, y0, x1, y1]: a region's corners in click_element's x,y (a picture's, mapped as its answer says), shown as large as fits, up to 8 times; not with crop or burst

No output schema declared.

No examples provided.

type_text ~124

Type text into whatever has the keyboard focus, a key at a time. ASCII only: a character with no key fails the call, once what's before it is typed. For keys and shortcuts (Return, ctrl+s), use press_keys.

NameTypeReqDescription
changesboolean–Also say what this changed in the accessible tree once the screen holds still (not a field's text, nor where things are): tree lines, + added, - gone, ~ changed
sessionstringyesIts name, from start_session
textstringyesThe text to type

No output schema declared.

No examples provided.

use_gamepad ~287

Work a virtual gamepad, in a session started with gamepads: press buttons together, tapped, held for hold seconds, or with state down left down until a call with state up; push a stick to x, y; pull a trigger to value; or neutral, letting go of everything. A stick or trigger stays where it's put, unless hold says for how long. Programs in the session see a real Xbox 360 controller, and none of the machine's. For keys and the mouse, press_keys and click_element.

NameTypeReqDescription
actionstringyesPress buttons, push a stick, pull a trigger, or let go of everything
buttonsarray–a b x y lb rb back start guide ls rs, and the d-pad's up down left right
holdnumber–Seconds to keep it down before letting go
padinteger–Which of the session's pads (1)
sessionstringyesIts name, from start_session
statestring–Only press, leaving it down until a call with up; or only let go
valuenumber–The trigger, let go to pulled all the way
whichstring–Which stick or trigger
xnumber–The stick, left to right
ynumber–The stick, up to down

No output schema declared.

No examples provided.

wait_for ~582

Wait until something is so, instead of sleeping; it fails after timeout seconds, saying so, and listing the windows there are when a window never came. what says what to wait for, and value which: window: a title, exactly or as a regex, app=RE, or the name a program was started by with spawn_program, for its window whatever its title; answers with the window's title, size and place. stable: the screen (or window) unchanged for value seconds (0.5; up to 60), as after a click, for the repaint. announcement: a regex in what was announced to a screen reader; each is waited for once. focus: the name of the node with the keyboard focus, as click_element takes one; answers with its tree line. node: a regex in the name or text of a node showing in the accessible tree, as a status line saying a page is drawn, where the screen holding still says nothing; answers with its tree line, and its text if that matched. match: a PNG's path, from the allow file's directory, that the screen (or window, cropped to crop) should look like; answers how long it took. change: any change from how it looked when the wait began; answers how long it took. line: a regex in a line of file written after the wait starts (or, with from_start, anywhere in it), for a program that logs its events; a file not there yet is waited for, and one rotated or rewritten is read from the top; answers with the line. To see how things are now, without waiting, use get_accessible_tree.

NameTypeReqDescription
cropstring–WIDTHxHEIGHT+X+Y, inside what's taken
filestring–line's, by its path from the allow file's directory
from_startboolean–line: anywhere in file
fuzznumber–match, change: percent a pixel may differ by (0)
ignorearray–match, change: boxes of the picture to leave out, as a clock or a cursor, each WIDTHxHEIGHT+X+Y
margininteger–match, with crop: pixels the picture may be from the crop's place each way, up to 32; answers where it matched (0)
mostinteger–match, change: pixels past fuzz allowed (0)
sessionstringyesIts name, from start_session
timeoutnumber–Seconds before it fails (10)
valuestring–What to wait for, as what says
whatstringyesThe kind of wait
windowstring–A window's title, exactly or a regex matched in full, or app=RE for its app id

No output schema declared.

No examples provided.

Install

How do I install the shotbox MCP server?

shotbox runs locally as a PyPI package, launched with uvx shotbox. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

pypi · shotbox

# add to Claude Code
claude mcp add mishan-shotbox -- uvx shotbox
Common questions

What is the shotbox MCP server?

shotbox is an MCP server listed in the public MCP registry as io.github.mishan/shotbox. Sealed X11/Wayland sessions to see, drive and check real GUI programs: a11y, pictures, sound. This page covers its PyPI package (shotbox).

Is the shotbox MCP server safe to use?

shotbox scores 78 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 24 October 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the shotbox MCP server expose?

shotbox exposes 19 tools: start_session, stop_session, spawn_program, get_program_output, get_accessible_tree, and 14 more. Their descriptions and schemas cost roughly 4,986 tokens of context every time the server is loaded.

Is the shotbox MCP server still maintained?

shotbox is still listed as active in the MCP registry. We last reached this channel on 24 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the shotbox MCP server under?

shotbox declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.