Skip to content

Instantly share code, notes, and snippets.

@vapvarun
Created April 28, 2026 08:20
Show Gist options
  • Select an option

  • Save vapvarun/862c17f05a6f6d54c3afa2e19e73c48e to your computer and use it in GitHub Desktop.

Select an option

Save vapvarun/862c17f05a6f6d54c3afa2e19e73c48e to your computer and use it in GitHub Desktop.
MCP Servers for WordPress (vapvarun.com) - Server patterns, REST API handlers, agentic loops
// MCP Server Skeleton for WordPress Agencies
// Pattern used in wp-blog, wpcs, and wp-malware-cleanup servers
// See: https://vapvarun.com/mcp-servers-wordpress-plugin-development/
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{ name: "wp-example-mcp", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
// 1. Declare what tools your server exposes
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "wp_run_cli",
description: "Run a safe WP-CLI command on the target site",
inputSchema: {
type: "object",
properties: {
site_id: { type: "string", description: "Site identifier from config" },
command: { type: "string", description: "WP-CLI command (without 'wp' prefix)" },
},
required: ["site_id", "command"],
},
},
],
}));
// 2. Implement the handlers
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === "wp_run_cli") {
const { site_id, command } = args;
// Validate against allowlist, connect to site, run command
const result = await runWpCli(site_id, command);
return {
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
};
}
throw new Error(`Unknown tool: ${name}`);
});
// 3. Start the server
const transport = new StdioServerTransport();
await server.connect(transport);
// WordPress REST API Tool Handler Pattern
// Used in wp-blog MCP server for post operations
// See: https://vapvarun.com/mcp-servers-wordpress-plugin-development/
import fetch from "node-fetch";
// Site config loaded from config/sites.json
const SITES = {
vapvarun: {
url: "https://vapvarun.com",
auth: process.env.VAPVARUN_APP_PASSWORD, // Never hardcode credentials
},
};
/**
* Generic WordPress REST API caller.
* Returns structured output the AI model can read.
*/
async function wpApiCall(site_id, endpoint, method = "GET", body = null) {
const site = SITES[site_id];
if (!site) throw new Error(`Unknown site: ${site_id}`);
const res = await fetch(`${site.url}/wp-json/wp/v2/${endpoint}`, {
method,
headers: {
Authorization: `Basic ${Buffer.from(site.auth).toString("base64")}`,
"Content-Type": "application/json",
},
body: body ? JSON.stringify(body) : undefined,
});
if (!res.ok) {
const err = await res.json().catch(() => ({ message: res.statusText }));
throw new Error(`WordPress API error ${res.status}: ${err.message}`);
}
return res.json();
}
// Example: get a post
export async function getPost(site_id, post_id) {
return wpApiCall(site_id, `posts/${post_id}`);
}
// Example: update a post
export async function updatePost(site_id, post_id, data) {
return wpApiCall(site_id, `posts/${post_id}`, "POST", data);
}
// Agentic Loop Pattern for Multi-Step WordPress Operations
// How the wp-malware-cleanup server runs scan-then-remediate loops
// See: https://vapvarun.com/mcp-servers-wordpress-plugin-development/
/**
* The key insight: instead of scripting a fixed sequence,
* expose atomic tools and let the AI decide the order.
*
* The AI will:
* 1. Run wp_scan_site
* 2. Read the scan results
* 3. Decide which wp_quarantine_file / wp_clean_injection calls to make
* 4. Run a verification scan to confirm remediation
* 5. Generate a report
*
* No script needed -- the model orchestrates the loop.
*/
// Tool definitions the AI can call (simplified)
const SECURITY_TOOLS = [
{
name: "wp_quick_scan",
description: "Fast threat signature scan. Returns array of threat objects with file paths and confidence scores.",
},
{
name: "wp_quarantine_file",
description: "Move a suspicious file to quarantine. Pass the absolute path returned by wp_quick_scan.",
},
{
name: "wp_regenerate_salts",
description: "Regenerate WordPress security salts and keys in wp-config.php.",
},
{
name: "wp_verify_core",
description: "Check all WordPress core files against official checksums. Returns modified/missing files.",
},
{
name: "wp_generate_report",
description: "Generate a cleanup report summarizing threats found, actions taken, and current site status.",
},
];
// The AI prompt that drives the loop (used internally)
const CLEANUP_PROMPT = `
You have access to security tools for this WordPress site.
Goal: clean and reharden the site.
1. Run wp_quick_scan to find threats
2. For each threat above 0.7 confidence, call wp_quarantine_file
3. Run wp_verify_core to check for modified core files
4. Regenerate salts
5. Run wp_quick_scan again to verify clean state
6. Generate a final report
Adapt based on what you find. Do not skip verification.
`;
export { SECURITY_TOOLS, CLEANUP_PROMPT };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment