coregutenberg

Gutenberg (Block Editor) Abilities

Block tree reads and writes, reusable blocks, block templates, patterns, and FSE global styles.

21Total Abilities
10Destructive
4Capability Gates
Functional Domains:
Core surface (no host plugin required)
WordPress capabilities required:
edit_theme_options 7delete_posts 1edit_posts 11read 2

Available Tools (21)

blocks_get_post_treeRead-only

Read a post or page as a structured Gutenberg block tree. Returns a flat list of blocks, each with its index path, block name, a plain-text snippet, and child count, far cheaper in tokens than fetching the full post_content. Use this first to find the path of the block you want to edit, then call blocks_get_block for full detail on one block. Works on any post type that stores block markup.

Ability IDmore-mcp/blocks-get-post-treeRequiresread
Parameter Schema3 parameters
{
  "type": "object",
  "properties": {
    "post_id": {
      "type": "integer",
      "description": "Post or page ID."
    },
    "depth": {
      "type": "integer",
      "description": "How many levels of nesting to include. Default 10. Use 0 for top-level blocks only."
    },
    "snippet_length": {
      "type": "integer",
      "description": "Max characters of plain text per block. Default 160, max 1000."
    }
  },
  "required": [
    "post_id"
  ]
}
blocks_get_blockRead-only

Get one block from a post by its index path, including full attributes, raw inner HTML, and its serialized markup. Use after blocks_get_post_tree has told you which path you want.

Ability IDmore-mcp/blocks-get-blockRequiresread
Parameter Schema2 parameters
{
  "type": "object",
  "properties": {
    "post_id": {
      "type": "integer",
      "description": "Post or page ID."
    },
    "path": {
      "type": "string",
      "description": "Dot-separated 0-based index path, e.g. \"0\" for the first top-level block or \"1.2\" for the third child of the second. Paths shift when siblings are inserted or removed. Always re-read the tree after a mutation rather than reusing an old path."
    }
  },
  "required": [
    "post_id",
    "path"
  ]
}
blocks_insertDestructive

Insert a new block into a post at a position relative to an existing block. Supply the block either as structured fields (block_name plus attributes and inner_html) or as raw markup. Set dry_run=true to preview the resulting tree without writing. Requires edit_post capability on the target post. Emits an undo token.

Ability IDmore-mcp/blocks-insertRequiresedit_posts
Parameter Schema9 parameters
{
  "type": "object",
  "properties": {
    "post_id": {
      "type": "integer",
      "description": "Post or page ID."
    },
    "path": {
      "type": "string",
      "description": "Path of the reference block. Dot-separated 0-based index path, e.g. \"0\" for the first top-level block or \"1.2\" for the third child of the second. Paths shift when siblings are inserted or removed. Always re-read the tree after a mutation rather than reusing an old path."
    },
    "position": {
      "type": "string",
      "enum": [
        "before",
        "after",
        "first_child",
        "last_child"
      ],
      "description": "Where to place the new block relative to the reference block."
    },
    "block_name": {
      "type": "string",
      "description": "Block type, e.g. \"core/paragraph\". Required unless markup is supplied."
    },
    "attributes": {
      "type": "object",
      "description": "Block attributes as a JSON object. Use blocks_get_type_schema to discover valid attributes."
    },
    "inner_html": {
      "type": "string",
      "description": "The block's saved HTML, e.g. \"<p>Hello</p>\" for a paragraph. Must match what the block's save() function would produce."
    },
    "markup": {
      "type": "string",
      "description": "Raw block markup as an alternative to the structured fields, e.g. \"<!-- wp:paragraph --><p>Hi</p><!-- /wp:paragraph -->\". Takes precedence over block_name/attributes/inner_html."
    },
    "expected_block_name": {
      "type": "string",
      "description": "Guard: abort unless the block at path has this name. Protects against a stale path pointing somewhere unintended."
    },
    "dry_run": {
      "type": "boolean",
      "description": "Preview the result without writing. Default false."
    }
  },
  "required": [
    "post_id",
    "path",
    "position"
  ]
}
blocks_updateDestructive

Update the block at a given path: replace its attributes, its inner HTML, or both. Attributes are replaced wholesale, not merged: read the block first with blocks_get_block, then send the complete attribute set you want. Set dry_run=true to preview. Requires edit_post. Emits an undo token.

