Skip to main content
Glama

pyxel-mcp

Let AI agents play, watch, and measure Pyxel games. pyxel-mcp is an MCP server that runs a Pyxel script headlessly, feeds it scheduled input, stops when a condition holds, and hands back the facts: screenshots, pixel grids, game state, assets, audio, and frame diffs.

PyPI Python Tests License MCP Registry

Why

An agent can write a Pyxel game in seconds, but it cannot open a window, press the arrow keys, or look at the screen. Editor-bound engines solve this with MCP servers that live inside the editor. Pyxel has no editor process to attach to, so pyxel-mcp drives the game itself:

  • Headless execution. Every call runs the script in a fresh subprocess with SDL dummy drivers and a frame budget. Set random_seed to seed Python's random module and Pyxel's random generator. Other randomness, timing, and external state can still affect the frames.

  • Input as data. Buttons, axes, and mouse position are scheduled per frame, so a playtest is a JSON document the agent can rerun and extend.

  • Stop on the event, not the clock. until="score >= 1" ends the run at the first frame where a game attribute holds, and "frame": "end" snapshots capture that moment.

  • Facts, not scores. Tools report pixels, values, and measurements. Deciding whether the game is good stays with the agent and the person asking for it.

  • See the frame in the result. inline: true returns a PNG as MCP image content, so the model looks at the screen without a second file read.

Related MCP server: Aseprite MCP

Install

Register the stdio server with your client:

claude mcp add --scope user pyxel -- uvx pyxel-mcp
codex mcp add pyxel -- uvx pyxel-mcp
gemini mcp add pyxel uvx pyxel-mcp

For Cursor (~/.cursor/mcp.json), a project-scoped Claude Code .mcp.json, or any other client that reads the common JSON format, add:

   {
     "mcpServers": {
       "pyxel": {
         "command": "uvx",
         "args": ["pyxel-mcp"]
       }
     }
   }

VS Code uses .vscode/mcp.json with a top-level servers key and "type": "stdio"; Codex CLI can also be configured in ~/.codex/config.toml as [mcp_servers.pyxel]. Run uvx pyxel-mcp install to print every variant.

Claude Code users can instead install the pyxel-skill plugin, which registers this server together with the skill that teaches agents how to use it:

claude plugin marketplace add kitao/pyxel-skill && claude plugin install pyxel@pyxel-skill

Restart the client after changing its configuration. The server writes this diagnostic to stderr:

[pyxel-mcp] starting - 8 tools

Python 3.11+ is required, and Pyxel >= 2.9.6 is installed as a dependency. Script tools execute local Python in subprocesses to isolate Pyxel state, but they do not sandbox untrusted code. See SECURITY.md.

How an agent uses it

flowchart LR
    W["Write or edit<br>game.py"] --> V["validate"]
    V --> R["run<br>inputs · until · snapshots"]
    R --> O{"Inspect facts<br>state · pixels · log"}
    O -- "defect" --> W
    O -- "looks right" --> A["read_image · read_tilemap<br>read_audio · diff_frames"]
    A --> D["Report evidence"]

The loop is deliberately small. The separate pyxel-skill project teaches agents when to use each tool and what counts as enough evidence; this package only supplies the observations.

Tools

Every script argument is a file path, not Python source. Relative asset paths inside the script resolve from the script's directory, as when running python game.py from that directory.

Tool

Returns

validate

Syntax errors and recognizable Pyxel code patterns, without executing.

run

Headless frames, scheduled input, logs, and state, screen_image, screen_grid, or video snapshots.

pyxel_info

Installed versions, paths, bundled examples, and resource URIs.

read_palette

Palette colors and image-bank indices in use.

read_image

Image-bank pixels and an optional PNG render.

read_tilemap

Tile coordinates, source bank, usage counts, bounds, and an optional render.

read_audio

A rendered sound or music WAV plus measurable audio data.

diff_frames

Pixel differences between two PNG files.

All tools declare input and output schemas. Every result includes ok and errors.

Script tools observe the first pyxel.run() call while its enclosing resources remain active. run drives the callbacks there; the asset readers inspect the pre-loop state. pyxel.quit() ends a run normally and preserves completed frames. Statements after pyxel.run() are not executed. Enclosing cleanup runs after observation, and cleanup failures are reported with phase: "script_exit". Stopping uses internal BaseException signals. Scripts or context-manager cleanup that suppress these signals are unsupported and may execute post-run code.

