WP Manifestindependent plugin directory
manifest / ai / simple-mcp

Simple MCP

Приватний MCP-сервер для WordPress: власний ендпоінт поза REST API, персональні ключі з дзеркаленням ролей/прав WordPress, WP-CLI для адмінів (deny-list) + безпечні типізовані інструменти для контенту, Gutenberg-блоків, ACF, медіа та мультимовності.

by Vitalii Kaplia · github.com/vitaliikaplia/simple-mcp

1stars
1forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/vitaliikaplia/simple-mcp/archive/refs/heads/master.zip

Readme

Simple MCP

Приватний MCP-сервер для WordPress. Дає AI-асистенту (Claude Code) працювати з сайтом «наче він локальний»: доступ до WP-CLI (для адмінів) + безпечні інструменти для медіа, Gutenberg-блоків та ACF — через власний ендпоінт поза WP REST API.

Доступ — персональними ключами: кожен ключ належить конкретному WordPress-користувачу й дзеркалить його роль. Що може ключ, вирішують (1) матриця «Права ролей» у налаштуваннях плагіна і (2) нативні capabilities WordPress для typed-операцій над об'єктами.

Не для публікації. Для власних проєктів.

Автор: Vitalii Kaplia · Поточна версія: 2.3.0.

Чому не готовий плагін

Проаналізовано ai-engine, easy-mcp-ai, royal-mcp. Усі:

  • сидять на WP REST API (а якщо REST вимкнено для анонімів — їхній ендпоінт не працює);
  • не мають WP-CLI passthrough;
  • несуть баласт (OAuth-сервери, 5–7 таблиць, SEO/GA4/WooCommerce, телеметрію, upsell).

Simple MCP бере з них найкраще (media_handle_sideload, wp_slash+round-trip verify, ACF через update_field, hashed-токен, rate-limit, audit-log) і викидає решту.

Встановлення

  1. Плагін лежить у wp-content/plugins/simple-mcp. Активуй у Плагіни.
  2. Налаштування → Simple MCP → перевір шлях ендпоінта (типово simple-mcp), матрицю «Права ролей», rate-limit, IP-allowlist і шляхи до wp/CLI-php.
  3. Профіль користувача → Simple MCP — ключ доступу → «Згенерувати ключ». Скопіюй (показується раз, разом із готовою командою підключення).
  4. Якщо ролі потрібен wp_cli, перевір, що wp доступний веб-серверу і proc_open не вимкнено.

Модель доступу: користувач → роль → ключ

  • Ключ персональний (smcp-{user_id}-…), генерується на сторінці профілю користувача (свого — кожен сам; будь-чийого — адмін на екрані редагування користувача). У БД лише SHA-256.
  • Автентифікований HTTP-запит виконується від імені власника ключа (wp_set_current_user). Типізовані операції над WordPress-об'єктами додатково перевіряють його нативні права: автор не відредагує чужий пост, редактор не запише опції (manage_options), публікація вимагає publish_posts і т.д.
  • Матриця «Права ролей» в налаштуваннях вмикає групи інструментів per-role (включно з кастомними ролями): ядро контенту, блоки, мультимовність, контент і дискавері, wp_cli, серверні операції. Вимкнена група повністю прихована від агента (tools/list і виклики).
  • wp_cli запускається окремим привілейованим процесом і не успадковує object-level права користувача з HTTP-запиту. Тому wp_cli і серверні операції мають хард-лімит: лише ролі з manage_options; для інших це була б ескалація привілеїв.
  • Кілька ролей у користувача = об'єднання їх дозволів. Зміна ролі міняє права ключа миттєво (права резолвляться на кожен запит, не «запікаються» в ключ).
  • Сторінка налаштувань і матриця — лише для адмінів (manage_options); посилання «Налаштування» на екрані Плагіни теж бачать тільки адміни. Звичайні користувачі бачать на сайті лише секцію власного ключа у своєму профілі.

Ключі в профілі користувача

Профіль (profile.php) → «Simple MCP — ключ доступу». Тут кожен користувач із MCP-доступом керує своїм ключем; адмін відкриває цю ж секцію на екрані редагування будь-кого (user-edit.php).

  • Показано, які групи інструментів дає роль користувача, і чи має роль MCP-доступ узагалі.
  • Згенерувати ключ — plaintext та готова команда claude mcp add … показуються один раз (транзієнт до 5 хвилин, який видаляється після показу); у БД лягає лише SHA-256. Повторна генерація інвалідовує старий.
  • Відкликати ключ — миттєво вимикає підключення цього користувача.
  • Видалення користувача автоматично прибирає його ключ (uninstall/wp_delete_user).

Підключення в Claude Code

claude mcp add --transport http simple-mcp https://САЙТ/simple-mcp \
  --header "Authorization: Bearer ВАШ_ПЕРСОНАЛЬНИЙ_КЛЮЧ"

Готова команда з реальним ключем показується при генерації в профілі. Для локалки без HTTPS додай у wp-config.php: define('SIMPLE_MCP_ALLOW_INSECURE', true);

