Skip to main content
Glama

Search and replace across the site

wp_search_replace
Destructive

Search and replace across the site's stored data, safe for serialized and JSON values; finding text without changing it is wp_search, one post is changed with wp_update_post. tables: posts (title, content, excerpt), postmeta, options, terms (names, descriptions, termmeta); default posts and postmeta. apply=false (default) is a dry run that returns a per-table preview; apply=true writes. Matching: serialized and JSON values are rewritten losslessly, and the CSS and caches Elementor builds from elementor_data (element cache with the rendered HTML, Markdown cache) are reset. Plain (non-regex) mode also finds the encoded forms WordPress and page builders store (JSON-escaped such as https://…, block attributes such as &, HTML entities such as &, and HTML inside block attributes), so "A & B" is found where a page stores "A & B", and writes the replacement in the form it found, as JSON inside block attributes. A serialized value holding a PHP object, a Serializable or enum record or a reference is left untouched (skipped_object_values), so no class is restored from stored data. Scope "text" (default): a page-builder page that a writer here writes (write_via in wp_get_builder_layout) changes only through that writer, in the texts, links and images it may change, under the field rules of wp_update_builder_element; its post_content copy is left out (copy_only). Matches in locked places (code, HTML, CSS, shortcodes, forms, placeholders, global parts, page code), and on pages the writer refuses as a whole, stay and are counted in locked_matches; scope "raw" reaches them. Fields a writer leaves are named in notes. A page whose page builder has no writer here, and a text a writer finds in none of its fields where the site shows post_content (SeedProd), are replaced as text (as_text, builder_pages_without_writer); a builder that keeps its own copy writes it over that at its next save. For an account without unfiltered_html, a post that WordPress's kses filter would store differently (an SVG, a style or a script dropped, a block attribute changed, in any field it filters) is not written and is named in notes. Scope "raw": the stored data as text everywhere, page-builder data and page code included (page-builder data needs unfiltered_html); a copy in post_content_filtered (SeedProd) is not read, so only post_content changes there until the page builder writes its copy back at its next save, and warnings names such pages. Undo: page-builder pages get undo points under one undo_token (undo_pages lists them). For pages a writer changes it holds their page-builder data and its copies; for pages changed outside a writer and in scope "raw" also post_content and the meta keys the call rewrites on them, except the code fields a page builder locks (custom CSS, for example): an undo leaves those as changed, and warnings names them. Posts without a page builder, titles, excerpts, options and terms are not in it, and the answer says so. Per call, at most 25 pages change through writers (next.builders continues) and at most 25 in scope "raw"; of the pages scope "text" changes outside a writer, up to 25 get an undo point, and the others, or any whose undo point cannot be recorded, are written without one and named in warnings (stop_at_undo_cap, allow_without_undo). Never touched: trash, auto-drafts, revisions (unless exclude_revisions=false), protected options and option names the option guard refuses, transients, the guid column, credential-like meta keys, widget rows, internal post types and taxonomies; rows the account may not read or edit are passed over silently. Protected "" meta keys are rewritten only for an account with manage_options and only when allow-listed (filter ab_mcp_pro_protected_meta_allowlist), never _wp_attached_file, _wp_attachment_metadata, _thumbnail_id or _wp_page_template; page-builder data (_elementor_data, panels_data, dslc_code, pagelayer-data, brizy, vcv-pageContent, mfn-page-items, tve_updated_post and more; filter ab_mcp_pro_markup_meta_keys) only for an account with unfiltered_html, on multisite a super admin. Writes go through the WordPress APIs (revisions created, serialization regenerated, caches invalidated), term names and descriptions through wp_update_term(). No slug is asked to change: a term shared by several taxonomies or with an empty stored slug is passed over, and slug_changes lists any slug a filter changed along with a name (term, old and new slug; up to 200, the rest in slug_changes_omitted). Paging: at most 5 000 000 ids per scan (10 000 per query, a tenth in regex mode; the terms table has three scans, the page-builder pages one, builders); next records where each scan stopped, and sent back as after it lets the next call continue without reading anything twice. Answer: per-table counts and previews; notes (up to 10 per table, notes_omitted the rest); warnings; skipped_object_values and skipped_unchecked_values (too large or too deep to walk: more than 64 levels or 12 nested serialized or JSON strings) count values, not rows, and the rest of such a row is still rewritten. Forwarded by AlphaBridge Connect to the one site this connection reaches.