Captured PNGs can travel inside the result: set inline: true on a screen_image snapshot, or inline=true on read_image and read_tilemap, and the PNG is returned as MCP image content next to the structured data. A single inline frame may omit its output path; the file is then written under the system temp directory and its path is still reported, so diff_frames and later comparisons keep working. At most 12 images are embedded per call.

Example

Hold right, jump at frame 25, stop as soon as the score changes, and look at that frame:

{
  "script": "/absolute/path/game.py",
  "frames": 600,
  "random_seed": 7,
  "inputs": [
    {"frame": 0, "buttons": ["KEY_RIGHT"]},
    {"frame": 25, "buttons": ["KEY_RIGHT", "KEY_SPACE"]},
    {"frame": 26, "buttons": ["KEY_RIGHT"]}
  ],
  "until": "score >= 1",
  "snapshots": [
    {"kind": "state", "frame": "end", "attrs": ["score", "player.x"]},
    {"kind": "screen_image", "frame": "end", "scale": 3, "inline": true}
  ]
}

The result reports until_met, the reached frame_count, the requested state values, the PNG path, and the PNG itself as image content. Artifact paths you choose must be absolute. Read log even when ok is true, and inspect captured images directly when appearance matters.

Resources

  • pyxel://run-snapshots-schema — complete run.snapshots grammar, including "end", ranges, and inline.

  • pyxel://validation-patterns — categories reported by validate.

  • pyxel://palette/default — default palette table.

  • pyxel://examples/{name} — source for an example bundled with the installed Pyxel package; discover names with pyxel_info.

Update

uvx caches packages. Force a refresh with:

uvx --refresh-package pyxel-mcp pyxel-mcp install

Troubleshooting

  • If tools do not appear, look for the starting - 8 tools diagnostic and restart the client.

  • If run fails, inspect errors, exit_status, and log.

  • If a script cannot find an asset, check the path relative to the script file, not to the client's working directory.

  • If a validation category is unfamiliar, read pyxel://validation-patterns.

  • Pyxel — the retro game engine this server observes.

  • pyxel-skill — the Agent Skill that turns these tools into a build-and-verify workflow.

  • CHANGELOG.md — what changed in each release.

MCP Registry

mcp-name: io.github.kitao/pyxel-mcp

License

MIT — see LICENSE.

Available Tools

8 tools
diff_framesA
Read-onlyIdempotent

Compare two PNG frames pixel by pixel and return their changed region and ratio.

ParametersJSON Schema
NameRequiredDescriptionDefault
frame_aYes
frame_bYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
ratioNo
errorsYes
regionNo
size_aNo
size_bNo
warningsNo
identicalNo
size_matchNo
total_pixelsNo
changed_pixelsNo

TDQS

A3.8/5.0
Behavior4/5

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 covered. The description adds behavioral detail: pixel-by-pixel comparison and the output of a changed region plus a ratio. This goes beyond the annotations without 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?

The description is a single, efficient sentence with no filler. It front-loads the core operation and the output, making it easy to scan and understand quickly.

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

Completeness3/5

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

An output schema exists, so return values do not need to be described. However, the missing input format details and lack of guidance on edge cases like mismatched image sizes make the description incomplete for confident invocation. It is adequate but has a clear gap.

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

Parameters2/5

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

The schema only defines two required strings with no format, and schema description coverage is 0%. The description identifies the parameters as 'PNG frames', which adds some meaning, but it does not clarify whether frame_a and frame_b are file paths, data URIs, raw byte strings, or something else. This leaves a critical ambiguity for the agent.

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 ('Compare'), identifies the resource ('two PNG frames'), and states the result ('changed region and ratio'). This clearly distinguishes it from sibling tools like read_image or run, which perform different operations.

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

Usage Guidelines3/5

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

The purpose implies when it should be used: whenever two PNG frames need to be compared. However, there is no explicit guidance about when to use this tool instead of alternatives, no exclusions, and no mention of prerequisites such as matching dimensions or format.

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

pyxel_infoA
Read-onlyIdempotent

Report installed versions, paths, examples, and Pyxel resource URIs.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
errorsYes
examplesNo
resourcesNo
stubs_pathNo
pyxel_versionNo
python_versionNo
pyxel_mcp_versionNo

TDQS

A4.2/5.0
Behavior4/5

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 fully covered. The description adds useful behavioral detail by specifying exactly what the tool reports, which is beyond what the empty input schema and annotations reveal.

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?

The description is a single sentence with the verb and key output categories front-loaded. Every word contributes meaning, and there is no redundancy or filler.

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

Completeness4/5

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

For a zero-parameter, read-only, non-destructive tool with an output schema and strong annotations, the description is sufficient for an agent to select and invoke it correctly. The only minor gap is the lack of explicit guidance about when to prefer it over sibling tools, but this does not hinder correct invocation.

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?

The tool has zero parameters, so the baseline of 4 applies. There is nothing for the description to explain about parameters, and the description correctly focuses on the tool's output rather than input semantics.

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 ('Report') and names an exact set of outputs: installed versions, paths, examples, and Pyxel resource URIs. This clearly distinguishes it from sibling read_* tools that target game assets such as palettes, images, tilemaps, and audio.

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

Usage Guidelines3/5

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

There is no explicit when-to-use or when-not-to-use guidance or mention of alternatives. However, the tool's purpose is strongly implied by its name and content: use it to introspect the Pyxel environment rather than to execute or validate game resources. The guidance is implicit, not explicit.

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

read_audioA

Render one Pyxel sound or music slot to WAV and return measurable audio data. Notes describe tracker fields, not an MML or PCM transcription.

ParametersJSON Schema
NameRequiredDescriptionDefault
scriptYes
targetYes
output_pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
pathNo
notesNo
errorsYes
channelsNo
warningsNo
sample_rateNo
peak_amplitudeNo
duration_secondsNo

TDQS

A3.5/5.0
Behavior3/5

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

The annotations provide only basic safety flags (readOnlyHint=false, destructiveHint=false), so the description carries the behavioral burden. It adds useful context about the output being WAV and measurable audio data, and clarifies that notes are tracker fields, but it does not disclose side effects such as whether output_path is overwritten or whether the operation has any state impact beyond file creation.

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?

Two front-loaded sentences with no filler. The first sentence states the core action and deliverable, and the second clears up a key interpretative trap without clutter.

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

Completeness2/5

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

With three required parameters, zero schema descriptions, and minimal annotations, the description leaves critical invocation details unexplained, particularly the meaning of 'script' and 'output_path'. Even though an output schema exists, the input side is too under-specified for an agent to call this tool correctly without additional context.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate, but it only hints at the target parameter via 'one Pyxel sound or music slot'. It gives no explanation for the required 'script' or 'output_path' parameters, leaving their roles and formats ambiguous.

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 names a specific verb and resource ('Render one Pyxel sound or music slot to WAV') and a clear deliverable ('return measurable audio data'), which distinguishes this audio-focused tool from siblings like read_image and read_tilemap. The clarifying clause about tracker fields further pins down its exact role.

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

Usage Guidelines3/5

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

Usage is implied by the audio-specific resource, but the description never states when to choose this tool over alternatives, nor does it name any sibling or exclusion. It lacks explicit 'use when' guidance, so an agent must infer applicability from the tool name and purpose.

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

read_imageA

Read palette-index pixels from a Pyxel image-bank region and optionally render it to PNG; inline=true returns the render as image content and makes render_path optional.

ParametersJSON Schema
NameRequiredDescriptionDefault
hNo
wNo
xNo
yNo
imageYes
inlineNo
scriptYes
render_pathNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
errorsYes
pixelsNo
regionNo
renderedNo
bank_sizeNo
color_countNo
image_indexNo

TDQS

A3.8/5.0
Behavior4/5

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

The description discloses a non-read-only side effect (optional PNG rendering) and explains that inline=true returns image content, going beyond the sparse annotations. This is consistent with readOnlyHint=false because rendering is a write-capable path.

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?

One compact, front-loaded sentence that puts the core read action first and then adds the conditional rendering behavior. No filler or redundant restatement of the tool name.

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

Completeness3/5

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

Covers the primary read/render flow and the inline behavior, and the output schema can handle return-value details. However, it does not explain the required script parameter or the coordinate-region semantics, so an agent must infer important calling details.

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

Parameters2/5

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

