Skip to main content
Glama
nkd3v
by nkd3v
README.md
# AI Site Manager MCP

An MCP server for the **AI Site Manager** WordPress plugin. Connect an MCP client to one or more sites' scoped API keys to work with posts, pages, custom post types, taxonomies, comments, media, approved settings, plugins and themes, and to migrate content between WordPress sites.

This is a local stdio MCP adapter. The AI Site Manager plugin must already be installed and activated on your WordPress site. It connects to that plugin's HTTPS API; it does not install the WordPress plugin or provide a hosted MCP endpoint.

## Install the WordPress companion

1. Download the [current ai-site-manager.zip](releases/ai-site-manager.zip?raw=true) from this repository. Tagged versions are also available on the [releases page](https://github.com/nkd3v/ai-site-manager-mcp/releases).
2. Upload it in **WordPress → Plugins → Add New → Upload Plugin**, then activate it. Requires WordPress 6.6+ and PHP 7.4+.
3. Open **Settings → AI Site Manager**. Create an expiring key, choose its user and scopes, and approve exact option names if settings access is needed.
4. Save the one-time key privately and copy the API base URL. Configure the MCP client below.

The companion source and disposable integration tests are in [wordpress-plugin/ai-site-manager](wordpress-plugin/ai-site-manager). Its [API guide](wordpress-plugin/ai-site-manager/docs/AI-GUIDE.md) describes native fields, permissions and operational limits. The companion's Python example sends an explicit User-Agent, and its HTTP test image has a valid PNG checksum.

## Run with npx

Requires **Node.js 22 or later**, npm, and Git for the GitHub package specifier.

```sh
export WP_AI_BASE='https://example.com/wp-json/ai-site-manager/v1'
# Supply WP_AI_KEY from your private environment or secret storage.
npx --yes github:nkd3v/ai-site-manager-mcp
```

The server waits for an MCP client to communicate over stdin/stdout. It does not open a browser. To check installation without credentials:

```sh
npx --yes github:nkd3v/ai-site-manager-mcp --version
```

The package runs directly from GitHub; npm registry publication is not required. To pin the current release, use `github:nkd3v/ai-site-manager-mcp#v1.4.1` instead of the unpinned specifier. Use a full commit SHA for an immutable pin.

For a local install:

```sh
npm install --global github:nkd3v/ai-site-manager-mcp
ai-site-manager-mcp --help
```

## Update an existing installation

Updating the MCP adapter and the WordPress companion are separate steps. An already running MCP server keeps using the code it started with until restarted.

1. Stop the server, or disconnect it in your MCP client.
2. Fetch and check the current MCP version without supplying credentials:

   ```sh
   npx --yes --prefer-online github:nkd3v/ai-site-manager-mcp --version
   ```

   For the theme-management update, expect `1.1.0` or later. npm caches packages; [`--prefer-online`](https://docs.npmjs.com/cli/npm-exec/#prefer-online) forces it to check for updates. If your MCP configuration pins an older tag or commit, such as `#v1.0.0`, change that package specifier too; checking the unpinned version does not update a pinned configuration. Use the unpinned specifier to follow the repository's default branch, or pin the commit you intend to run.
3. From companion `1.3.0`, WordPress offers new releases in **Dashboard → Updates** and the plugin list, and can update the companion automatically if you enable auto-updates for it. It verifies each ZIP against the release's `SHA256SUMS`. For older companions, or to update manually: download the [current WordPress companion ZIP](releases/ai-site-manager.zip?raw=true). In **WordPress → Plugins → Add New → Upload Plugin**, upload it and choose **Replace current with uploaded** when prompted. Theme support requires companion version `1.1.0` or later. Replacing the plugin preserves its keys and settings; do not uninstall it as part of the update.
4. With companion `1.4.1` or later, open **Settings → AI Site Manager**, choose **Edit permissions** beside an active key, adjust its scopes and approved option names, then **Save permissions**. Changes apply to the next API request using the same key; its owner and expiry are preserved. For theme access, enable the needed `themes:read`, `themes:write` and/or `themes:delete` scopes. Older companions require creating a replacement key and updating your client credentials.
5. Restart or reconnect the MCP server so the client refreshes its tool list and credentials. Call `aism_discover` to verify the companion version and key scopes, then `aism_themes_list` if you granted `themes:read`.

The MCP configuration below includes `--prefer-online` so subsequent launches check for updates. This does not update an already running process. If you installed the adapter globally instead of using npx, rerun `npm install --global github:nkd3v/ai-site-manager-mcp`, check `ai-site-manager-mcp --version`, and restart it.

## MCP client configuration

Add this entry to a client that accepts `mcpServers` configuration:

```json
{
  "mcpServers": {
    "ai-site-manager": {
      "command": "npx",
      "args": ["--yes", "--prefer-online", "github:nkd3v/ai-site-manager-mcp"],
      "env": {
        "WP_AI_BASE": "https://example.com/wp-json/ai-site-manager/v1",
        "WP_AI_KEY_FILE": "/absolute/path/to/ai-site-manager.key"
      }
    }
  }
}
```

The key file must contain **only the API key**, with an optional trailing newline. Keep it outside your repositories and restrict access to its owner (`chmod 600 /absolute/path/to/ai-site-manager.key`). An environment export file is a different format: source it in your shell, then launch the server using `WP_AI_KEY`, or use your MCP client's secret/environment mechanism. MCP clients launched from a desktop application may not inherit your shell environment. Client-specific configuration formats vary.

You can supply `WP_AI_KEY` directly instead of `WP_AI_KEY_FILE`; do not set both. Never place the key in command arguments, URLs, public examples or committed configuration.

When run in a terminal, the server prompts for a missing `WP_AI_BASE` and, if neither credential variable is set, `WP_AI_KEY_FILE`. Enter the HTTPS API namespace URL and the path to an existing plain-text key file. Values apply only to that process and are not saved. Existing environment values are kept, and supplying `WP_AI_KEY` skips the key-file prompt. Press Ctrl+C to cancel.

Prompts go to stderr, keeping stdout available for MCP messages. Automatic prompting requires both stdin and stderr to be terminals. Desktop MCP clients and other noninteractive launches must supply the variables in their configuration; missing values produce a startup error listing the variables to set.

## Several sites

To work with more than one site, for example to migrate between them, set `WP_AI_SITES_FILE` to a JSON file naming each site. Keys stay in separate files or environment variables; inline `key` entries are rejected.

```json
{
  "default": "old",
  "sites": {
    "old": { "base": "https://old.example.com/wp-json/ai-site-manager/v1", "key_file": "/absolute/path/old.key" },
    "new": { "base": "https://new.example.com/?rest_route=/ai-site-manager/v1", "key_env": "NEW_SITE_KEY", "auth_header": "X-AISM-Key" }
  }
}
```

Every site tool accepts an optional `site` argument with one of these names; `aism_sites` lists them. Without `site`, tools use `default`. With several sites and no default, `site` is required, so a write never goes to a guessed site. `WP_AI_BASE` plus `WP_AI_KEY` or `WP_AI_KEY_FILE` can be combined with the file: it adds a site named `WP_AI_SITE_NAME` (default `default`), which becomes the default unless the file names one. `WP_AI_TIMEOUT_MS` and `WP_AI_MAX_UPLOAD_BYTES` apply to every site.

## Migrate between WordPress sites

Install companion 1.4.0+ on both sites. On the **source**, create a key with `migration:read`. On the **target**, create a key with `migration:read` and `migration:write`, plus `plugins:write`/`themes:write` if packages should be transferred and `migration:delete` if you want rollback. Both key owners need administrator capabilities (`manage_options`, `export`/`import`; `unfiltered_html` on the target for metadata and settings). Configure both sites as above, then ask the AI to migrate. The intended sequence is:

1. `aism_migration_plan`: compares versions, themes, plugins, post types and taxonomies, detects earlier migrations and recommends options. For example, it suggests `match_slugs: true` when the target is a fresh install, so its default posts are replaced rather than duplicated.
2. `aism_migration_transfer_package` for each required theme (parents are handled automatically) and each active plugin. It copies the exact installed files from the source, which covers custom and premium code, or installs from WordPress.org with `from: "wordpress.org"`.
3. `aism_migration_run` with the returned `cursor` until `done` is true. Each call does as much as fits in `max_seconds`. The phases are terms → media (original files, same year/month folders, regenerated sizes) → all post types (including menus, templates, global styles and patterns) → comments → site settings (front page, permalinks, widgets, customizer) → finalize, which remaps IDs and rewrites URLs.
4. `aism_migration_status` to compare counts, then review the target. Re-running `aism_migration_run`, optionally with `modified_after`, syncs later changes without duplicating anything.
5. `aism_migration_rollback` if needed. It deletes what the migration created and restores the settings it changed.

`aism_migration_copy` copies selected posts with their terms, featured images, embedded media and reusable blocks (as drafts by default). User accounts are not created; authors are matched by login, then email, then `default_author` or `author_map`. The source is only read. Media files go through the MCP process within `WP_AI_MAX_UPLOAD_BYTES` and the target's upload limit. Offloaded media that the source cannot serve locally is fetched from its public URL without credentials. See the companion's [migration guide](wordpress-plugin/ai-site-manager/docs/AI-GUIDE.md#migrate-between-sites-140) for what is and is not migrated.

## Configuration

| Variable | Purpose | Default |
| --- | --- | --- |
| `WP_AI_BASE` | HTTPS API namespace URL; supports WordPress installed in a subdirectory and `https://example.com/?rest_route=/ai-site-manager/v1` | Required |
| `WP_AI_KEY` | Scoped API key | Required unless using a key file |
| `WP_AI_KEY_FILE` | Absolute path to a plain-text key file | Alternative to `WP_AI_KEY` |
| `WP_AI_AUTH_HEADER` | `Authorization` or `X-AISM-Key` | `Authorization` |
| `WP_AI_TIMEOUT_MS` | Request timeout, 1000–600000 milliseconds | `120000` |
| `WP_AI_MAX_UPLOAD_BYTES` | Local upload and migration download limit, up to 1 GiB; WordPress/host limits also apply | `33554432` (32 MiB) |
| `WP_AI_SITES_FILE` | JSON file of named sites (see [Several sites](#several-sites)) | Optional |
| `WP_AI_SITE_NAME` | Name for the `WP_AI_BASE` site | `default` |

## Tools

| Tools | Operations |
| --- | --- |
| `aism_discover`, `aism_guide`, `aism_schema` | Inspect scopes, expiry, resources, approved options and native schemas |
| `aism_content_list`, `aism_content_get` | Read/search content, terms, comments and native type/taxonomy/status discovery; pagination headers are included |
| `aism_content_create`, `aism_content_update`, `aism_content_delete` | Create drafts, update native fields/metadata, assign taxonomy/featured images, moderate comments, trash or permanently delete |
| `aism_revisions` | Read a revision list or one revision |
| `aism_media_upload` | Upload an operator-provided local image/media file; optional title, alt text, caption and parent post |
| `aism_settings_list`, `aism_settings_get`, `aism_settings_update` | Read or replace values of exactly approved settings |
| `aism_plugins_list`, `aism_plugin_install`, `aism_plugin_upload`, `aism_plugin_update`, `aism_plugin_action` | List/install/upload/activate/deactivate/update/delete plugins |
| `aism_themes_list`, `aism_theme_install`, `aism_theme_upload`, `aism_theme_action` | List/install/upload/activate/update/delete themes |
| `aism_sites` | List configured site connections |
| `aism_migration_manifest`, `aism_migration_export`, `aism_migration_plan`, `aism_migration_status` | Inspect sites, raw export pages, migration plans and progress (read-only) |
| `aism_migration_transfer_package`, `aism_migration_run`, `aism_migration_copy`, `aism_migration_rollback` | Transfer plugins/themes, migrate a whole site in resumable steps, copy selected posts, undo a migration |

The authenticated site guide is also available as the MCP resource `aism://guide`. Successful tool results include `{status, headers, data}`; native pagination headers appear in `headers`. API failures set MCP `isError` and include the status and error code. Credentials are redacted from results.

Start with `aism_discover`, then `aism_schema` for the relevant resource. `aism_content_create` defaults posts and pages to `draft`; publication requires an explicit `status`. Native JSON fields and query parameters pass through to the plugin. Use `context: "edit"` to read raw Gutenberg content; preserve it when editing. `aism_content_update` sends only the supplied fields. Structured settings updates replace the whole value, so read immediately before editing.

The server exposes all tools; the API independently enforces the key's scopes, approved option names and owner's current WordPress capabilities on every request. Read scopes do not permit edits or deletions. Plugin and theme installation adds executable code; grant those permissions only when intended. The gateway has no arbitrary SQL, PHP execution, user administration, private metadata access or remote-URL fetching. The tool hints identify reads and destructive operations; clients must still honor the operator's authorization.

Use `aism_plugin_update` with `plugin` from `aism_plugins_list`. Omit `file_path` for a WordPress-advertised update, or provide an operator-supplied local ZIP to replace that installed plugin (both MCP and companion 1.2.0+). The ZIP must have the same top-level plugin folder and main PHP filename and a strictly newer version. ZIP updates require `plugins:write` plus `update_plugins` and `upload_plugins`, preserve active/inactive status, and reject AI Site Manager itself, multisite mutations, incompatible packages and single-file plugins stored directly in the plugins root. `aism_plugin_upload` remains for new inactive installations. Re-list plugins after updating; inspect state after timeouts before retrying.

Theme support requires companion plugin 1.1.0 or later and a key issued with `themes:read`, `themes:write` and/or `themes:delete` as needed. Existing keys gain no additional permissions; create a new key to grant theme access. `aism_schema` accepts `themes`. Use the `stylesheet` identifier from `aism_themes_list` as the `theme` argument for actions. Installation leaves themes inactive and ZIP uploads never replace installed themes. Switching to another theme deactivates the current one; there is no standalone deactivate action. Deletion rejects the active theme and its parent. Updates use WordPress-advertised packages. Theme mutations support single-site WordPress only.

## Network behavior and troubleshooting

- HTTPS certificate validation remains enabled. Configure trusted certificates through Node's supported certificate configuration if your environment requires a private CA.
- Credentials go only to the configured API origin. Redirects are refused, including same-origin redirects. Configure the final canonical URL.
- The explicit `AI-Site-Manager-MCP/1.0` User-Agent avoids the default Python-urllib signature that some Cloudflare rules block. Host/firewall policies still apply.
- Requests are never automatically retried. After a timeout or failed upload, search/read state before retrying: WordPress may already have created the object or file. There is no idempotency, atomic compare-and-swap or rollback.
- Responses are limited to 16 MiB; use `per_page`, `page` and `_fields` for large collections. Uploads use multipart and enforce the local file limit before sending.
- A `401` means the key is missing, invalid, expired or revoked. A `403` can mean missing scopes, native capabilities, an unapproved setting, or a host/firewall rejection. Use `X-AISM-Key` if your host strips Authorization.
- The normal server writes only MCP protocol messages to stdout. Startup errors go to stderr. `--help` and `--version` print human-readable output and exit.

## Development

```sh
git clone https://github.com/nkd3v/ai-site-manager-mcp.git
cd ai-site-manager-mcp
npm ci
npm run check
npm test
npm pack --dry-run
```

The upload ZIP is built from an explicit allowlist of companion files; tests, credentials and local artifacts are excluded. To rebuild and verify it, install [uv](https://docs.astral.sh/uv/) and run:

```sh
uv run --system-certs scripts/package-plugin.py
```

`scripts/migration-e2e.mjs` runs a full two-site migration through the MCP server against disposable local WordPress sites; see the comments at its top. Tests exercise credential isolation, URL handling, pagination, redirects, uncertain writes, upload limits and real MCP tool/resource calls against simulated API responses. They never modify a live WordPress site. The source is plain JavaScript with no build or install scripts. Package contents are explicitly limited to source, documentation and license.

Every push to `main` must increase the MCP and companion versions together and rebuild the companion ZIP. The Release workflow rejects unchanged or reused versions, runs validation, and publishes `v<version>` at the pushed commit with the MCP tarball, WordPress upload ZIP, and `SHA256SUMS`. Check that the workflow and release succeeded after each push. Repository contributors and agents must follow [AGENTS.md](AGENTS.md).

Built using the [official MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk). The initial source commit is created through GitHub's commit API and verified for GitHub's GPG signature.

The JavaScript MCP adapter is MIT licensed. The separately distributed WordPress companion is GPL-2.0-or-later; see its [license](wordpress-plugin/ai-site-manager/LICENSE).

TDQS

B3.4/5.0

Scored across 31 tools

Disambiguation3/5

Most tools target clearly separate resources, but several boundaries are blurry: aism_plugin_update overlaps heavily with aism_plugin_action (which also performs updates), and the install/upload pairs (aism_plugin_install vs aism_plugin_upload, aism_theme_install vs aism_theme_upload) differ only by source in a way that requires careful reading. The migration cluster (run vs copy vs export vs transfer_package) is well described but still easy to misselect at a glance.

Naming Consistency4/5

Nearly all names follow a `aism_<resource>_<action>` snake_case pattern, with a few bare-noun outliers (aism_sites, aism_revisions, aism_schema, aism_guide, aism_discover) that lack an action verb. Minor singular/plural drift (aism_plugins_list vs aism_plugin_install, aism_themes_list vs aism_theme_action) is readable but not perfectly uniform.

Tool Count2/5

31 tools is well past the comfortable range for a single server, and the surface is inflated by near-duplicate pairs (plugin install/upload/update/action, theme install/upload/action). While the WordPress-management domain is genuinely broad, several of these could be collapsed into parameterized tools.

Completeness4/5

Coverage is strong: full content CRUD plus media upload, settings read/update, plugin and theme lifecycle, revisions, and an end-to-end migration lifecycle (plan, run, status, rollback, copy, export, package transfer). Gaps are modest and often explicitly documented as unsupported (revision mutation, self-update, multisite mutations, user creation, site connection management beyond listing).

Maintenance

ActivityMaintained
ResponsivenessNo issues