Input Schema

NameRequiredDescriptionDefault
typeNoPost type filter for the posts table and the page-builder pages (postmeta is scanned for every post whose meta the account may read and edit); a call without the posts table ignores it (flags.type_ignored). Default any.
afterNoThe next object of a previous call (keys posts, postmeta, options, term_names, term_descriptions, termmeta, builders; each the id to continue behind). Default: start at the beginning of every table.
applyNotrue writes the changes; false (default) returns the dry-run preview only.
limitNoMax matched rows processed per table (1–2000). Default 200. When truncated=true, next, sent back as after, continues there; notes say why a scan stopped, and only where the row limit stopped it does a higher limit take more rows (page-builder pages stay at 25 per call: table builders, scope raw, stop_at_undo_cap). Rows the policy passes over do not count.
regexNotrue treats search as a PCRE regex (no delimiters; slower: every row of the id budget is read and tested in PHP, without a SQL prefilter). Matches the stored bytes only, without the encoded forms. In scope text, a page-builder page whose writer does not apply a pattern to its fields is left as it is and named in notes, with the way: scope "raw". Default false.
scopeNotext (default): page-builder pages that a writer of this version writes are changed only in the texts, links and images their writer may change; matches in locked places are counted in locked_matches; the page-builder pages it changes get an undo point (those changed outside a writer up to 25 per call; warnings names the pages beyond). raw: the stored data as text everywhere, page code included (page-builder data needs unfiltered_html; a copy a page builder keeps in post_content_filtered, as SeedProd does, is not read), with an undo point for every page-builder page.
searchYesText to find (or PCRE pattern without delimiters when regex=true).
tablesNoTables to process: posts, postmeta, options, terms. Default ["posts","postmeta"].
replaceNoReplacement text. Default "" (removes the match).
case_insensitiveNoCase-insensitive matching. Default false.
stop_at_undo_capNoscope text: one call keeps undo points for up to 25 page-builder pages it changes outside a writer. Default false: the pages beyond them are written without one, as before, and warnings names them. true: the posts and postmeta scans stop before the first such page instead (truncated, with a note); next, sent back as after, continues there, so every page gets an undo point.
exclude_revisionsNotrue (default) skips post revisions; false includes them.
allow_without_undoNotrue writes a page-builder page whose undo point would be over the size limit, without a way back. Default false: such a page is not written. Any other failure to record the undo point still refuses the page. Applies to scope raw and to the pages a writer changes; in scope text a page changed outside a writer is written as before when its undo point cannot be recorded, and warnings names it.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed7 schema fields changed
    • changedInput schema / properties / allow_without_undo / description
      Previous value: -"Write a page-builder page whose undo point would be over the size limit, without a way back. Default false: such a page is not written. Any other failure to record the undo point still refuses the page. Applies to scope raw and to the pages a writer changes; in scope text a page changed outside a writer is written as before when its undo point cannot be recorded, and warnings names it."New value: +"true writes a page-builder page whose undo point would be over the size limit, without a way back. Default false: such a page is not written. Any other failure to record the undo point still refuses the page. Applies to scope raw and to the pages a writer changes; in scope text a page changed outside a writer is written as before when its undo point cannot be recorded, and warnings names it."
    • changedInput schema / properties / apply / description
      Previous value: -"Set true to write changes. Default false (dry-run preview)."New value: +"true writes the changes; false (default) returns the dry-run preview only."
    • changedInput schema / properties / exclude_revisions / description
      Previous value: -"Skip post revisions. Default true."New value: +"true (default) skips post revisions; false includes them."
    • changedInput schema / properties / limit / description
      Previous value: -"Max matched rows processed per table (1–2000). Default 200. When truncated=true, pass next back as after to continue; notes say why a scan stopped, and only where the row limit stopped it does a higher limit take more rows (page-builder pages stay at 25 per call: table builders, scope raw, stop_at_undo_cap). Rows the policy passes over do not count."New value: +"Max matched rows processed per table (1–2000). Default 200. When truncated=true, next, sent back as after, continues there; notes say why a scan stopped, and only where the row limit stopped it does a higher limit take more rows (page-builder pages stay at 25 per call: table builders, scope raw, stop_at_undo_cap). Rows the policy passes over do not count."
    • changedInput schema / properties / regex / description
      Previous value: -"Treat search as a PCRE regex (no delimiters; slower: every row of the id budget is read and tested in PHP, without a SQL prefilter). Matches the stored bytes only, without the encoded forms. In scope text, a page-builder page whose writer does not apply a pattern to its fields is left as it is and named in notes, with the way: scope \"raw\". Default false."New value: +"true treats search as a PCRE regex (no delimiters; slower: every row of the id budget is read and tested in PHP, without a SQL prefilter). Matches the stored bytes only, without the encoded forms. In scope text, a page-builder page whose writer does not apply a pattern to its fields is left as it is and named in notes, with the way: scope \"raw\". Default false."
    • changedInput schema / properties / stop_at_undo_cap / description
      Previous value: -"scope text: one call keeps undo points for up to 25 page-builder pages it changes outside a writer. Default false: the pages beyond them are written without one, as before, and warnings names them. true: the posts and postmeta scans stop before the first such page instead (truncated, with a note); pass next back as after to continue, so every page gets an undo point."New value: +"scope text: one call keeps undo points for up to 25 page-builder pages it changes outside a writer. Default false: the pages beyond them are written without one, as before, and warnings names them. true: the posts and postmeta scans stop before the first such page instead (truncated, with a note); next, sent back as after, continues there, so every page gets an undo point."
    • changedInput schema / properties / type / description
      Previous value: -"Post type filter for the posts table and the page-builder pages (postmeta is scanned for every post whose meta you may read and edit); a call without the posts table ignores it (flags.type_ignored). Default any."New value: +"Post type filter for the posts table and the page-builder pages (postmeta is scanned for every post whose meta the account may read and edit); a call without the posts table ignores it (flags.type_ignored). Default any."
  2. Added

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already flag destructiveHint=true, non-idempotent, and open-world, but the description adds extensive context beyond them: serialized/JSON-safe rewriting, skipped object values, locked places, undo-point behavior and caps, permission requirements (unfiltered_html, manage_options, multisite super admin), paging semantics, and precisely what is never touched (trash, revisions, transients, guid, credential-like meta, etc.). This is far richer than the annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The opening is front-loaded with purpose and alternatives, but the body is a dense wall of text with repeated statements (e.g., scope and undo-cap behavior restated in multiple places). While much of the detail is warranted for a complex tool, the presentation could be restructured for easier scanning without losing information.

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

Completeness5/5

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

For a 13-parameter, destructive, open-world tool with no output schema, the description covers the answer shape (per-table counts and previews, notes, warnings, skipped counts), paging continuation via 'after', limits, undo behavior, and permission gates. An agent has everything needed to call it safely and interpret the result.

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

Parameters5/5

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

Schema coverage is 100%, so baseline is 3, but the description adds meaningful semantics not present in the schema: plain mode finds encoded forms (JSON-escaped, HTML entities, block attributes), replacement is written in the same encoded form, regex mode matches stored bytes only, and scope 'text' follows writer field rules. These details materially help an agent choose parameter values correctly.

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 first sentence states a specific verb and resource ('search and replace across the site's stored data') and immediately distinguishes it from siblings: wp_search for find-only and wp_update_post for single-post edits. It then enumerates the tables covered, so an agent can tell exactly what this tool does and does not touch.

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

Usage Guidelines5/5

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

It explicitly names alternatives (wp_search, wp_update_post) and the conditions that select them, explains apply=false as a dry run vs apply=true as a write, and details when to choose scope 'text' vs 'raw'. The description goes further by stating safe-use constraints (undo caps, permissions, never-touched tables) that an agent needs before invoking.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources