
Automating WordPress edits often becomes a poor choice between SSH credentials, fragile commands, and overly generic APIs. mcp-wp-go is an MCP server written in Go that uses WordPress's native REST API to create, edit, publish, unpublish, validate posts, and manage media — without running remote shell on the server. The idea is to give AI agents a controlled interface to operate content, while keeping WordPress's own permissions, hooks, and cache in the pipeline.
The problem: editorial automation should not depend on SSH
SSH and WP-CLI remain excellent for host maintenance, but they are not the best frontier for routine editorial tasks. An agent that only needs to create a draft, upload an image, or check if a URL is public should not receive unrestricted access to the operating system. The WordPress REST API already offers authentication, per-user capabilities, and endpoints for posts, media, categories, and tags.
mcp-wp-go connects this API to Model Context Protocol (MCP). In practice, the MCP client communicates via stdio with the local binary; the binary communicates with a single configured WordPress via HTTPS. The site URL is not accepted as a tool argument, preventing a call from being redirected to another destination.
How the architecture works
- MCP Client: Codex, Claude Code or another client calls typed tools.
- mcp-wp-go: local Go process;
stdoutis reserved for the protocol and logs go tostderr. - WordPress REST API: receives authenticated calls via an app password, not the server password.
- WordPress: applies user permissions, hooks, and cache integration from the installation itself.
This design does not replace WordPress access control: it makes it the central layer. Create an exclusive app password for automation, use a user with the smallest set of capabilities that gets the job done, and revoke the password if it gets exposed. Never put the password in Git, README, logs, or in the versioned configuration file of the MCP client.
What mcp-wp-go does
The project organizes the tools into four groups:
- Posts: list, read editable HTML, create drafts, update content, publish, unpublish, and send to trash.
- Media: list, get metadata, upload GIF, JPEG, PNG or WebP, update alt text/caption, and delete.
- Covers: upload an image, place it as the first element in the body, and use the relative URL returned by the site itself. The tool does not set a featured image, avoiding duplication in themes that render it separately.
- Validation: query categories and tags, test authentication and verify if a post is published and if its permalink returns HTTP 2xx.
In recent versions, wordpress_get_post also returns featured_media. This allows a QA routine to confirm that the cover is in the body and was not unintentionally marked as a featured image.
Installation on Linux
The project requires Go 1.27 or newer to compile. Clone the repository, run the tests, build the binary and install it to the user's default local directory. Sensitive configuration stays outside the clone:
git clone https://github.com/jniltinho/mcp-wp-go.git
cd mcp-wp-go
make check
make build
# Instala o binário para o usuário atual.
install -D -m 0755 dist/mcp-wp-go "$HOME/.local/bin/mcp-wp-go"
# Cria uma configuração privada fora do repositório.
install -d -m 700 "$HOME/.config"
install -m 600 .env.example "$HOME/.config/mcp-wp-go.env"
$EDITOR "$HOME/.config/mcp-wp-go.env"
command -v mcp-wp-go
The build artifact is at dist/mcp-wp-go, but the stable path used by the client is ~/.local/bin/mcp-wp-go. This way, the clone can stay in any directory and be updated or removed without breaking the MCP configuration. If ~/.local/bin is not yet in the PATH of the session, use the absolute path in the client or add it to the shell configuration. The environment loader understands simple lines CHAVE=VALOR; it does not perform shell expansion or hidden commands.
WP_BASE_URL=https://wp.exemplo.com
WP_USERNAME=editor-automacao
WP_APP_PASSWORD=senha-de-aplicativo-do-wordpress
WP_TIMEOUT=30s
WP_MAX_UPLOAD_BYTES=26214400
# Recomendado: limita quais diretórios locais podem ser lidos para upload.
WP_UPLOAD_ROOT=/srv/capas
No use the root password, the normal WordPress account password, or database credentials. The application password is specific to this integration and can be revoked independently.
Register with the MCP client
Store sensitive configuration outside the repository and point the client to absolute paths:
{
"mcpServers": {
"wordpress_go": {
"type": "stdio",
"command": "/home/operador/.local/bin/mcp-wp-go",
"args": ["--env-file", "/home/operador/.config/mcp-wp-go.env"]
}
}
}
After reloading the client, call wordpress_site_health. The response identifies the authenticated user but does not expose the password. This is the first test before any editorial change.
Secure flow: draft, cover, publish, and check
A predictable editorial flow starts with a draft. First, use wordpress_list_categories and wordpress_list_tags to reuse existing taxonomies; then create the post in draft. Creation closes comments automatically.
{
"title": "Novo guia técnico",
"content": "<p>Introdução do artigo.</p>",
"status": "draft",
"categories": [46],
"tags": [311, 31]
}
Next, use wordpress_set_post_cover with a local WebP image and a alt_text descriptive. The tool only accepts allowed regular images, checks type and extension, respects the configured limit, and can restrict reading to WP_UPLOAD_ROOT.
Publishing and unpublishing were separated from common editing. The tools wordpress_publish_posts and wordpress_unpublish_posts accept from one to a hundred unique IDs, but require explicit confirmation:
{ "ids": [123, 124], "confirm": true }
Batch operations are not transactional: if one ID fails, the others may have already been processed. That's why the response lists the result of each post. Before bulk publishing, validate the selection with wordpress_get_post or wordpress_list_posts.
Finally, wordpress_check_post_live confirms two things: the post status is publish and the public permalink returns HTTP 2xx. For a cover, also check featured_media, the first image in HTML and the visual result in the browser. Automation reduces repetitive work; it does not eliminate editorial review.
Protections against common errors
- Deleting a post or media requires
confirm: true; the default is moving to trash. Permanent deletion requirespermanent: true. - Editing a post does not change slug, date, or status. Status changes have their own tools and mandatory confirmation.
- Upload does not accept arbitrary files: GIF, JPEG, PNG and WebP go through extension, signature and size validation.
- The HTTP client limits redirects and does not allow a redirect to leave the configured WordPress host.
- The public check rejects permalinks outside the configured host, reducing the risk of using a URL returned by the API to make external requests.
There is an important difference between restricting host access and solving all content security. An agent can still write bad text, delete a post if it receives confirmation, or reproduce a malicious instruction from another source. Work with drafts, do human review before destructive changes, and maintain WordPress backups and revision history.
Go, testing, and releases
O projeto usa a SDK oficial do MCP para Go e mantém main.go na raiz do repositório. O Makefile oferece make fmt, make vet, make test and make check. Os testes cobrem, entre outros pontos, fechamento de comentários na criação, URL relativa de capa, validação de featured_media e mudança de status sem alterar outros campos.
As tags acionam GitHub Actions. A release v0.2.0 publica pacotes para Linux amd64, macOS arm64 e Windows amd64, com notas de versão revisadas. Isso facilita testar o mesmo servidor MCP em estações de trabalho e servidores sem exigir que cada operador compile Go localmente.
Where this project fits in
O mcp-wp-go é uma peça de automação editorial, não uma substituição para observabilidade, backup ou hardening do WordPress. Ele combina bem com uma rotina que gera imagens, pesquisa fontes, redige rascunhos e valida links; para conteúdo técnico, é útil aplicar a mesma disciplina de mudança que já usamos em infraestrutura. Quem mantém agentes e ferramentas também pode aproveitar o guia de OpenObserve no Ubuntu para centralizar logs e investigar falhas de integração.
O projeto é aberto e recebe contribuições no GitHub. Antes de usar em produção, leia o README, ajuste as permissões do usuário WordPress e teste em um ambiente não crítico.
Sources: repositório e README do mcp-wp-go · release v0.2.0 · SDK oficial MCP para Go · WordPress REST API · WordPress Application Passwords.