Ability IDmore-mcp/blocks-updateRequiresedit_posts
Parameter Schema6 parameters
{
  "type": "object",
  "properties": {
    "post_id": {
      "type": "integer",
      "description": "Post or page ID."
    },
    "path": {
      "type": "string",
      "description": "Dot-separated 0-based index path, e.g. \"0\" for the first top-level block or \"1.2\" for the third child of the second. Paths shift when siblings are inserted or removed. Always re-read the tree after a mutation rather than reusing an old path."
    },
    "attributes": {
      "type": "object",
      "description": "Complete replacement attribute object. Omit to leave attributes unchanged."
    },
    "inner_html": {
      "type": "string",
      "description": "Replacement saved HTML for the block. Omit to leave unchanged. Ignored for blocks that have child blocks."
    },
    "expected_block_name": {
      "type": "string",
      "description": "Guard: abort unless the block at path has this name."
    },
    "dry_run": {
      "type": "boolean",
      "description": "Preview the result without writing. Default false."
    }
  },
  "required": [
    "post_id",
    "path"
  ]
}
blocks_deleteDestructive

Delete the block at a given path, including all of its children. Set dry_run=true to preview what would be removed. Requires edit_post. Emits an undo token that restores the full pre-deletion content.

Ability IDmore-mcp/blocks-deleteRequiresedit_posts
Parameter Schema4 parameters
{
  "type": "object",
  "properties": {
    "post_id": {
      "type": "integer",
      "description": "Post or page ID."
    },
    "path": {
      "type": "string",
      "description": "Dot-separated 0-based index path, e.g. \"0\" for the first top-level block or \"1.2\" for the third child of the second. Paths shift when siblings are inserted or removed. Always re-read the tree after a mutation rather than reusing an old path."
    },
    "expected_block_name": {
      "type": "string",
      "description": "Guard: abort unless the block at path has this name. Strongly recommended for deletes."
    },
    "dry_run": {
      "type": "boolean",
      "description": "Preview without writing. Default false."
    }
  },
  "required": [
    "post_id",
    "path"
  ]
}
blocks_moveDestructive

Move a block (with its children) from one path to another within the same post. The destination is resolved before the source is removed, so you can use the paths exactly as reported by blocks_get_post_tree without compensating for shifts. Requires edit_post. Emits an undo token.

Ability IDmore-mcp/blocks-moveRequiresedit_posts
Parameter Schema6 parameters
{
  "type": "object",
  "properties": {
    "post_id": {
      "type": "integer",
      "description": "Post or page ID."
    },
    "from_path": {
      "type": "string",
      "description": "Path of the block to move. Dot-separated 0-based index path, e.g. \"0\" for the first top-level block or \"1.2\" for the third child of the second. Paths shift when siblings are inserted or removed. Always re-read the tree after a mutation rather than reusing an old path."
    },
    "to_path": {
      "type": "string",
      "description": "Path of the reference block at the destination."
    },
    "position": {
      "type": "string",
      "enum": [
        "before",
        "after",
        "first_child",
        "last_child"
      ],
      "description": "Placement relative to the destination block."
    },
    "expected_block_name": {
      "type": "string",
      "description": "Guard: abort unless the block at from_path has this name."
    },
    "dry_run": {
      "type": "boolean",
      "description": "Preview without writing. Default false."
    }
  },
  "required": [
    "post_id",
    "from_path",
    "to_path",
    "position"
  ]
}
blocks_validate_markupedit_posts

Validate Gutenberg block markup server-side and report a confidence level rather than a pass/fail. Checks delimiter balance, attribute JSON, block registration, attribute types against registered schemas, and nesting constraints. IMPORTANT: PHP cannot run a block's JavaScript save() function, which is what the editor actually compares against, so this cannot guarantee the editor will accept the markup, and a block that is not registered server-side is reported as "unknown", never as invalid. Use before writing hand-authored markup.

Ability IDmore-mcp/blocks-validate-markupRequiresedit_posts
Parameter Schema1 parameter
{
  "type": "object",
  "properties": {
    "markup": {
      "type": "string",
      "description": "Raw block markup to validate."
    }
  },
  "required": [
    "markup"
  ]
}
blocks_list_typesedit_posts

List Gutenberg block types registered on this site, with name, title, category, dynamic flag, and nesting constraints. Filter by category or search term. Note that blocks registered only in JavaScript do not appear: absence here does not mean a block is unavailable in the editor.

Ability IDmore-mcp/blocks-list-typesRequiresedit_posts
Parameter Schema2 parameters
{
  "type": "object",
  "properties": {
    "category": {
      "type": "string",
      "description": "Filter by block category slug, e.g. \"text\", \"media\", \"design\"."
    },
    "search": {
      "type": "string",
      "description": "Case-insensitive substring match against block name and title."
    }
  }
}
blocks_get_type_schemaedit_posts

Get the full attribute schema for one block type: every attribute with its type and default, plus supports flags and registered variations. Call this before constructing a block with blocks_insert so the attributes you send match what the block actually accepts.

Ability IDmore-mcp/blocks-get-type-schemaRequiresedit_posts
Parameter Schema1 parameter
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Fully-qualified block name, e.g. \"core/heading\"."
    }
  },
  "required": [
    "name"
  ]
}
blocks_list_templatesedit_theme_options

List site templates available for this theme. Returns each template's slug, title, description, and whether it was customized in the database or is still the theme-provided file. Works only when a block theme (Full Site Editing theme) is active. Filters by type (templates or template parts) and area.

Ability IDmore-mcp/blocks-list-templatesRequiresedit_theme_options
Parameter Schema3 parameters
{
  "type": "object",
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "template",
        "template_part"
      ],
      "description": "Filter by type. Omit for both."
    },
    "area": {
      "type": "string",
      "description": "For template parts: filter by area (\"header\", \"footer\", \"uncategorized\"). For templates: omit."
    },
    "search": {
      "type": "string",
      "description": "Case-insensitive substring search on slug and title."
    }
  }
}
blocks_get_templateedit_theme_options

Get a single template by slug, returning its full block markup, content hash, and metadata. The slug is the name portion only, e.g. "single-post" for templates/single-post.html in the theme, or just "index" for the fallback index template. The tool resolves both theme-file and database-customized versions and tells you which you received.

Ability IDmore-mcp/blocks-get-templateRequiresedit_theme_options
Parameter Schema2 parameters
{
  "type": "object",
  "properties": {
    "slug": {
      "type": "string",
      "description": "Template slug. For theme-provided templates this is the filename without extension, e.g. \"index\", \"single-post\", \"page\". For database-customizations the ID is theme//slug (e.g. \"flavor//single-post\"), which this tool resolves automatically."
    },
    "type": {
      "type": "string",
      "enum": [
        "template",
        "template_part"
      ],
      "description": "Default \"template\"."
    }
  },
  "required": [
    "slug"
  ]
}
blocks_update_templateDestructive

Create or update a database customization of a theme template. Pass the slug (e.g. "single-post" or "header"). If the theme provides the template, the new content shadows it; if no theme template exists, a new custom template is created. The previous state is captured for undo.

Ability IDmore-mcp/blocks-update-templateRequiresedit_theme_options
Parameter Schema6 parameters
{
  "type": "object",
  "properties": {
    "slug": {
      "type": "string",
      "description": "Template slug. For theme-provided templates this is the filename without extension, e.g. \"index\", \"single-post\", \"page\". For database-customizations the ID is theme//slug (e.g. \"flavor//single-post\"), which this tool resolves automatically."
    },
    "content": {
      "type": "string",
      "description": "The new block markup for the template body. Must be valid Gutenberg block markup. The title, description, and slug are derived automatically."
    },
    "title": {
      "type": "string",
      "description": "Optional human-readable title. Defaults to the slug title-cased."
    },
    "type": {
      "type": "string",
      "enum": [
        "template",
        "template_part"
      ],
      "description": "Default \"template\"."
    },
    "area": {
      "type": "string",
      "description": "Template part area (\"header\", \"footer\", \"uncategorized\"). Only relevant when type is \"template_part\"."
    },
    "dry_run": {
      "type": "boolean",
      "description": "Preview what would be written without modifying the database."
    }
  },
  "required": [
    "slug",
    "content"
  ]
}
blocks_revert_templateDestructive

Remove a database customization, causing the theme-provided file to resurface. Pass the slug only: if a database post exists for that slug, it is deleted; if none exists, the tool reports that no customization was found and no changes were made. Captures the pre-deletion state for undo.

Ability IDmore-mcp/blocks-revert-templateRequiresedit_theme_options
Parameter Schema3 parameters
{
  "type": "object",
  "properties": {
    "slug": {
      "type": "string",
      "description": "Template slug. For theme-provided templates this is the filename without extension, e.g. \"index\", \"single-post\", \"page\". For database-customizations the ID is theme//slug (e.g. \"flavor//single-post\"), which this tool resolves automatically."
    },
    "type": {
      "type": "string",
      "enum": [
        "template",
        "template_part"
      ],
      "description": "Default \"template\"."
    },
    "dry_run": {
      "type": "boolean",
      "description": "Preview what would be deleted without modifying the database."
    }
  },
  "required": [
    "slug"
  ]
}
blocks_list_patternsedit_theme_options

List registered block patterns available on this site. Read-only: patterns cannot be edited through this tool. Returns the pattern name, slug, category, description, and whether the pattern uses specific block types.

Ability IDmore-mcp/blocks-list-patternsRequiresedit_theme_options
Parameter Schema2 parameters
{
  "type": "object",
  "properties": {
    "category": {
      "type": "string",
      "description": "Filter by pattern category slug, e.g. \"buttons\", \"columns\", \"header\"."
    },
    "search": {
      "type": "string",
      "description": "Case-insensitive substring search on name and slug."
    }
  }
}
blocks_list_reusableedit_posts

List reusable blocks (the wp_block post type). Returns each block's ID, title, and a snippet of its content. Reusable blocks are global: updating one is reflected everywhere it is used.

Ability IDmore-mcp/blocks-list-reusableRequiresedit_posts
Parameter Schema3 parameters
{
  "type": "object",
  "properties": {
    "per_page": {
      "type": "integer",
      "description": "Number of reusable blocks per page. Default 20, max 100."
    },
    "page": {
      "type": "integer",
      "description": "Page number, 1-indexed. Default 1."
    },
    "search": {
      "type": "string",
      "description": "Case-insensitive substring search on the block title."
    }
  }
}
blocks_get_reusableedit_posts

Get a single reusable block by ID, returning its title, full block markup, and a token-budget-friendly summary of its internal block structure.

Ability IDmore-mcp/blocks-get-reusableRequiresedit_posts
Parameter Schema1 parameter
{
  "type": "object",
  "properties": {
    "reusable_id": {
      "type": "integer",
      "description": "The post ID of the reusable block (the wp_block post type)."
    }
  },
  "required": [
    "reusable_id"
  ]
}
blocks_create_reusableDestructive

Create a new reusable block. Requires edit_posts capability. Returns the new block's ID.

Ability IDmore-mcp/blocks-create-reusableRequiresedit_posts
Parameter Schema2 parameters
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "description": "Human-readable title for the reusable block."
    },
    "content": {
      "type": "string",
      "description": "Block markup for the reusable block. Must be valid Gutenberg block markup."
    }
  },
  "required": [
    "title",
    "content"
  ]
}
blocks_update_reusableDestructive

Update an existing reusable block's content. Reusable blocks are global: this change is reflected everywhere the block is embedded. Captures the previous content for undo. Requires edit_post capability on the wp_block post.

Ability IDmore-mcp/blocks-update-reusableRequiresedit_posts
Parameter Schema4 parameters
{
  "type": "object",
  "properties": {
    "reusable_id": {
      "type": "integer",
      "description": "The post ID of the reusable block to update."
    },
    "title": {
      "type": "string",
      "description": "New title for the block. Omit to leave unchanged."
    },
    "content": {
      "type": "string",
      "description": "New block markup. Required."
    },
    "dry_run": {
      "type": "boolean",
      "description": "Preview without writing. Default false."
    }
  },
  "required": [
    "reusable_id",
    "content"
  ]
}
blocks_delete_reusableDestructive

Permanently delete a reusable block. All places where this block is embedded will fall back to rendering nothing. Captures the deleted content for undo. Requires delete_post capability on the wp_block post.

Ability IDmore-mcp/blocks-delete-reusableRequiresdelete_posts
Parameter Schema2 parameters
{
  "type": "object",
  "properties": {
    "reusable_id": {
      "type": "integer",
      "description": "The post ID of the reusable block to delete."
    },
    "dry_run": {
      "type": "boolean",
      "description": "Preview without deleting. Default false."
    }
  },
  "required": [
    "reusable_id"
  ]
}
blocks_get_global_stylesedit_theme_options

Read the site's global styles (theme.json): the colour palette, typography scale, spacing presets, layout widths, and per-block style overrides that a block theme renders from. This is the Site Editor's Styles sidebar, and the Gutenberg counterpart of elementor_get_kit. Pick which layer you want with origin: "user" (default) is what the Site Editor has saved and the only layer that is writable; "theme" is the active theme's own theme.json defaults; "merged" is what actually renders, after core, block, theme and user layers are combined in that priority order. IMPORTANT: by default this returns a KEY INDEX, not the values, because merged theme.json data on a real block theme carries a section per registered block and is larger than a single tool result allows. Pass keys:["settings.color.palette","styles.typography"] to read specific dot-paths, or include_all:true to force the whole object. Read the user layer before writing with blocks_update_global_styles, since a list-valued preset such as settings.color.palette is replaced wholesale rather than merged element by element. Requires edit_theme_options.

Ability IDmore-mcp/blocks-get-global-stylesRequiresedit_theme_options
Parameter Schema3 parameters
{
  "type": "object",
  "properties": {
    "origin": {
      "type": "string",
      "enum": [
        "user",
        "theme",
        "merged"
      ],
      "description": "Which layer to read. \"user\" (default) is the saved Site Editor customization and the only writable layer. \"theme\" is the theme's theme.json defaults, useful for discovering which preset slugs exist before overriding them. \"merged\" is the effective rendered result."
    },
    "keys": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Dot-paths to return the actual values for, e.g. \"settings.color.palette\", \"styles.color.background\", or a bare top-level key like \"settings\". A path that is absent from this layer is reported in unset_paths rather than returned as empty, because \"unset here\" and \"empty\" mean different things: an unset user value means the theme default still applies."
    },
    "include_all": {
      "type": "boolean",
      "description": "Return the complete theme.json object instead of the key index. Expect a very large response on the merged origin; prefer keys."
    }
  }
}
blocks_update_global_stylesDestructive

Write the site's user global styles (theme.json), which is what the Site Editor's Styles sidebar saves. IMPORTANT: the keys you send are MERGED into the existing user styles, not replaced, so sending only settings.color.palette leaves typography and every per-block override untouched. Nested objects merge recursively, but a LIST value (settings.color.palette, settings.typography.fontSizes, settings.spacing.spacingSizes) is replaced wholesale, the same rule as the Elementor kit repeaters: read the current list with blocks_get_global_styles keys:["settings.color.palette"] and send the full list back with your edits, or you will drop the entries you omitted. Pass replace_settings=true only for a deliberate wholesale swap, which discards every top-level key you do not send and reports what it removed. Accepts the "settings" and "styles" top-level keys; "version" and WordPress's isGlobalStylesUserThemeJSON marker are structural and written automatically (without that marker WordPress ignores the stored JSON entirely, so a write would succeed, read back correctly, and change nothing on the page). Set dry_run=true to preview a per-path diff without writing. After a write the response re-reads the stored value to confirm what landed, and the theme_json caches are invalidated so the next render picks the change up. Emits an undo token restoring the full pre-write user styles. Site-wide change. Requires edit_theme_options.

Ability IDmore-mcp/blocks-update-global-stylesRequiresedit_theme_options
Parameter Schema4 parameters
{
  "type": "object",
  "properties": {
    "settings": {
      "type": "object",
      "description": "theme.json \"settings\" subtree: presets and opt-ins such as color.palette, typography.fontSizes, spacing.spacingSizes, layout.contentSize. Merged recursively; list values replace wholesale."
    },
    "styles": {
      "type": "object",
      "description": "theme.json \"styles\" subtree: the applied values such as color.background, typography.fontFamily, elements.link, and per-block overrides under blocks. Merged recursively; list values replace wholesale."
    },
    "replace_settings": {
      "type": "boolean",
      "description": "Replace the whole user styles object instead of merging. Discards every top-level key you do not send. Default false."
    },
    "dry_run": {
      "type": "boolean",
      "description": "Report the per-path diff the call would apply without writing. Default false."
    }
  }
}