Adds meaningful semantics for inline and render_path by explaining their relationship, but leaves the required script parameter and the coordinate parameters x/y/w/h unexplained. With 0% schema description coverage, this is a substantial gap.

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 action: read palette-index pixels from a Pyxel image-bank region and optionally render to PNG. The resource ('image-bank region') and pixel-mode clearly distinguish it from sibling read tools like read_palette and read_tilemap.

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

Usage Guidelines3/5

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

Provides a clear condition for inline mode and render_path optionality, but gives no guidance on when to choose read_image over alternatives such as read_palette or read_tilemap. Tool-selection context is only implied by the purpose rather than stated.

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

read_paletteC

Read the active Pyxel palette and the palette indices used by image banks.

ParametersJSON Schema
NameRequiredDescriptionDefault
scriptYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
colorsNo
errorsYes
palette_sizeNo
used_indicesNo
extended_paletteNo

TDQS

C2.9/5.0
Behavior1/5

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

The description frames the operation as a read ('Read the active Pyxel palette'), but the annotations set readOnlyHint to false, which contradicts the clear read-only semantics of the description. It also sets idempotentHint to false for an operation that should be idempotent. This is an annotation contradiction, and the description adds no further behavioral context.

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?

The description is a single front-loaded sentence with no filler words; it names the action and the resource in the order an agent needs. It is concise without sacrificing the core object.

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

Completeness2/5

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

Although the tool is simple and an output schema exists, the description omits the meaning of the required 'script' parameter and does not clarify the exact relationship between the active palette and image-bank indices. Combined with the misleading annotations, the description is incomplete for reliable invocation.

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

Parameters1/5

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

The single required parameter 'script' has 0% schema description coverage, and the description does not mention or explain how 'script' relates to reading the palette. With no parameter details in the schema, the description fails to compensate.

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 action ('Read') on a specific resource ('active Pyxel palette and the palette indices used by image banks'). This distinguishes it from sibling tools like read_image, read_tilemap, and read_audio, so an agent can identify the tool's scope.

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

Usage Guidelines3/5

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

The description implies this tool is for retrieving palette data, but it does not explicitly state when to choose read_palette over read_image, read_tilemap, or read_audio, nor does it list exclusions or prerequisites such as needing a script.

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

read_tilemapA

Read Pyxel tile coordinates, usage, bounds, source bank, and optional rendered output; inline=true returns the render as image content and makes render_path optional.

ParametersJSON Schema
NameRequiredDescriptionDefault
inlineNo
scriptYes
tilemapYes
render_pathNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
sizeNo
tilesNo
usageNo
errorsYes
imgsrcNo
regionNo
renderedNo
tilemap_indexNo
zero_tile_usedNo
zero_tile_nonemptyNo

TDQS

A3.8/5.0
Behavior3/5

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

With all annotations false, the description carries the burden of behavioral disclosure. It explains the inline rendering behavior and the optional render_path, but does not clarify potential file-writing side effects when render_path is used, nor the meaning of 'source bank'. It adds some behavioral context but leaves important details implied.

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?

The description is a single dense sentence with no filler, front-loading the main action and then adding the conditional inline behavior. It is concise, though the semicolon-heavy structure and slight repetition of 'optional rendered output' vs 'inline=true' could be streamlined.

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

Completeness3/5

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

Given the output schema existshare, return-value documentation is not needed, and the description covers the tool's core purpose and inline mode. However, the required `script` parameter is unexplainedeing, and the behavior of render_path when inline=false is ambiguous. This is adequate but not complete for a 4-parameter tool with no annotation support.

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 0%, so the description must compensate. It explicitly explains the inline and render_path relationshipbell, and 'tilemap' is contextually clear. However, the required `script` parameter is not described at all, and the exact roles of `script` and `tilemap` as inputs are left to inference.

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 clearly identifies the resource (Pyxel tilemap) and lists specific data it reads: tile coordinates, usage, bounds, source bank, and optional rendered output. This is more specific than sibling read_* tools and leaves little ambiguity about the tool's function.

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?

The description gives a concrete usage condition: inline=true returns render as image content and makes render_path optional, which helps the agent decide between inline and path-based output. It does not explicitly name sibling alternatives or exclusions, but the context of reading tilemaps is clear enough.

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

runA

