Введение
Если вы хотите управлять своим WordPress-сайтом через внешние инструменты, например Claude, удобным способом будет использовать MCP-сервер. В этой статье мы разберём, как создать такой сервер на Python с поддержкой WPML для мультиязычности.
1. Архитектура сервера
Мы используем библиотеку FastMCP для реализации MCP-сервера. Сервер умеет:
- Получать список постов.
- Получать один пост по ID.
- Создавать посты.
- Обновлять посты.
- Работать с языком поста через WPML (lang параметр).
Конфигурация подключения к WordPress хранится в отдельном .ini файле, что позволяет легко менять учётные данные и URL сайта.
2. Конфигурационный файл
Создайте файл wordpress.ini в той же папке, что и скрипт MCP:
[wordpress]
url = https://example.com
user = your_username
app_password = your_application_password
Где взять пароль: этот пароль нужно создать на сайте, зайдя в профиль пользователя и выбрав опцию создания пароля приложения.
3. Основной код MCP-сервера
import os
import configparser
import requests
from typing import Optional, Dict
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("WordPress-MCP-Server")
# --- load config ---
config = configparser.ConfigParser()
config_path = os.path.join(os.path.dirname(__file__), 'wordpress.ini')
config.read(config_path)
WP_URL = config['wordpress']['url']
WP_USER = config['wordpress']['user']
WP_APP_PASSWORD = config['wordpress']['app_password']
auth = (WP_USER, WP_APP_PASSWORD)
# --- helper function ---
def wp_request(method: str, endpoint: str, data: Optional[Dict] = None, lang: Optional[str] = None):
url = f"{WP_URL.rstrip('/')}/wp-json/wp/v2/{endpoint.lstrip('/')}"
params = {}
if lang:
params['lang'] = lang # WPML language parameter
resp = requests.request(method, url, auth=auth, json=data, params=params)
resp.raise_for_status()
return resp.json()
# --- MCP tools ---
@mcp.tool()
def list_posts(status: str = "publish", per_page: int = 10, lang: Optional[str] = None):
"""Return a list of posts in the specified language"""
return wp_request('GET', f'posts?status={status}&per_page={per_page}', lang=lang)
@mcp.tool()
def get_post(post_id: int, lang: Optional[str] = None):
"""Return a single post by ID in the specified language"""
return wp_request('GET', f'posts/{post_id}', lang=lang)
@mcp.tool()
def create_post(title: str, content: str, status: str = "draft", lang: Optional[str] = None):
"""Create a new post in the specified language"""
endpoint = 'posts'
if lang:
endpoint += f"?lang={lang}"
data = {"title": title, "content": content, "status": status}
return wp_request('POST', endpoint, data)
@mcp.tool()
def update_post(post_id: int, title: Optional[str] = None, content: Optional[str] = None,
status: Optional[str] = None, lang: Optional[str] = None):
"""Update an existing post in the specified language"""
data = {}
if title is not None:
data['title'] = title
if content is not None:
data['content'] = content
if status is not None:
data['status'] = status
if not data:
return {"error": "No data to update"}
endpoint = f'posts/{post_id}'
if lang:
endpoint += f"?lang={lang}"
return wp_request('POST', endpoint, data)
if __name__ == "__main__":
print("WordPress MCP server running with WPML language support...")
mcp.run()
4. Использование MCP-сервера
Примеры вызовов функций через MCP:
Получить посты на французском:
list_posts(lang="fr")
Получить конкретный пост на немецком:
get_post(123, lang="de")
Создать пост на испанском:
create_post("Hola mundo", "Contenido de prueba", status="publish", lang="es")
Обновить пост на английском:
update_post(456, title="Updated title", lang="en")
WPML создаёт отдельные записи для каждого языка. Этот MCP умеет работать с языком через параметр lang, но автоматическая привязка переводов между языками здесь невозможна без дополнительных расширений.
С помощью такого MCP-сервера можно интегрировать WordPress с внешними инструментами и управлять контентом на разных языках. Структура сервера простая, безопасная и расширяемая: можно добавлять дополнительные функции, например работу с категориями, тегами или медиафайлами.
Если хочешь, можно дополнительно сделать конфиг с языком по умолчанию, чтобы не передавать lang в каждом вызове, и это ещё больше упростит работу с мультиязычным контентом.
