npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

goodlayers-mcp

v1.5.1

Published

MCP server for managing WordPress sites with Goodlayers page builder via SSH

Downloads

1,722

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 --setup

This single command:

  • Creates ~/.config/wordpress-mcp/ with a placeholder config.json
  • Creates snapshots/ and schemas/ 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 logging

Configuration 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        # ESLint

Deployment 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:

  1. Set up SSH key + deploy user on the server
  2. Add an entry to ~/.config/wordpress-mcp/config.json
  3. Run site_validate via 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