Summary
The client never sets an explicit User-Agent header when calling the WordPress REST API. I ran the published package against a local test listener to see what actually goes out on the wire, and the request arrives with:
That's Node's own built-in fetch (undici) default when nothing overrides it, not something specific to this package. It carries no identifying information at all, and "node" is common enough that it's effectively indistinguishable from a huge range of unrelated scripts and tools.
Why this matters
I've run into WordPress security/firewall plugins blocking this traffic because their bot-protection systems classify requests partly by User-Agent, and a bare node string looks indistinguishable from bot/scraper traffic. Since MCP clients run on the end user's own machine with no fixed IP, User-Agent is really the only practical signal a security plugin has to work with here, and right now it doesn't carry one.
This would affect any WordPress security plugin that does UA-based classification, and any project built on this bridge, not just a single use case.
Where this happens
src/lib/wordpress-api.ts, in the headers object construction (around lines 391-396):
const headers: Record<string, string> = {
'Content-Type': 'application/json',
Accept: 'application/json, text/event-stream',
'MCP-Protocol-Version': '2025-06-18',
...customHeaders,
};
No User-Agent key is set here, which matches what actually goes out on the wire: Node's built-in fetch default.
Suggested fix
Add an explicit, version-stamped User-Agent at the same spot, something like:
const headers: Record<string, string> = {
'Content-Type': 'application/json',
Accept: 'application/json, text/event-stream',
'MCP-Protocol-Version': '2025-06-18',
'User-Agent': `mcp-wordpress-remote/${VERSION}`,
...customHeaders,
};
(keeping it before ...customHeaders so a caller can still override it via CUSTOM_HEADERS if they need to)
This is a small change but it's the difference between security plugins being able to build a real allowlist rule for this traffic versus not being able to identify it at all. Happy to open a PR for this if that's useful, just wanted to raise it first in case there's a reason it's currently left unset that I'm not seeing.
Summary
The client never sets an explicit
User-Agentheader when calling the WordPress REST API. I ran the published package against a local test listener to see what actually goes out on the wire, and the request arrives with:That's Node's own built-in
fetch(undici) default when nothing overrides it, not something specific to this package. It carries no identifying information at all, and"node"is common enough that it's effectively indistinguishable from a huge range of unrelated scripts and tools.Why this matters
I've run into WordPress security/firewall plugins blocking this traffic because their bot-protection systems classify requests partly by User-Agent, and a bare
nodestring looks indistinguishable from bot/scraper traffic. Since MCP clients run on the end user's own machine with no fixed IP, User-Agent is really the only practical signal a security plugin has to work with here, and right now it doesn't carry one.This would affect any WordPress security plugin that does UA-based classification, and any project built on this bridge, not just a single use case.
Where this happens
src/lib/wordpress-api.ts, in the headers object construction (around lines 391-396):No
User-Agentkey is set here, which matches what actually goes out on the wire: Node's built-in fetch default.Suggested fix
Add an explicit, version-stamped User-Agent at the same spot, something like:
(keeping it before
...customHeadersso a caller can still override it viaCUSTOM_HEADERSif they need to)This is a small change but it's the difference between security plugins being able to build a real allowlist rule for this traffic versus not being able to identify it at all. Happy to open a PR for this if that's useful, just wanted to raise it first in case there's a reason it's currently left unset that I'm not seeing.