goodlayers-mcp
v1.5.1
Published
MCP server for managing WordPress sites with Goodlayers page builder via SSH
Downloads
1,722
Maintainers
Readme
WordPress Goodlayers MCP Server
An MCP (Model Context Protocol) server that gives Claude Code structured, safe access to WordPress sites running the Goodlayers page builder. Manage pages, layouts, menus, media, files, and site options across multiple client sites — all through natural conversation with Claude Code.
The Problem
Goodlayers stores entire page layouts as PHP serialized data in wp_postmeta. This format uses byte-counted strings — a single wrong character corrupts the entire page. Manually editing these layouts is error-prone and dangerous.
This MCP server handles all serialization/deserialization via WP-CLI on the remote server, presenting layouts as clean JSON that Claude Code can safely reason about and manipulate.
Features
- 22 MCP tools across 8 functional areas (pages, layouts, menus, media, files, options, snapshots, site management)
- Auto-snapshot safety — every destructive write is captured before execution; rollback is always one tool call away
- Multi-site support — config-driven site management with per-client SSH isolation
- Zero-code onboarding — add new sites with a config entry and SSH key, no code changes
- Path-guarded file I/O — file operations restricted to child theme and custom plugin directories
- Goodlayers layout composition — build page layouts from declarative JSON specs using the 60-column grid system
- Schema extraction — auto-extract element type definitions from the live Goodlayers plugin
Architecture
Claude Code → MCP Tool Call → Config Lookup (siteKey) → SSH → WP-CLI → WordPress- stdio transport — runs as a local subprocess, no server infrastructure needed
- Per-site SSH connections with lazy-connect and connection pooling
- All PHP serialization happens remotely via
wp eval-file— never in TypeScript - Client isolation — each site has its own SSH key and config; no cross-client access
Quick Start
Prerequisites
- Node.js 22+
- SSH access to your WordPress server(s)
- WP-CLI installed on the remote server(s)
- Goodlayers theme active on the target site(s)
Setup
npx goodlayers-mcp --setupThis single command:
- Creates
~/.config/wordpress-mcp/with a placeholderconfig.json - Creates
snapshots/andschemas/directories - Registers the MCP server with Claude Code
Then edit ~/.config/wordpress-mcp/config.json with your site's SSH credentials:
{
"sites": {
"mysite": {
"host": "203.0.113.10",
"user": "deploy",
"sshKeyPath": "~/.ssh/id_ed25519",
"wpPath": "/var/www/mysite/public_html",
"childThemeDir": "/var/www/mysite/public_html/wp-content/themes/flavor-child",
"customPluginDir": "/var/www/mysite/public_html/wp-content/plugins/mysite-custom"
}
}
}Validate
Start a Claude Code conversation and ask it to validate your site:
"Validate the mysite WordPress connection"
Claude Code will call site_validate and report on SSH, WP-CLI, WordPress, Goodlayers, and directory access.
Tools Reference
Site Management
| Tool | Description |
|------|-------------|
| site_info | Get URL, theme, plugins, PHP version |
| site_validate | Health check (SSH, WP-CLI, WordPress, Goodlayers, directories) + auto-schema extraction |
Page Management
| Tool | Description |
|------|-------------|
| page_list | List pages with optional status/search filters |
| page_read | Read full page layout as JSON |
| page_create | Create new page with title, slug, status, and layout |
| page_update | Update page content, layout structure, or both |
| page_delete | Delete page (auto-snapshot first) |
Goodlayers Layout
| Tool | Description |
|------|-------------|
| schema_extract | Extract element type definitions from live plugin and cache by version |
| layout_compose | Compose a layout from declarative JSON spec (no write) |
Menu Management
| Tool | Description |
|------|-------------|
| menu_list | List all menus with items and hierarchy |
| menu_add_item | Add menu item (post, custom link, or category) |
| menu_remove_item | Remove menu item by ID |
| menu_reorder | Reorder menu items by ID array |
Snapshot Safety
| Tool | Description |
|------|-------------|
| snapshot_list | List snapshots for a site with optional date filtering |
| snapshot_restore | Restore page from snapshot (double-snapshotted for safety) |
Media
| Tool | Description |
|------|-------------|
| media_upload | Import image from URL or file path |
| media_list | List media items with optional search/type filters |
Site Options
| Tool | Description |
|------|-------------|
| option_get | Read WordPress option |
| option_set | Set WordPress option (auto-snapshot current value) |
File Management
| Tool | Description |
|------|-------------|
| file_read | Read file from child theme or custom plugin (restricted paths only) |
| file_write | Write file to child theme or custom plugin (restricted paths, auto-snapshot) |
| css_append | Append CSS rules to child theme custom.css |
Usage Examples
Once the MCP server is configured, just talk to Claude Code naturally:
Read a page layout:
"Show me the layout of page 5420 on mysite"
Build a new page:
"Create a new Services page with a hero section, three feature columns, and a CTA button"
Edit existing content:
"Update the homepage hero title to 'Welcome to Our New Site'"
Manage menus:
"Add the new Services page to the main navigation menu"
Upload media:
"Upload this logo image and add it to the header"
Rollback a change:
"List recent snapshots for mysite and restore the previous version of page 5420"
Add custom CSS:
"Add a CSS rule to make the hero section full-width on mobile"
How Goodlayers Layouts Work
Goodlayers stores page layouts as a tree structure in wp_postmeta:
Page (array of wrappers)
├── Wrapper (type: "background" — a full-width section)
│ ├── value: {style/layout properties}
│ └── items: [columns]
│ ├── Column (type: "column", size: "1/2", "1/3", etc.)
│ │ └── items: [elements]
│ │ ├── Element (type: "title", "text-box", "button", etc.)
│ │ │ └── value: {element-specific properties}
│ │ └── ...
│ └── ...
└── ...The grid system uses 60 columns: 60 = full width, 30 = half, 20 = third, 15 = quarter.
This structure is stored as PHP serialized data (byte-counted strings). The MCP server handles all serialization via WP-CLI on the remote server, so Claude Code works with clean JSON.
Safety
- Auto-snapshots — every destructive operation (page update, delete, option set, file write) captures the current state before executing. Snapshots are stored locally at
~/.config/wordpress-mcp/snapshots/{siteKey}/ - Double-snapshot on restore — restoring a snapshot first captures the current state, so you can undo the undo
- Path guard — file operations are restricted to configured directories (child theme, custom plugin). Traversal attempts are rejected before any SSH execution
- Client isolation — per-site SSH keys and config; Claude Code passes a site key, never raw credentials
- No arbitrary PHP — all PHP execution is scoped to specific WP-CLI operations
Project Structure
src/
├── index.ts # Entry point, config loader, server bootstrap
├── server.ts # MCP server instantiation + tool registration
├── config/ # Configuration & site lookup
│ ├── types.ts # SiteConfig interface
│ ├── loader.ts # Load & validate config.json
│ └── validator.ts # Zod schemas for config validation
├── connection/ # SSH connection & WP-CLI execution
│ ├── manager.ts # SSH connection pool (lazy-connect, keepalive)
│ ├── executor.ts # execWpCli + execWpCliWithPhp runners
│ └── types.ts # WpCliResult, WpCliOptions interfaces
├── goodlayers/ # Goodlayers page builder integration
│ ├── types.ts # GoodlayersElement, Column, Wrapper, Page types
│ ├── codec.ts # readLayout, writeLayout, roundTripVerify
│ ├── composer.ts # createWrapper, addColumn, addElement helpers
│ └── validator.ts # validateElementProperties, loadElementSchema
├── safety/ # Snapshot & security
│ ├── snapshot.ts # createSnapshot, withSnapshot wrapper
│ ├── path-guard.ts # Path validation for file operations
│ └── types.ts # SnapshotOptions, SnapshotMetadata
├── tools/ # MCP tool handlers (22 tools)
│ ├── site/ # site_info, site_validate
│ ├── pages/ # page_list, page_read, page_create, page_update, page_delete
│ ├── goodlayers/ # schema_extract, layout_compose
│ ├── layout/ # Layout composition support
│ ├── snapshots/ # snapshot_list, snapshot_restore
│ ├── menus/ # menu_list, menu_add_item, menu_remove_item, menu_reorder
│ ├── media/ # media_upload, media_list
│ ├── options/ # option_get, option_set
│ └── files/ # file_read, file_write, css_append
└── util/ # Utilities
├── errors.ts # Custom error classes + formatToolError
└── logger.ts # stderr loggingConfiguration Reference
| Field | Required | Default | Description |
|-------|----------|---------|-------------|
| host | yes | — | SSH hostname or IP address |
| user | yes | — | SSH username |
| sshKeyPath | yes | — | Absolute path to SSH private key |
| wpPath | yes | — | WordPress installation path on server |
| port | no | 22 | SSH port |
| wpBinary | no | wp | WP-CLI binary name or full path |
| commandTimeout | no | 30000 | SSH command timeout (ms) |
| childThemeDir | no | — | Child theme directory path |
| customPluginDir | no | — | Custom plugin directory path |
| allowedPaths | no | — | Additional allowed paths for file operations |
Development
npm run dev # Run with tsx (hot reload)
npm run build # Compile TypeScript → dist/
npm test # Run Vitest test suite
npm run typecheck # Type checking without emitting
npm run lint # ESLintDeployment Pipeline
A GitHub Actions workflow template is included at .github/workflows/deploy.yml for automated deployment (push to main → SSH pull on server). See ONBOARDING.md for full setup instructions including deploy key provisioning.
Adding a New Site
See ONBOARDING.md for the complete step-by-step guide. The short version:
- Set up SSH key + deploy user on the server
- Add an entry to
~/.config/wordpress-mcp/config.json - Run
site_validatevia Claude Code — it proves everything works and auto-extracts the Goodlayers schema
No code changes required.
Tech Stack
- TypeScript — type-safe implementation with Zod validation throughout
- @modelcontextprotocol/sdk — official MCP SDK
- node-ssh — SSH connection management
- Zod — runtime schema validation
- Vitest — test framework
License
ISC
