

Home: one switch, on from the moment you activate. Hidden routes answer 404.
ClearComet Cloak for MCP is an on/off curtain in front of your site’s MCP and Abilities routes.
WordPress sites now have routes that AI assistants and bots use: the MCP Adapter’s mcp routes, the Abilities API, and MCP servers added by other plugins. Those routes are listed in the public /wp-json index unless something removes them.
A new install starts paused. Cloak saves that explicitly (on is false) and shows a notice, with Turn on and a link to the settings screen, until you turn it on. The switch on that screen shows Paused. Updating from an older version does not change your on/off choice. A site that was already protected stays protected, including one that never saved a settings row (on those versions, no row meant on).
Once Cloak is on, the default door mode is lights out. A stranger who requests a hidden route gets WordPress’s ordinary not-found answer (rest_no_route, 404), and those routes are left off the public /wp-json index. You do not have to create a key. Who gets in:
X-WP-Nonce or _wpnonce). The block editor does this. A cookie with no nonce does not count. An application password does not count unless you turn that rule on.cloak_allow_authenticated_users filter.X-Cloak-Key header (optional, Advanced). The older X-BlindPig-Key header still works.Unlisted mode (optional, per door): the route stays off the public index, and a request to the address itself is answered by the route. Use this when an assistant must see 401 and WWW-Authenticate on its first, still-anonymous request. Anyone who already knows the address can tell the route exists.
.well-known OAuth files are not hidden. /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server, including path-scoped copies, can name your MCP address. Cloak leaves them up so other OAuth uses on the site keep working. The first anonymous request to the MCP address is still a 404 in the default mode. The follow-up request gets through only after WordPress has accepted the login, or you have allowed a key, an address, or Unlisted mode.
WordPress still checks its own login after Cloak lets a request through. Cloak does not replace application passwords, and an application password alone does not get past Cloak.
People are already scanning the internet for MCP servers:
initialize handshakes POSTed to /mcp from 49 different IP addresses, on a server that runs no MCP at all. SANS Internet Storm Center, diary 33150/wp-json route list; it is fixed in 3.1.4. Wordfence/wp-json/mcp/v1/. Rapid7 Metasploit, Packet Storm via VulnersTo be honest about it: most of these knocks are reconnaissance, not attacks. GreyNoise saw no MCP-specific exploitation attempts in its honeypots. But being listed is how a site ends up on someone’s target list, and Cloak keeps your MCP doors off that list.
Activate Cloak and it is not protecting yet. An admin notice stays up until you turn it on. It is not dismissible. It has Turn on and Open settings. After you turn it on, a separate notice explains how AI assistants and bots get in, and that one can be dismissed.
An update keeps the on/off state the site already had. Deactivating and activating again does not pause a site that was already set up. CLOAK_DISABLED in wp-config.php still forces Cloak off.
Settings > Cloak for MCP shows one door-slot switch and one line telling you whether you’re protected. Click the slot to pause or resume. Everything else is optional and lives on the Advanced pages: doors, the guest list, a secret key for your own apps, Cloudflare, access rules, an activity log and tools (export/import).
You don’t need a key. It’s only for your own apps or scripts that connect from changing addresses. Generate a key, or paste your own (20+ characters: letters, digits, _ and -). Apps send it in the X-Cloak-Key header. Rotate keeps the old key working for 24 hours so you can update your apps; Turn off stops it. The key page has ready-made snippets for a desktop AI assistant, curl and n8n.
Cloak stores only a fingerprint of the key (a salted HMAC-SHA256), never the key itself, so a new key is shown once, right after it is made. Lost it? Make a new one. Keys are never exported and are compared in constant time.
Cloak trusts the CF-Connecting-IP header only when the request really comes from one of Cloudflare’s published ranges. X-Forwarded-For is never used. The plugin ships with Cloudflare’s list (checked 2026-10-06); Refresh from Cloudflare on the Guest list page downloads the current official list from Cloudflare’s public API over a checked HTTPS connection, and keeps the old list if anything looks wrong.
These optional constants pin a setting in code. The matching field shows as locked on the settings screen. They apply once protection is on, except CLOAK_DISABLED, which always switches protection off.
define( 'CLOAK_KEY', 'your-long-random-key' ); (20+ characters; works alongside a key made on the screen)
define( 'CLOAK_GUESTS', array( '203.0.113.7', '198.51.100.0/24' ) );
define( 'CLOAK_MODES', array( '/acme/v1' => 'lights_out' ) ); (modes: `open`, `unlisted`, `lights_out`)
lights_out (the default) answers 404 and hides the route from the index. `unlisted` hides the route from the index and lets the address itself answer, which is what an OAuth client needs in order to see 401. `open` leaves the route unchanged.
define( 'CLOAK_DISABLED', true ); (emergency off switch)
cloak_presets: change or add guest presets. Each preset is id => array( 'label' => ..., 'cidrs' => array( ... ) ). A single cidr string is still accepted. Presets stay off until an administrator adds them. The older blindpig_presets filter still runs first.cloak_cf_ranges: change the Cloudflare ranges used to trust CF-Connecting-IP.cloak_client_ip: supply the visitor address yourself if your site sits behind another trusted proxy. It must return a valid IP.cloak_allow_authenticated_users: default true. When true, a user WordPress has already logged in for this REST request may use a hidden route, unless that login is an application password or a cookie session (those keep their own rules). Return false to require a Cloak key, a guest address, or a browser nonce as well. Cloak never treats the Authorization header, by itself, as a login. The older blindpig_allow_authenticated_users filter still runs first.Cloak never phones home: no tracking, no analytics, no account, no ads. It makes no outside requests except two optional ones that only run when an administrator clicks a button: the quick check, which asks your own site for one hidden door, and Refresh from Cloudflare (see “External services” below). The activity log keeps the last 200 visits to hidden doors (time, IP address, door, result) on your site only and never records headers or keys. Deleting the plugin deletes all of its data.
Cloak is one layer of protection, not a guarantee. Keep WordPress, your plugins and your passwords up to date. Cloak is provided as-is, without warranty of any kind, under the GPL (see license.txt).
Cloak connects to one outside service, and only when an administrator asks it to.
Cloudflare IP list (optional, manual). When you click Refresh from Cloudflare on Settings > Cloak for MCP > Guest list, the plugin sends one HTTPS GET request to https://api.cloudflare.com/client/v4/ips to download Cloudflare’s public list of its own server address ranges. The list is used only to decide when the CF-Connecting-IP header can be trusted.
The optional quick check sends one request from your site to your own site’s address; nothing goes to a third party.