MCP server for AI assistants

Easy Blog Networks runs a hosted Model Context Protocol (MCP) server at https://app.easyblognetworks.com/mcp/. Connect Claude Code, Claude Desktop, Cursor or any other MCP client to it once and the assistant can list the blogs on the account and write, edit and manage posts, pages, media, categories, tags and site settings on every one of them. Nothing is installed on the blogs: the server forwards each call to the blog’s core WordPress REST API with the application password EBN already holds for Automated Content.

Setup

The server speaks the Streamable HTTP transport in its stateless form: one JSON-RPC 2.0 message per POST, answered with JSON. Authentication is the same HTTP Basic credential the REST API takes, the account email and the API key from the Account Settings page:

echo -n "EMAIL:API_KEY" | base64

The Settings page shows the snippets below with the token already filled in.

Claude Code:

claude mcp add --transport http easyblognetworks \
    https://app.easyblognetworks.com/mcp/ \
    --header "Authorization: Basic TOKEN"

Cursor (mcp.json):

{
  "mcpServers": {
    "easyblognetworks": {
      "url": "https://app.easyblognetworks.com/mcp/",
      "headers": {"Authorization": "Basic TOKEN"}
    }
  }
}

Claude Desktop does not send custom headers to remote servers yet, so it goes through the mcp-remote bridge (claude_desktop_config.json, needs Node.js):

{
  "mcpServers": {
    "easyblognetworks": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://app.easyblognetworks.com/mcp/",
               "--header", "Authorization: Basic TOKEN"]
    }
  }
}

A collaborator API key works the same way and only sees the networks it was given. Regenerating the API key invalidates the token.

Tools

Network tools read EBN’s database:

list_networks

Networks on the account with blog counts and limits.

list_blogs

Blogs with ID, domain, network, state, HTTPS and rest_api_enabled, optionally for one network.

get_blog

State, DNS, WordPress stats, health score and last backup of one blog.

list_backups

The backup EBN keeps for a blog. Download links come from the REST API.

enable_rest_api

Issues the blog a new WordPress application password through croner, the same as the “Enable REST API” button on the blog page. Takes about a minute.

create_blog

Creates and deploys a new blog in a network, with the same options as the REST API (title, tagline, theme, plugins, slots, HTTPS). Account key only.

delete_blog

Schedules a blog for deletion in 24 hours, like the button on the blog page; the deletion can be cancelled there until then. Account key only.

Blog tools take a blog_id, check the caller may see that blog, and forward to /wp-json/wp/v2/ on the blog with context=edit so the agent gets raw, editable content. Only core WordPress endpoints are used, so EBN Core’s post limits and blacklists still apply:

  • list_posts, get_post, create_post, update_post

  • list_pages, get_page, create_page, update_page

  • list_media, upload_media (from a public URL or base64, 10 MB)

  • list_categories, create_category, list_tags, create_tag

  • get_site_settings, update_site_settings

Content cannot be deleted through the tools, and there is no theme or plugin management. New posts and pages are drafts unless status says otherwise.

Errors

A blog tool fails with a message that names the blog and says what to do:

  • the blog is not Online yet,

  • the REST API is not enabled (call enable_rest_api),

  • the blog could not be reached,

  • WordPress rejected the stored credentials (call enable_rest_api),

  • a plugin or security rule answered without JSON,

  • WordPress returned an error, which is passed on.

Tool failures come back as MCP tool results with isError set, so the agent can read them and react. Malformed requests get JSON-RPC errors, a missing or wrong credential gets HTTP 401, and anything but POST gets 405.

Limits and audit trail

Each account may make 60 tool calls per minute; the rate limit counter lives in redis. Every write tool (create_*, update_*, upload_media, enable_rest_api, delete_blog) writes an audit log entry of type BlogMCP on the blog, naming the tool, the account that called it and what changed, so staff can tell a customer what their agent did. Entries are kept for a year.

Implementation

Everything lives in ebn.mcp: the JSON-RPC dispatch, the tool registry (TOOLS, filled by the @tool decorator) and the WordPress forwarding (wp_call). Calls to blogs time out after 25 seconds so the agent gets an error before Heroku’s router drops the request. upload_media refuses source URLs that resolve to private addresses and does not follow redirects, because the download runs from inside EBN’s infrastructure.

OAuth, which claude.ai and ChatGPT connectors need, is a follow-up story.