Sandbox
New in v3.7.0. The Sandbox is where code your AI agent generates through the MCP tools actually lives: custom Gutenberg blocks, custom Elementor widgets, and PHP snippets. Everything is isolated under wp-content/emcp-sandbox, never your theme, WordPress core, or another plugin, and every artifact is created inactive. A human has to review and activate it before it runs. That review step is the whole point: the AI never writes raw PHP or JS directly into your site.
EMCP Tools → Build → Sandbox (admin.php?page=emcp-tools-widgets) opens an overview with three cards (Widgets / PHP Snippets / Blocks), each opening its own list, and an Awaiting your review queue.
| Pillar | Tier | What it is |
|---|---|---|
| Blocks | Pro | AI-generated custom Gutenberg blocks, compiled from a spec. Active blocks appear in the block editor inserter under “EMCP Custom.” List: &view=blocks. |
| Widgets | Pro | AI-generated custom Elementor widgets, sandboxed and shown in the panel under “Custom (EMCP).” List: &view=widgets. Tool reference: Widget Builder. |
| PHP Snippets | Free (capability-gated) | Small PHP snippets an AI agent can draft, run as a shortcode or on a hook, that stay inactive until reviewed. List: &view=snippets. |
This page covers the PHP Snippets tools (undocumented elsewhere) and the admin review workflow shared by all three pillars. For creating custom Elementor widgets, see Widget Builder; for custom Gutenberg blocks, the tool reference is below.
PHP Snippets tools
Section titled “PHP Snippets tools”A snippet runs as a shortcode ([emcp_snippet id="N"]), on a WordPress hook, or both. Code is validated on every create/update, and rejected only if it trips a critical finding, the kind that blocks activation outright (eval, file writes, network calls, and similar). create-php-snippet always produces an inactive draft; it never runs until an admin activates it in the Sandbox.
Findings come in three levels (severity on each finding), so routine code doesn’t get lost in noise: critical blocks activation; warning doesn’t block but is worth a reviewer’s attention (writing a site option, sending email); notice is routine and expected in working code (exiting after a redirect, reading request input). Only critical findings stop a snippet from saving or activating; warnings and notices come back alongside a successful save so an agent or reviewer can see them without being blocked by them. On the Sandbox screen the three levels read Must change, Worth a read and Note.
| Tool | Purpose |
|---|---|
emcp-tools/validate-php-snippet | Dry-run validation, no code is saved. |
emcp-tools/create-php-snippet | Create a snippet as an inactive draft. |
emcp-tools/update-php-snippet | Update code/settings; re-validates. An active snippet is recompiled, or demoted to draft if it no longer passes. |
emcp-tools/get-php-snippet | Return a snippet’s code, settings, and status. |
emcp-tools/list-php-snippets | List snippets (id, title, status). |
emcp-tools/delete-php-snippet | Delete a snippet. |
create-php-snippet / update-php-snippet input:
title: a label for the snippet.code(required on create): PHP code, no<?phptag needed, runs inside an isolated function. Usereturnorechofor shortcode output.context:"shortcode","hook", or"both". Defaults to shortcode.hook: the WordPress action to attach to when context is hook/both (e.g.wp_footer,init).priority: hook priority, default10.
Activation always requires a human, in the Sandbox UI, regardless of who created the draft. There is no activate tool for snippets.
Custom Gutenberg Blocks tools
Section titled “Custom Gutenberg Blocks tools”Same shape as Widget Builder, for the block editor instead of Elementor: the agent submits a JSON spec plus an HTML template with {{control}} placeholders, never raw JS, and the plugin compiles a real block.
| Tool | Purpose |
|---|---|
emcp-tools/list-block-control-types | List supported attribute types, template syntax, attribute options and the allowed supports keys, call first. |
emcp-tools/validate-block-spec | Dry-run the generator, no code saved. |
emcp-tools/create-custom-block | Generate a block as an inactive draft from a spec. |
emcp-tools/update-custom-block | Replace a block’s spec, regenerate, re-validate. |
emcp-tools/get-custom-block | Return a block’s spec, generated code, and status. |
emcp-tools/list-custom-blocks | List generated blocks (id, title, block name, status). |
emcp-tools/set-block-status | Return a block to an inactive draft. Accepts only draft; activation happens on the Sandbox screen. |
emcp-tools/delete-custom-block | Delete a block (record + sandbox files). |
Template syntax matches the Widget Builder: {{attribute_name}} for values, {{#if name}}…{{/if}} for conditionals, {{#each repeater}}…{{/each}} for loops, every value escaped by its declared attribute type. A runtime safety net isolates compile failures, a malformed block is demoted to draft with a recorded error rather than breaking the block editor.
Attribute types and options
Section titled “Attribute types and options”Every attribute takes a name, type, default and label. Types: string, richtext, number, boolean, select, color, media, url and repeater.
| Option | Applies to | What it does |
|---|---|---|
group | any attribute | Places the control in a named, collapsible sidebar panel. Attributes with the same group share a panel; the first panel opens by default. Without a group a control sits in Settings. |
help | any attribute | Hint text shown under the control. |
min, max, step | number | Range of the slider. |
options | select | Required list of { value, label }. |
media_types | media | Widens the picker: ["image"] (default), "video", "audio", "application", or a mix. |
Since v3.20.0:
- Color controls offer the active theme’s palette swatches as well as a custom color.
- Media controls show a thumbnail with Replace and Remove and store the alt text and media type. In the template,
{{name}}prints the URL,{{name_alt}}the Media Library alt text and{{name_id}}the attachment ID, so<img src="{{photo}}" alt="{{photo_alt}}">gets a real alt. Declaring a separate attribute such asphoto_altbeside aphotomedia attribute is refused. - Reserved names are refused. WordPress uses
align,className,style,backgroundColor,textColor,gradient,fontSize,fontFamily,borderColor,shadow,anchor,lock,metadataandlayoutfor its own block attributes and would silently overwrite an attribute of the same name.create-custom-block,update-custom-blockandvalidate-block-specrefuse these names and suggest another (for examplecontent_align). Blocks already on the site, and blocks arriving through an import, a Cloud pull or a Marketplace install, keep working unchanged.
Repeaters
Section titled “Repeaters”type: "repeater" gives a list of rows that the person editing can add, remove, reorder and edit in the sidebar, each row opening on its own.
| Option | What it does |
|---|---|
fields | Required list of row fields, each { name, type, label?, default?, help?, options?, min?, max?, step?, media_types? }. Any type except repeater: repeaters cannot nest. |
default | Starter rows, a list of { field: value } objects. |
title_field | The field shown as each row’s title in the sidebar. |
item_label | Row name used when the title field is empty. |
add_label | Text of the add button. |
min_rows, max_rows | Row limits (whole numbers of 0 or more). |
In the template, loop rows with {{#each items}}…{{/each}} and print a field by name, for example {{#each items}}<li>{{name}} {{price}}</li>{{/each}}. Each field is escaped by its own type, and a media field in a row also gives {{field_alt}} and {{field_id}}.
Block supports
Section titled “Block supports”supports switches on WordPress’s own style panels for the block. Pass true or the panel’s own options object for each key:
| Key | Panel |
|---|---|
align | Wide and full alignment, e.g. ["wide","full"]. |
color | Text, background and link colors. |
spacing | Padding and margin. |
typography | Typography, such as font size and line height. |
border | Radius, width, color and style (new in 3.20.0). |
shadow | Box shadow (new in 3.20.0). |
dimensions | Dimensions such as minimum height (new in 3.20.0). |
background | Background image (new in 3.20.0). |
Since v3.20.0 these choices also reach the front end. The generated render.php merges WordPress’s wrapper attributes (the support classes and inline styles, the Additional CSS class field and alignment) into the template’s root element, without adding a wrapper element, so give the template a single root element. In the editor preview the merge is skipped, because the editor’s own block wrapper already carries those styles. Blocks created before 3.20.0 pick this up the next time they are updated. The merge uses WordPress core functions only, so it keeps working in a Sandbox plugin export.
The Sandbox admin screens
Section titled “The Sandbox admin screens”
Overview and review queue
Section titled “Overview and review queue”Each overview card shows how many artifacts are active and how many are inactive / drafts (a free site shows “Requires Pro” on the Widgets and Blocks cards). Click a card to open its list.
Awaiting your review lists every inactive widget, block and snippet, newest first, with who drafted it, when, and the validator summary (“Nothing flagged”, “N ordinary notes” or “N things worth reading”). Review code opens that item’s code drawer on its list. The Sandbox entry in the sidebar shows a badge with the number of drafts the validator flagged, and the Dashboard’s Needs your attention card links here with Review drafts.
The lists
Section titled “The lists”The Widgets, Blocks and PHP Snippets lists share one layout:

- On or off switch: the human review gate. Nothing an agent creates runs until you switch it on here. A PHP snippet asks “Activate this snippet?” first, because it runs real PHP.
- Filter tabs All / Active / Inactive (the snippet list adds Needs reading) and a search box. Lists show 20 items per page.
- View code: inspect the generated PHP, JS and CSS before deciding whether to activate it. Blocks also have Preview, which renders the block on the server with its default values in a sandboxed frame.
- Export: download a
.jsonbundle of the artifact. - Import bundle: upload a
.jsonbundle exported from another site (or from Export); imports always land as a new inactive draft. - More actions (the three-dot menu): Cloud and Marketplace actions (below) and Delete, which removes the record and its sandbox files after a confirmation.
The PHP Snippets list also has Add snippet and Edit, which open an editor drawer with a title, Runs as (Shortcode, Hook or Both, with the hook name and priority), the code and the validator findings. Saving there never switches a draft on; an edited active snippet stays active.
Cloud Library and Marketplace
Section titled “Cloud Library and Marketplace”If the EMCP Cloud module is on and this site is connected, each list also gets:
- A Cloud column: “Not in Cloud”, “Synced” (the Cloud copy matches) or “Changed” (edited since it was saved). Refresh cloud status re-checks it.
- Save to Cloud / Update in Cloud in the row menu, and Save all to Cloud above the table: back up artifacts to your EMCP Cloud account.
- Cloud library (marked CROSS-SITE): browse artifacts you’ve saved from any of your connected sites and Import one into the current site, as a new inactive draft to review.
- Publish to Marketplace in the row menu: publish an artifact to the EMCP Marketplace for others to install. Once published, the menu offers Push update to Marketplace (with a “What changed” note, sent for review) and View on Marketplace.
These buttons, and the plain Export / Import bundle buttons above, are calls to MCP tools an agent can also use directly: export-sandbox-artifact / import-sandbox-artifact for the general portable-bundle mechanism (no Cloud connection needed), and cloud-backup / cloud-pull / cloud-marketplace-list / cloud-marketplace-install for the Cloud-connected versions. Full tool reference: EMCP Cloud & Marketplace.
Export as plugin (Pro)
Section titled “Export as plugin (Pro)”The Export as plugin button on the overview (&view=export, shown while the Sandbox Plugin Export module is on) packages every active widget, block and snippet as a standalone plugin ZIP. Fill in the plugin name, slug, author and version, choose what to include, and click Build and download ZIP. Install the plugin on a site and deactivate EMCP Tools there: the exported plugin stays dormant while EMCP Tools is active and takes over on the next request after it is deactivated. One export can be installed per site. See Export as plugin for what is bundled, API keys and the limits.
Permissions
Section titled “Permissions”Creating, updating and deleting any Sandbox artifact requires manage_options plus unfiltered_html, the same bar as site-wide custom code, and so does activating one on the Sandbox screen. Read/validate tools require edit_posts.