Run a Pyxel script headlessly for a frame budget or until a condition holds, with scheduled input and state, screen, or video capture. screen_image snapshots with inline=true also return the PNG as image content, and a single inline frame may omit its output path.

ParametersJSON Schema
NameRequiredDescriptionDefault
untilNo
framesYes
inputsNo
scriptYes
timeoutNo
snapshotsNo
random_seedNo
stall_window_framesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
logYes
errorsYes
seededYes
snapshotsYes
until_metNoTrue once `until` held, False when it was evaluated without ever holding, None when it was never evaluated.
exit_statusYesok includes reaching the frame budget, matching until, or an explicit pyxel.quit(). Cleanup failures are reported as crashed.
frame_countYesNumber of completed update/draw pairs; excludes a partial quit frame.
elapsed_secondsYes

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already indicate it is not read-only, not idempotent, and not destructive. The description adds useful details like the inline image behavior and headless execution, but it does not disclose the risk of executing arbitrary user code or potential side effects. The description partially adds behavioral context beyond annotations but misses key aspects.

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?

The description is concise (two sentences) and front-loaded with the core purpose. The second sentence adds a specific, non-obvious detail about inline images. It is efficient, though it could be slightly better organized with explicit sections for parameters and usage.

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

Completeness2/5

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

Given the high complexity (8 parameters, nested snapshot objects, discriminator), the description is far too brief. It does not explain the differences between snapshot types, the format of 'until' conditions, or the meaning of stall_window_frames. An agent would need to rely heavily on the schema and would likely struggle to construct valid requests.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate. It only offers a high-level overview (frame budget, condition, scheduled input, capture) but does not explain individual parameters like timeout, stall_window_frames, random_seed, or the snapshot request variants. This is insufficient for a complex tool with 8 parameters.

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 clearly states the verb (run), resource (Pyxel script), and context (headlessly, with frame budget or condition). It also mentions capture capabilities, which distinguishes it from the read/info sibling tools. This is specific and unambiguous.

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?

The description provides clear context on the tool's purpose (running scripts headlessly with capture) but does not explicitly mention alternatives or when not to use it. Given the sibling set (all read/info tools), the intended usage is fairly obvious, so this is a 4 rather than a 3.

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

validateA
Read-onlyIdempotent

Check Python syntax and report recognizable Pyxel code patterns.

ParametersJSON Schema
NameRequiredDescriptionDefault
scriptYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
errorsYes
issuesNo

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds valuable behavioral context by specifying that the tool performs syntax checking and pattern recognition, which implies a non-executing, analysis-only behavior. This goes beyond what annotations state, though it stops short of detailing exactly what patterns are recognized or how results are reported.

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?

The description is a single, front-loaded sentence with zero filler. It wastes no words and communicates the core action and focus immediately, making it easy for an agent to parse and act on quickly.

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

Completeness4/5

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

Given the tool has a single parameter and an output schema (which presumably documents the return structure), the description covers the essentials: what the tool does and on what input. It does not explain potential edge cases (e.g., handling of invalid syntax) but those are likely covered by the output schema. The description is sufficiently complete for a straightforward validation tool.

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 input schema has zero description coverage for its single parameter, so the description must convey parameter meaning. It does so by implication: the tool validates Python syntax, so 'script' is the Python code to be checked. However, it does not explicitly state that the parameter contains the source code, and gives no hints about expected encoding, length limits, or file references. This is adequate for a single simple parameter but not fully explicit.

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 states a specific verb ('Check') and a clear resource ('Python syntax' and 'Pyxel code patterns'), which precisely distinguishes it from sibling tools like 'run', 'read_palette', and 'read_tilemap' that perform execution or read operations. An agent can immediately understand this is a validation tool, not a runtime or read tool.

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

Usage Guidelines2/5

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

