MarketCanvas-Env MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MarketCanvas-Env MCP ServerLoad the 'Covered headline' example and tell me the current reward."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MarketCanvas-Env
A standalone Python design-canvas simulator with a local inspector, an RL-style API, an optional Gymnasium adapter, and an official-SDK MCP server. No model, API key, external data, or training run is required.
Start here
Read WRITEUP.md or its two-page PDF for the assignment response. The optional companion research paper reports the human study with embedded consistency checks and exploratory reward fitting.
For a new checkout, follow Fresh installation below before running the demo or inspector.
Related MCP server: engineering-bridge
Try it locally
After installation, run from this directory:
.venv/bin/python playground.pyOpen http://127.0.0.1:8765/. The inspector initially shows a valid reference banner. Try:
Choose White text on yellow CTA and click Load example. Reward should fall from
1.000to-0.020.Select element e3 · cta · shape, set Text color to
#172033, and click Apply edit. Reward returns to1.000.Click Submit design. The episode ends and delivers its terminal reward once.
Try Covered headline, Clipped headline, Duplicate CTA, or Unrelated extra text (known limitation).
Use Start blank to design manually. Add elements and assign a role with the role selector. Required headline type is
text; CTA type isshape.
Fill and text colors each offer named presets, a color preview, and an editable six-digit hex code. For example, #000000 is black, #FFFFFF is white, and #FFFF00 is yellow. Choose Apply edit to commit a color change. Text can use No fill; shapes and image placeholders require a fill.
The controls invoke the actual Python environment. The canvas image is rendered by Pillow, not a separate browser approximation. The inspector and stdio MCP server use the same code but own separate episodes. Stop the inspector with Ctrl+C. To use a different port: python playground.py --port 8766.
Loaded examples start at 0/40, including examples with a prepared defect. Their setup actions are recorded separately and do not consume your edit budget. Every edit attempt and submission then consumes one action. Inspector trajectory downloads contain initial_observation, setup_actions, and transitions in a versioned JSON object, so even an untouched example can be replayed. replay.py also accepts the original JSON-array and JSONL exports. The scripted construction demo still counts its own construction actions because it deliberately builds from blank.
Fresh installation
Use Python 3.12 or later; this version was tested on Python 3.12.14, macOS arm64. From the project directory:
python3.12 -m venv .venv
.venv/bin/python -m pip install -r requirements.lock.txtAlternatively, use uv venv --python 3.12 then uv pip install -r requirements.lock.txt.
A fresh environment and clean source copy passed 74 tests (one private-data integration check skipped), the demo, replay, and public-data research reproduction. See verification details. The lock records the exact tested package versions; other operating systems have not been tested. The bundled DejaVu font has its original license in marketcanvas/assets/.
Demo, experiments, and tests
.venv/bin/python demo.py
.venv/bin/python demo.py --headline "Weekend Offers" --cta "Explore offers"
.venv/bin/python replay.py results/demo/trajectory.jsonl
.venv/bin/python experiments.py --seeds 12
.venv/bin/python reward_comparison.py --seeds 12
.venv/bin/python aesthetic_comparison.py
.venv/bin/python -m pytest -qdemo.py generates its mock prompt from explicit constraints, builds a banner, introduces poor contrast, repairs it, submits, and prints state and reward. Outputs include before/after PNGs, final state and evaluation, and a JSONL trajectory.
The experiment report is results/experiments/REPORT.md, with raw CSVs, per-condition JSON and PNGs, a visual comparison sheet, and measured local timings. These are tests of the evaluator, not LLM performance results. Re-running overwrites generated files in the chosen output directory; use --output to retain another run.
Two separate, offline reward studies preserve the original live reward:
Graded-reward comparison: remove only the validity cap, measure contrast-repair sensitivity, and expose invalid high-scoring designs. Includes a replayable repair trajectory and separately logged alternative scores.
Aesthetic-rule pilot: add a headline-size hierarchy rule while retaining the cap, inspect six score-hidden designs, and test counterexamples and parameter sensitivity. Includes a blank review form; no human ratings are claimed.
The alternative evaluators are evaluate_uncapped(state) and evaluate_hierarchy(state) in marketcanvas/reward_variants.py. They do not mutate episodes or change the reward delivered by the playground, MCP, or Gymnasium adapter. A future trainer must explicitly select and version its terminal evaluator. Neither is a globally continuous or validated measure of marketing effectiveness.
Viewer research pilot
.venv/bin/python viewer_pilot.py
.venv/bin/python rating_server.pyOpen http://127.0.0.1:8766/ for twelve score-hidden design pairs. Rate CTA discoverability and overall preference separately. Choices save locally; notes save on leaving the field or using Save progress. You can resume after reloading. Finishing explicitly reveals the predictions and locks ratings. The canvas inspector on port 8765 retains its own scene and original reward.
The builder freezes stimuli, parameters, predictions, relevant source and documentation in results/viewer-pilot-v1/. Re-running verifies this pack rather than replacing it. New hypotheses require a new study directory and separate responses. Personal ratings live in private/viewer-pilot-v1/ratings.json, excluded from Git. Completed analysis is generated in the adjacent analysis/ folder and is also shown in the rating page. No human results are claimed before completion.
Read the completed research paper and full viewer method. Reproduce the reported results with python reproduce_research.py; see research/README.md. The principal follow-up uses embedded_pilot.py --serve on port 8768: 12 new pairs plus six embedded checks, with repeats excluded from primary agreement. The pure Python alternative is marketcanvas.viewer.evaluate_viewer(state). The model predicts early region inspection, not actual gaze, comprehension, or marketing effectiveness. It is not trained on human data. Automated workflow tests use separate temporary records, never the participant's ratings.
Research results and scope
The embedded batch produced viewer agreement of 4/12 for discoverability and 4/12 for preference. Same-side discoverability consistency was 3/3; reversed-side consistency was 1/3. These are exploratory results from one reviewer, not a validated viewer or a demonstration of side bias. The later fitted contextual reward achieved 10/24 training agreement and 8/24 grouped cross-validation agreement, versus 11/24 for the frozen viewer. It remains opt-in in marketcanvas/fitted_reward.py; the live reward is unchanged. See research/README.md for provenance and reproducible outputs.
RL interface
from marketcanvas import MarketCanvasEnv
env = MarketCanvasEnv()
observation, info = env.reset(seed=42)
observation, reward, terminated, truncated, info = env.step({
"op": "add_element",
"element": {"type": "text", "role": "headline", "content": "Summer Sale",
"x": 100, "y": 80, "width": 600, "height": 90, "font_size": 42}
})
preview = env.current_reward() # Read-only diagnostic; not an earned reward.
rgb = env.render() # uint8 array, shape (600, 800, 3).Actions: add_element, move_element, update_element, delete_element, submit. Updating properties includes text, colors, size, role, type, and z-index. IDs/creation order are immutable. Every attempted edit costs one step; invalid actions preserve elements and return an error. Post-terminal actions raise EpisodeFinished. There is no auto-reset.
The 40-action limit is part of the task and remaining time is observed. submit or budget exhaustion sets terminated=True; the core never independently truncates. Nonterminal reward is zero. Terminal reward lies in [-1,1] and is returned once. Reset begins a new trial, not an action available inside a training episode.
GymCanvasEnv in marketcanvas/gym_adapter.py passes Gymnasium's environment checker and declares JSON-text action/observation spaces. Actions and observations are JSON strings in this adapter; the core uses dictionaries. This does not supply a tokenizer, a tensor policy, or an off-the-shelf PPO training integration.
MCP
.venv/bin/python mcp_server.pyThis command waits for stdio protocol messages; it is not a browser server. Use mcp-config.example.json with an MCP-capable desktop client, replacing both paths with absolute paths. Do not add ordinary stdout logging to this server.
Tools: get_canvas_state, get_action_schema, execute_action, get_current_reward, reset_environment. First read the state and schema, then execute actions and submit. Tool responses include structured JSON. One stdio process owns one environment; edits are serialized with a lock. The transport test launches actual MCP subprocesses, performs initialization and tool discovery, compares their edits with Python execution, and checks independent processes.
The inspector also feature-detects browser WebMCP and exposes two local page tools. That is an optional convenience; the required standalone MCP server works independently of browser support.
Scope and limits
800×600 fixed canvas; maximum 24 elements; single-line printable ASCII text, up to 256 characters; fixed DejaVu Sans font; opaque rectangles and image placeholders; no rotation, transparency, rich text, imported images, or mouse interaction. Shapes may contain centered labels. Text is centered within its own bounding box. Bounds are validated; text overflow is rendered clipped and penalized when it affects a required slot.
The agent gets exact semantic state and constraints. This favors controlled task evaluation over realistic screenshot-only computer use. Required text is checked for content, glyph visibility, clipping, minimum 16px size, and contrast. Decorative content is not comprehensively evaluated. A high reward is not a certification of aesthetic quality, marketing effectiveness, or complete accessibility.
Read WRITEUP.md for formulation and scaling, and RESEARCH_NOTES.md for literature, experimental interpretation, and next studies.
Available Tools
5 toolsexecute_actionA
Execute one edit or submit; an invalid attempt consumes one step without changing elements.
Examples: {"op":"move_element","id":"e1","x":100,"y":80}; {"op":"update_element","id":"e1","properties":{"text_color":"#000000"}}; {"op":"add_element","element":{"type":"text","role":"headline","content":"Summer Sale"}}; {"op":"submit"}. Call get_action_schema for full property definitions.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and delivers the most valuable behavioral trait: failed attempts burn a step yet leave elements unchanged, implying atomic failure and a cost penalty for guessing. It does not address reversibility of valid edits, idempotency, or permissions, but the step-cost disclosure is substantive and non-obvious.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The key behavioral constraint (one action, invalid attempts cost a step) is front-loaded before the examples, so an agent gets the critical rule immediately. The examples are dense but each illustrates a distinct operation; the trailing quote and line breaks are minor formatting noise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the description correctly offloads exhaustive property definitions to get_action_schema. Combined with the examples and the step-cost rule, an agent has enough to invoke correctly, though it must make a second call before authoring a valid payload.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the single 'action' parameter is an untyped object with additionalProperties, so the schema provides essentially no semantics. The description compensates with four concrete payload shapes (move_element, update_element, add_element, submit) showing the op/id/properties/element keys, and defers exhaustive definitions to get_action_schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and scope: 'Execute one edit or submit,' which tells the agent this is the sole mutation entry point among read-only siblings like get_canvas_state and get_current_reward. The worked examples make the resource (canvas elements) concrete, though the resource is never named directly — the agent infers it from the payloads.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It establishes the operational rule that exactly one action is executed per call and warns that an invalid attempt consumes a step without changing elements, which implicitly tells the agent to validate first. It also routes the agent to get_action_schema for full property definitions. It stops short of explicitly contrasting when to call this versus get_canvas_state or reset_environment.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_action_schemaA
Read the validated action schema for add, move, update, delete, and submit.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. 'Read' conveys a read-only, side-effect-free operation and 'validated' implies the schema has been checked, which is useful context. However, it does not mention permissions, rate limits, or whether the schema is static or environment-dependent. Because an output schema exists, the return format need not be described here.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence that is front-loaded with the verb and resource, with no wasted words. Appropriately sized for a zero-parameter getter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is a simple read with zero parameters and an existing output schema, so the description need not explain return values. It names the covered action types, which is sufficient operational scope. The only slight gap is that it does not relate itself to the sibling execute_action.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline of 4 applies. The description does not need to add parameter meaning beyond the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Read') and resource ('validated action schema') and enumerates the action types covered (add, move, update, delete, submit). It implicitly distinguishes itself from the sibling execute_action by being a schema read rather than an execution. The only gap is that sibling differentiation is not made explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description offers no guidance on when to use this tool versus execute_action or the other siblings, nor any prerequisites or conditions. It only states what is returned, leaving the agent to infer the use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_canvas_stateA
Read complete semantic state, task constraints, geometry, and spatial relations.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. 'Read' implies a non-mutating operation and the description enumerates the complete state content, but it does not explicitly address side effects, permissions, idempotency, or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no filler or repetition. Every term contributes to specifying what state is read.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read tool with an output schema, the description appropriately names the content scope and does not need to explain return values or inputs. The main remaining gap, sibling routing, is better covered under usage guidelines.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so per the rubric the baseline is 4. There are no parameter semantics for the description to clarify beyond what the empty schema already shows.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb, 'Read,' and names the resources it reads: semantic state, task constraints, geometry, and spatial relations. This clearly states the tool's purpose, but it does not explicitly differentiate itself from siblings such as get_current_reward or get_action_schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives, nor any when-not conditions or prerequisites. The description only states what is read, leaving the agent to infer that it should call this tool when full canvas state is needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_current_rewardA
Read a diagnostic score preview and components. Does not advance or reward an episode.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It clearly discloses the key behavioral trait: the operation is read-only with respect to episode progression ('Does not advance or reward an episode'). It does not mention other traits like caching or permissions, but for a zero-param diagnostic read, the non-mutation disclosure is substantive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the tool's function and then the key non-side-effect constraint. Every sentence earns its place; no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (0 params, no annotations) and the presence of an output schema, the description covers the essential purpose and non-advancement behavior. It could be more complete by explicitly relating to sibling read tools, but for a simple diagnostic read the coverage is adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has zero parameters, so the baseline score is 4. The description adds no parameter information because there are none, which is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Read') and resource ('diagnostic score preview and components'), and the second sentence clarifies it does not advance or reward an episode, which helps distinguish it from execute_action. However, it does not explicitly differentiate from get_canvas_state or get_action_schema, so a 4 rather than 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an implied context (diagnostic preview without side effects), but does not explicitly say when to use this tool versus siblings like get_canvas_state or execute_action. It gives a when-not condition ('Does not advance or reward an episode') but no positive selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reset_environmentB
Discard this episode and start a blank canvas with an optional structured task specification.
| Name | Required | Description | Default |
|---|---|---|---|
| seed | No | ||
| task | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden, and it does disclose the key destructive trait: the current episode is discarded. However, it says nothing about irreversibility, permission requirements, or what 'blank canvas' means for prior state, leaving meaningful behavioral gaps for a destructive operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; the action is stated first and the optional argument second. Slightly metaphorical phrasing ('blank canvas') costs a little precision but costs no space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, and the core action is conveyed. Still, for a destructive reset with zero annotation coverage, the missing seed semantics and reversibility/precondition details leave the definition thinner than the operation warrants.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It loosely gestures at the 'task' parameter ('optional structured task specification') but gives no shape, format, or examples, and the 'seed' parameter is entirely unexplained despite being directly relevant to reproducibility of a reset.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and effect ('Discard this episode and start a blank canvas'), which is clearly distinct from the read-oriented siblings get_canvas_state and get_current_reward. It does not name a sibling explicitly, but the reset semantics are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied (start a fresh episode) rather than stated as an explicit trigger, and there is no guidance on when NOT to reset or what precondition must hold before discarding the current episode. Adequate but leaves the agent to infer the calling context.
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.
5 tool updates
v0.1.0- First observed
execute_action - First observed
get_action_schema - First observed
get_canvas_state - First observed
get_current_reward - First observed
reset_environment
TDQS
Scored across 5 tools
Each tool has a clearly distinct target: get_canvas_state reads world state, get_action_schema reads the action spec, get_current_reward reads scoring diagnostics, execute_action mutates, and reset_environment restarts. The three 'get_' readers could superficially look similar but their nouns (state/schema/reward) are unambiguous. No two tools overlap in purpose.
All five tools follow a clean snake_case verb_noun pattern (get_canvas_state, get_action_schema, execute_action, get_current_reward, reset_environment). The convention is uniform across readers, mutators, and lifecycle ops. No mixing of styles.
Five tools is exactly right for an environment-style server: observe, inspect schema, act, preview reward, reset. Nothing is redundant and nothing feels missing at the count level. Well-scoped and each tool earns its place.
The surface covers the full interaction lifecycle: reset/init, state observation, action schema discovery, action execution (add/move/update/delete/submit), and reward feedback. This is a complete observe-act-reward loop with no obvious dead ends.
Maintenance
Related MCP Connectors
Read-only MCP server for the OPERANT AI operating-agent calibration benchmark.
MCP server (stdio): validate JSON against JSON Schema (draft-07 / 2020-12) via the AgentForge API
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
Remote MCP server for AI.TV creators — delegate account operations to your AI agent over MCP.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceMCP stdio bridge to a running Navop desktop application, enabling AI agents to interact with Navop via MCP protocol.3MIT
- AlicenseNot gradedqualityAmaintenanceA local STDIO MCP server that bridges MCP clients to the Codex CLI by sending instructions to a configured workspace, exposing task run, status, and result tools with a read-only sandbox and no remote transport.124MIT
- FlicenseNot gradedqualityCmaintenanceEnables MCP-compatible hosts such as OpenCode to drive the Codex CLI through codex app-server over stdio, exposing tools to run prompts, inspect status, list threads, and interrupt running turns.-
- AlicenseNot gradedqualityBmaintenanceEnables local CLI and desktop MCP clients to control the MazeBench 3D game engine via stdio, with real-time browser viewing, action recording, and post-run summaries and replays.MIT