Тільки локальний клієнт (Claude Code CLI). Плагін автентифікується статичним Bearer-ключем і не реалізує OAuth-сервер, тож хмарний веб-інтерфейс claude.ai (Settings → Connectors → Add custom connector) підключити його не може — той потік очікує OAuth. Локальний сайт (*.test/localhost) з хмари теж недоступний. Використовуй Claude Code на машині, що бачить сайт; для віддалених інсталяцій — публічний HTTPS-домен. Перевірка: claude mcp listsimple-mcp: ✓ Connected.

Основний спосіб автентифікації — Authorization: Bearer …. Якщо проксі/FPM зрізає Authorization, підтримується запасний заголовок X-Simple-MCP-Key: ВАШ_КЛЮЧ.

Транспорт

  • MCP Streamable HTTP + JSON-RPC 2.0, protocol 2025-06-18.
  • Шлях ендпоінта налаштовується в адмінці (типово /simple-mcp) і ловиться на do_parse_requestне через register_rest_route, тому вимкнений REST API на анонімів на нього не впливає.
  • Методи: initialize, tools/list, tools/call, ping.
  • Автентифікований GET на ендпоінт повертає simple-mcp для health-check; без валідного ключа запит повертається у звичайний WordPress routing (типово це 404).

Інструменти

📖 Повний гайд для агентів: docs/MCP-GUIDE.md — модель контенту, рецепти й пастки (як не зламати блоки, мультимовність, опції). Ключові правила також прокидуються агенту через MCP instructions при підключенні.

Ядро

Інструмент Призначення
wp_cli Привілейований WP-CLI (без «wp»). Deny-list + блок метасимволів; wp-config та plugin/theme install/update/delete — лише з окремим дозволом, редагування файлів коду заборонене політикою.
get_post / update_post Читання / block-safe запис (wp_slash + запит ревізії + content_verified для тіла).
acf_get / acf_update ACF на пості/user/term/comment/опціях (не блокові поля).
upload_media · upload_begin · upload_chunk · upload_finish Медіа через media_handle_sideloadресайз + webp (chunked для великих, до 1 GB).

Блоки (ACF-поля всередині Гутенберг-блоків — inline в post_content)

Інструмент Призначення
block_get / list_block_fields Читання блоків сторінки / схема полів блоку (з ACF-реєстру).
block_update Безпечна правка ACF-поля(ів) блоку (server-side flattener + field_key mirror + verify).
block_insert / block_move / block_remove / block_replace Структура сторінки з JSON-специфікацій.

Мультимовність (детект wp-loc/WPML)

Інструмент Призначення
wploc_get_translations / wploc_link_translation / wploc_create_translation Резолв/лінк/створення перекладів (trid, slug↔wpml_code).

Контент і дискавері

Інструмент Призначення
create_post Створити пост/сторінку/CPT з block-safe тілом.
render_post Рендер do_blocks HTML для верифікації.
safe_delete Translation-aware видалення (не каскадить переклади).
describe_site Схема форку: блоки+поля, ACF-опції, CPT/таксономії, мовна мапа; кеш 1 год, refresh:true перебудовує.

Загальний CRUD термів і plain Settings-API options виконується через wp_cli, якщо ця група доступна ролі. Типізовані acf_* працюють зі значеннями ACF термів/опцій, а wploc_* — зі зв'язками перекладів; окремого typed tool для створення/редагування термів немає.

Права ролей (матриця в адмінці)

Налаштування → Simple MCP → Права ролей. Одна таблиця: рядки — групи інструментів, колонки — всі ролі (включно з кастомними). Вимкнена для ролі група повністю прихована від агента (не в tools/list, не викликається), а instructions при конекті підлаштовуються під конкретного користувача:

  • MCP-доступ (ядро контенту) — головний тумблер ролі; off = роль без MCP взагалі.
  • wp_cli, Серверні операції — лише для ролей з manage_options (хард-лімит).
  • Блоки, Контент і дискавері — за потреби.
  • Мультимовність — з авто-детектом: якщо WP-LOC/WPML нема — група прихована для всіх.

Дефолти дзеркальні: administrator — усе (server ops off); editor — ядро контенту + блоки + мультимовність + контент і дискавері (усе, крім wp_cli і серверних операцій); author — лише ядро (нативні caps обмежують його своїми постами); решта (включно з кастомними) — off.

Безпека

  • HTTPS-only (крім SIMPLE_MCP_ALLOW_INSECURE для локалки).
  • Персональні ключі: smcp-{user_id}-{64 симв.}, у БД лише SHA-256 (user meta), звірка hash_equals. Основний транспорт секрету — Authorization: Bearer; запасний, якщо цей заголовок зрізає проксі, — X-Simple-MCP-Key. Ключ ніколи не передаємо в URL, щоб він не тікав у логи/проксі. Відкликання — кнопкою в профілі; видалення користувача теж інвалідовує ключ.
  • Два шари авторизації typed tools: матриця ролей (які групи інструментів видно) + нативні WordPress-capabilities на кожну операцію над WP-об'єктом (edit_post на конкретний пост, publish_posts, upload_files, manage_options, delete_post, …). wp_cli — навмисний привілейований виняток, тому окремо обмежений manage_options-ролями.
  • Deny-list для руйнівних команд (db drop, db reset, site empty, eval, …) — спільний для всіх ключів.
  • Серверні операції (wp-config directives + plugin/theme install/update/delete) — за замовчуванням заблоковані; вмикаються в матриці per-role (конфіг і набір плагінів законно різняться між середовищами; тема сайту й Simple MCP мають окремі versioned sources). Читання конфігу (config get/list) дозволене завжди. Руйнівне агент має перепитувати.
  • Rate-limit по користувачу (типово 120/хв; 0 вимикає; невалідні спроби — штрафна пауза по IP), опційний IP-allowlist: точний IPv4/IPv6 або IPv4 CIDR; джерелом IP вважається лише REMOTE_ADDR.
  • Audit-log кожного tools/call інструмента з прив'язкою до користувача (таблиця {prefix}simple_mcp_log). Перегляд у Налаштування → Simple MCP → Останні виклики: фільтр за діапазоном дат (від/до), пагінація (10 записів на сторінку) і кнопка «Очистити лог». Ретенція — 30 днів (щоденний cron), тож таблиця не росте безмежно.
  • Kill-switch: define('SIMPLE_MCP_DISABLE', true); у wp-config.php.
  • SSRF-захист на завантаження з URL (блок приватних діапазонів).

wp_cli — це керований RCE за задумом, тому він структурно недоступний ролям без manage_options. Адмінський ключ = адмін-пароль. Рекомендація: обкатати на локалці → staging, на проді — IP-allowlist/VPN і ключі з мінімально потрібними ролями.

Про deny-list. Команди виконуються токенізовано, без шелла (proc_open argv), тож чейнінг (;, &&, `, $()), лапкові трюки (db "drop") і провідні глобальні прапорці (--quiet db drop) не обходять фільтр; --exec/--require/--ssh/--http заблоковані окремо. Але з увімкненим wp_cli deny-list — це запобіжник від випадковостей, а не пісочниця: адмін із ключем все одно може досягти руйнівного ефекту іншою командою (напр. db query). Це прийнята модель (адмінський ключ = повний доступ). Хочеш жорсткого обмеження — видай ключ користувачу з вужчою роллю (editor/author): він працюватиме лише типізованими інструментами в межах своїх нативних прав.

Про upload_media з url. Є SSRF-гейт (схема http/https + перевірка A/AAAA на приватні діапазони) плюс core wp_safe_remote_get. Залишковий ризик — DNS-rebinding, тому для недовірених джерел завантажуй через base64, а не url.

Авто-оновлення через GitHub

Плагін оновлюється стандартним механізмом WordPress із публічного репозиторію vitaliikaplia/simple-mcp:

  • Раз на 12 год (невдалу перевірку кешує на 1 год; ручна Оновлення → Перевірити знову передає ?force-check=1) читається Version: із raw.githubusercontent.com/.../simple-mcp.php.
  • Якщо версія на GitHub новіша за встановлену — з'являється звичайне «Доступне оновлення».
  • Пакет — zip гілки (archive/refs/heads/<branch>.zip); тека нормалізується під slug simple-mcp.
  • Щоб випустити оновлення: однаково підніми Version: у заголовку і SIMPLE_MCP_VERSION у simple-mcp.php, онови changelog у README та в class-simple-mcp-github-updater.php, перевір PHP lint і запуш у release-гілку.

Типова гілка — master (як у wp-loc). За потреби перевизначається константою define('SIMPLE_MCP_GITHUB_BRANCH', '<гілка>'); у wp-config.php.

Константи (wp-config.php)

Константа Дія
SIMPLE_MCP_DISABLE true — миттєво вимкнути сервер.
SIMPLE_MCP_ALLOW_INSECURE true — дозволити HTTP (лише для локалки).
SIMPLE_MCP_WP_BIN Шлях до бінарника wp, якщо не в PATH.
SIMPLE_MCP_PHP_BIN Шлях до CLI-php для wp-cli.
SIMPLE_MCP_GITHUB_BRANCH Гілка для авто-оновлення (типово master).

Вимоги

PHP 8.1+, WordPress 6.0+, WP-CLI на сервері (для wp_cli) і доступний proc_open. ACF-інструменти — за наявності ACF.

Зміни

2.3.0 — технічний minor-реліз

  • Синхронно піднято версійний заголовок, runtime-константу й релізні метадані до 2.3.0.

2.2.0 — повна синхронізація документації

  • README, agent guide, AGENTS.md, MCP initialize instructions, описи інструментів і підказки адмінки звірено з фактичною реалізацією.
  • Уточнено межі typed tools і привілейованого wp_cli, capability-перевірки, content_verified/ревізії, авторизаційні заголовки, кеші, upload limits і release-процес.
  • Задокументовано всі 23 інструменти, ACF comment targets, term/plain-option обмеження та актуальний changelog 2.1.0.

2.1.0 — авторський URL і релізні метадані

  • Авторський URL у заголовку плагіна та WordPress-вікні деталей оновлено на kaplia.pro.
  • Версійний заголовок і SIMPLE_MCP_VERSION синхронно піднято до 2.1.0.

Read the full README on GitHub →