The description gives no explicit guidance on when to use this tool versus alternatives. It does not mention typical workflows (e.g., 'use before run'), nor does it reference any sibling tools, leaving the agent to infer usage context from the tool's name and purpose alone.

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. 1 tool updatev1.3.1
    • Changedrun2 fields changed
      • addedOutput schema / properties / exit_status / description
        Added value: +"ok includes reaching the frame budget, matching until, or an explicit pyxel.quit(). Cleanup failures are reported as crashed."
      • addedOutput schema / properties / frame_count / description
        Added value: +"Number of completed update/draw pairs; excludes a partial quit frame."
  2. 21 tool updatesv1.3.0
    • Removedcapture_frames
    • Removedcompare_frames
    • Addeddiff_frames
    • Removedinspect_bank
    • Removedinspect_layout
    • Removedinspect_palette
    • Removedinspect_screen
    • Removedinspect_sprite
    • Removedinspect_state
    • Removedinspect_tilemap
    • Removedplay_and_capture
    • Changedpyxel_info13 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "ExampleInfo": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "description": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Description"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "path": {
        +        "title": "Path",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "path"
        +    ],
        +    "title": "ExampleInfo",
        +    "type": "object"
        +  },
        +  "ToolErrorRecord": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "frame": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Frame"
        +      },
        +      "message": {
        +        "title": "Message",
        +        "type": "string"
        +      },
        +      "path": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Path"
        +      },
        +      "phase": {
        +        "title": "Phase",
        +        "type": "string"
        +      },
        +      "traceback": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Traceback"
        +      }
        +    },
        +    "required": [
        +      "phase",
        +      "message"
        +    ],
        +    "title": "ToolErrorRecord",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / additionalProperties
        Added value: +false
      • addedOutput schema / properties / errors
        Added value: +{
        +  "items": {
        +    "$ref": "#/$defs/ToolErrorRecord"
        +  },
        +  "title": "Errors",
        +  "type": "array"
        +}
      • addedOutput schema / properties / examples
        Added value: +{
        +  "items": {
        +    "$ref": "#/$defs/ExampleInfo"
        +  },
        +  "title": "Examples",
        +  "type": "array"
        +}
      • addedOutput schema / properties / ok
        Added value: +{
        +  "title": "Ok",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / python_version
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Python Version"
        +}
      • addedOutput schema / properties / pyxel_mcp_version
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Pyxel Mcp Version"
        +}
      • addedOutput schema / properties / pyxel_version
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Pyxel Version"
        +}
      • addedOutput schema / properties / resources
        Added value: +{
        +  "additionalProperties": {
        +    "type": "string"
        +  },
        +  "title": "Resources",
        +  "type": "object"
        +}
      • removedOutput schema / properties / result
        Removed value: -{
        -  "title": "Result",
        -  "type": "string"
        -}
      • addedOutput schema / properties / stubs_path
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Stubs Path"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "result"
        -]New value: +[
        +  "ok",
        +  "errors"
        +]
      • changedOutput schema / title
        Previous value: -"pyxel_infoOutput"New value: +"PyxelInfoResult"
    • Addedread_audio
    • Addedread_image
    • Addedread_palette
    • Addedread_tilemap
    • Removedrender_audio
    • Addedrun
    • Removedrun_and_capture
    • Addedvalidate
    • Removedvalidate_script
  3. 14 tool updatesv0.8.0
    • First observedcapture_frames
    • First observedcompare_frames
    • First observedinspect_bank
    • First observedinspect_layout
    • First observedinspect_palette
    • First observedinspect_screen
    • First observedinspect_sprite
    • First observedinspect_state
    • First observedinspect_tilemap
    • First observedplay_and_capture
    • First observedpyxel_info
    • First observedrender_audio
    • First observedrun_and_capture
    • First observedvalidate_script

TDQS

A3.7/5.0

Scored across 8 tools

Disambiguation5/5

Each tool maps to a distinct concern: environment info, script execution, audio rendering, frame comparison, and specific resource readers for images, palettes, and tilemaps. Even the read_* tools are cleanly separated by resource type, so there is no meaningful overlap between them.

Naming Consistency4/5

Most tools follow a clear action_resource pattern, especially read_image, read_palette, read_tilemap, and read_audio. The deviations are minor: pyxel_info is noun-ish and run is a bare verb, but both are still understandable and do not undermine the overall scheme.

Tool Count5/5

With 8 tools, the surface is tightly scoped to running Pyxel scripts and inspecting Pyxel resources and output. No tool feels redundant or out of place, and the count is well within the ideal range.

Completeness4/5

The server covers a coherent inspect-and-run workflow: validate scripts, execute them, capture frames, diff frames, and read images, palettes, tilemaps, and audio. The main gap is the lack of tools for creating or modifying Pyxel resources, which is a workaround if the server is intended as a read-only/testing interface.

Maintenance

ActivityNo data
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers