@automattic/mcp-wordpress-remote 0.2.19 → 0.2.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,6 +50,7 @@ Add to your MCP client configuration (e.g., Claude Desktop's `claude_desktop_con
50
50
  You can add custom headers to all API requests using the `CUSTOM_HEADERS` environment variable. This is useful for API keys, custom authentication, or other header requirements.
51
51
 
52
52
  #### JSON Format (Recommended):
53
+
53
54
  ```json
54
55
  {
55
56
  "mcpServers": {
@@ -66,6 +67,7 @@ You can add custom headers to all API requests using the `CUSTOM_HEADERS` enviro
66
67
  ```
67
68
 
68
69
  #### Comma-Separated Format:
70
+
69
71
  ```json
70
72
  {
71
73
  "mcpServers": {
@@ -82,6 +84,7 @@ You can add custom headers to all API requests using the `CUSTOM_HEADERS` enviro
82
84
  ```
83
85
 
84
86
  #### Command Line Usage:
87
+
85
88
  ```bash
86
89
  CUSTOM_HEADERS='{"X-MCP-API-Key": "wc_mcp_FaQduhQcW0mfVaZgP3yaaqDuXaZ3mw7j"}' \
87
90
  WP_API_URL="https://your-site.com" \
@@ -89,6 +92,7 @@ npx @automattic/mcp-wordpress-remote
89
92
  ```
90
93
 
91
94
  Custom headers are included in:
95
+
92
96
  - All WordPress API requests
93
97
  - OAuth discovery requests
94
98
  - OAuth token exchange requests
@@ -130,8 +134,6 @@ OAuth 2.1 provides the most secure and user-friendly experience with full MCP Au
130
134
  }
131
135
  ```
132
136
 
133
-
134
-
135
137
  **MCP Authorization Specification Features:**
136
138
 
137
139
  - **OAuth 2.1 authorization code flow** with PKCE (RFC 7636)
@@ -240,34 +242,32 @@ For WooCommerce-specific tools and reports:
240
242
 
241
243
  ### Environment Variables
242
244
 
243
- | Variable | Description | Default | Required |
244
- | ---------------------------- | ---------------------------------- | -------------------- | -------- |
245
- | `WP_API_URL` | WordPress site URL | - | ✅ |
246
- | `OAUTH_ENABLED` | Enable OAuth authentication | `true` | - |
247
- | `OAUTH_CALLBACK_PORT` | OAuth callback port | `7665` | - |
248
- | `OAUTH_HOST` | OAuth callback hostname | `127.0.0.1` | - |
249
- | `WP_OAUTH_CLIENT_ID` | Custom OAuth client ID | - | - |
250
- | **OAuth Endpoints** | | | |
251
- | `OAUTH_AUTHORIZE_ENDPOINT` | OAuth authorization endpoint | - | ✅ (for custom OAuth) |
252
- | `OAUTH_TOKEN_ENDPOINT` | OAuth token endpoint | - | ✅ (for custom OAuth) |
253
- | `OAUTH_AUTHENTICATE_ENDPOINT`| OAuth authenticate endpoint | - | - |
254
- | **MCP OAuth 2.1 Settings** | | | |
255
- | `OAUTH_FLOW_TYPE` | OAuth flow type (authorization_code or implicit) | `authorization_code` | - |
256
- | `OAUTH_USE_PKCE` | Use PKCE (required for OAuth 2.1) | `true` | - |
257
- | `OAUTH_DYNAMIC_REGISTRATION` | Enable dynamic client registration | `true` | - |
258
- | `OAUTH_RESOURCE_INDICATOR` | Use resource indicators (RFC 8707) | `true` | - |
259
- | **Configuration** | | | |
260
- | `WP_MCP_CONFIG_DIR` | Config directory override | `~/.mcp-auth` | - |
261
- | `LOG_FILE` | Log file path | - | - |
262
- | `LOG_LEVEL` | Log level (0-3) | `2` | - |
263
- | **Legacy Authentication** | | | |
264
- | `JWT_TOKEN` | JWT token for authentication | - | - |
265
- | `WP_API_USERNAME` | WordPress username (legacy) | - | - |
266
- | `WP_API_PASSWORD` | WordPress app password (legacy) | - | - |
267
- | `WOO_CUSTOMER_KEY` | WooCommerce consumer key | - | - |
268
- | `WOO_CUSTOMER_SECRET` | WooCommerce consumer secret | - | - |
269
-
270
-
245
+ | Variable | Description | Default | Required |
246
+ | ----------------------------- | ------------------------------------------------ | -------------------- | --------------------- |
247
+ | `WP_API_URL` | WordPress site URL | - | ✅ |
248
+ | `OAUTH_ENABLED` | Enable OAuth authentication | `true` | - |
249
+ | `OAUTH_CALLBACK_PORT` | OAuth callback port | `7665` | - |
250
+ | `OAUTH_HOST` | OAuth callback hostname | `127.0.0.1` | - |
251
+ | `WP_OAUTH_CLIENT_ID` | Custom OAuth client ID | - | - |
252
+ | **OAuth Endpoints** | | | |
253
+ | `OAUTH_AUTHORIZE_ENDPOINT` | OAuth authorization endpoint | - | ✅ (for custom OAuth) |
254
+ | `OAUTH_TOKEN_ENDPOINT` | OAuth token endpoint | - | ✅ (for custom OAuth) |
255
+ | `OAUTH_AUTHENTICATE_ENDPOINT` | OAuth authenticate endpoint | - | - |
256
+ | **MCP OAuth 2.1 Settings** | | | |
257
+ | `OAUTH_FLOW_TYPE` | OAuth flow type (authorization_code or implicit) | `authorization_code` | - |
258
+ | `OAUTH_USE_PKCE` | Use PKCE (required for OAuth 2.1) | `true` | - |
259
+ | `OAUTH_DYNAMIC_REGISTRATION` | Enable dynamic client registration | `true` | - |
260
+ | `OAUTH_RESOURCE_INDICATOR` | Use resource indicators (RFC 8707) | `true` | - |
261
+ | **Configuration** | | | |
262
+ | `WP_MCP_CONFIG_DIR` | Config directory override | `~/.mcp-auth` | - |
263
+ | `LOG_FILE` | Log file path | - | - |
264
+ | `LOG_LEVEL` | Log level (0-3) | `2` | - |
265
+ | **Legacy Authentication** | | | |
266
+ | `JWT_TOKEN` | JWT token for authentication | - | - |
267
+ | `WP_API_USERNAME` | WordPress username (legacy) | - | - |
268
+ | `WP_API_PASSWORD` | WordPress app password (legacy) | - | - |
269
+ | `WOO_CUSTOMER_KEY` | WooCommerce consumer key | - | - |
270
+ | `WOO_CUSTOMER_SECRET` | WooCommerce consumer secret | - | - |
271
271
 
272
272
  ### Disable OAuth
273
273
 
package/dist/lib.d.ts CHANGED
@@ -280,6 +280,7 @@ declare function getFetchInfo(): {
280
280
  *
281
281
  * Supports:
282
282
  * - macOS: Automatic PAC file detection from system proxy settings
283
+ * - macOS: System SOCKS proxy detection (AutoProxxy Tunnel All Traffic)
283
284
  * - All platforms: Environment variables (SOCKS_PROXY, HTTPS_PROXY, etc.)
284
285
  */
285
286
 
package/dist/lib.js CHANGED
@@ -35641,15 +35641,19 @@ import { SocksProxyAgent } from "socks-proxy-agent";
35641
35641
  import { HttpsProxyAgent } from "https-proxy-agent";
35642
35642
  var proxyConfig = { type: "none" };
35643
35643
  var initializationPromise = null;
35644
- function detectMacOsPac() {
35644
+ function detectMacOsProxy() {
35645
35645
  if (process.platform !== "darwin") return null;
35646
35646
  try {
35647
35647
  const output = execSync("scutil --proxy", { encoding: "utf-8", timeout: 3e3 });
35648
35648
  const pacEnabled = output.match(/ProxyAutoConfigEnable\s*:\s*(\d)/)?.[1] === "1";
35649
35649
  const pacUrl = output.match(/ProxyAutoConfigURLString\s*:\s*(\S+)/)?.[1];
35650
- if (pacEnabled && pacUrl) {
35651
- return pacUrl;
35652
- }
35650
+ const socksEnabled = output.match(/SOCKSEnable\s*:\s*(\d)/)?.[1] === "1";
35651
+ const socksHost = output.match(/SOCKSProxy\s*:\s*(\S+)/)?.[1];
35652
+ const socksPort = output.match(/SOCKSPort\s*:\s*(\d+)/)?.[1];
35653
+ return {
35654
+ pacUrl: pacEnabled && pacUrl ? pacUrl : null,
35655
+ socks: socksEnabled && socksHost && socksPort ? { host: socksHost, port: socksPort } : null
35656
+ };
35653
35657
  } catch {
35654
35658
  }
35655
35659
  return null;
@@ -35715,10 +35719,10 @@ async function initializeProxy() {
35715
35719
  return initializationPromise;
35716
35720
  }
35717
35721
  async function doInitializeProxy() {
35718
- const pacUrl = detectMacOsPac();
35719
- if (pacUrl) {
35722
+ const macProxy = detectMacOsProxy();
35723
+ if (macProxy?.pacUrl) {
35720
35724
  try {
35721
- const response = await fetch(pacUrl);
35725
+ const response = await fetch(macProxy.pacUrl);
35722
35726
  const pacScript = await response.text();
35723
35727
  const { getQuickJS } = await import("@tootallnate/quickjs-emscripten");
35724
35728
  const { createPacResolver } = await import("pac-resolver");
@@ -35728,12 +35732,20 @@ async function doInitializeProxy() {
35728
35732
  type: "pac",
35729
35733
  pacResolver: resolver
35730
35734
  };
35731
- logger.info(`PAC proxy initialized from ${sanitizeProxyUrl(pacUrl)}`, "PROXY");
35735
+ logger.info(`PAC proxy initialized from ${sanitizeProxyUrl(macProxy.pacUrl)}`, "PROXY");
35732
35736
  return;
35733
35737
  } catch (error) {
35734
35738
  logger.error(`Failed to initialize PAC proxy: ${error}`, "PROXY");
35735
35739
  }
35736
35740
  }
35741
+ if (macProxy?.socks) {
35742
+ const { host, port } = macProxy.socks;
35743
+ const bracketedHost = host.includes(":") ? `[${host}]` : host;
35744
+ const socksUrl = `socks5://${bracketedHost}:${port}`;
35745
+ proxyConfig = { type: "env", envProxy: { url: socksUrl, type: "socks" } };
35746
+ logger.info(`System SOCKS proxy configured: ${sanitizeProxyUrl(socksUrl)}`, "PROXY");
35747
+ return;
35748
+ }
35737
35749
  const envProxy = detectEnvProxy();
35738
35750
  if (envProxy) {
35739
35751
  proxyConfig = { type: "env", envProxy };
package/dist/proxy.js CHANGED
@@ -36305,15 +36305,19 @@ import { SocksProxyAgent } from "socks-proxy-agent";
36305
36305
  import { HttpsProxyAgent } from "https-proxy-agent";
36306
36306
  var proxyConfig = { type: "none" };
36307
36307
  var initializationPromise = null;
36308
- function detectMacOsPac() {
36308
+ function detectMacOsProxy() {
36309
36309
  if (process.platform !== "darwin") return null;
36310
36310
  try {
36311
36311
  const output = execSync("scutil --proxy", { encoding: "utf-8", timeout: 3e3 });
36312
36312
  const pacEnabled = output.match(/ProxyAutoConfigEnable\s*:\s*(\d)/)?.[1] === "1";
36313
36313
  const pacUrl = output.match(/ProxyAutoConfigURLString\s*:\s*(\S+)/)?.[1];
36314
- if (pacEnabled && pacUrl) {
36315
- return pacUrl;
36316
- }
36314
+ const socksEnabled = output.match(/SOCKSEnable\s*:\s*(\d)/)?.[1] === "1";
36315
+ const socksHost = output.match(/SOCKSProxy\s*:\s*(\S+)/)?.[1];
36316
+ const socksPort = output.match(/SOCKSPort\s*:\s*(\d+)/)?.[1];
36317
+ return {
36318
+ pacUrl: pacEnabled && pacUrl ? pacUrl : null,
36319
+ socks: socksEnabled && socksHost && socksPort ? { host: socksHost, port: socksPort } : null
36320
+ };
36317
36321
  } catch {
36318
36322
  }
36319
36323
  return null;
@@ -36379,10 +36383,10 @@ async function initializeProxy() {
36379
36383
  return initializationPromise;
36380
36384
  }
36381
36385
  async function doInitializeProxy() {
36382
- const pacUrl = detectMacOsPac();
36383
- if (pacUrl) {
36386
+ const macProxy = detectMacOsProxy();
36387
+ if (macProxy?.pacUrl) {
36384
36388
  try {
36385
- const response = await fetch(pacUrl);
36389
+ const response = await fetch(macProxy.pacUrl);
36386
36390
  const pacScript = await response.text();
36387
36391
  const { getQuickJS } = await import("@tootallnate/quickjs-emscripten");
36388
36392
  const { createPacResolver } = await import("pac-resolver");
@@ -36392,12 +36396,20 @@ async function doInitializeProxy() {
36392
36396
  type: "pac",
36393
36397
  pacResolver: resolver
36394
36398
  };
36395
- logger.info(`PAC proxy initialized from ${sanitizeProxyUrl(pacUrl)}`, "PROXY");
36399
+ logger.info(`PAC proxy initialized from ${sanitizeProxyUrl(macProxy.pacUrl)}`, "PROXY");
36396
36400
  return;
36397
36401
  } catch (error) {
36398
36402
  logger.error(`Failed to initialize PAC proxy: ${error}`, "PROXY");
36399
36403
  }
36400
36404
  }
36405
+ if (macProxy?.socks) {
36406
+ const { host, port } = macProxy.socks;
36407
+ const bracketedHost = host.includes(":") ? `[${host}]` : host;
36408
+ const socksUrl = `socks5://${bracketedHost}:${port}`;
36409
+ proxyConfig = { type: "env", envProxy: { url: socksUrl, type: "socks" } };
36410
+ logger.info(`System SOCKS proxy configured: ${sanitizeProxyUrl(socksUrl)}`, "PROXY");
36411
+ return;
36412
+ }
36401
36413
  const envProxy = detectEnvProxy();
36402
36414
  if (envProxy) {
36403
36415
  proxyConfig = { type: "env", envProxy };
@@ -38796,12 +38808,45 @@ function prepareRequest(wpRequestParams, mcpRequest, context) {
38796
38808
  }
38797
38809
  }
38798
38810
  function createSessionContext() {
38811
+ let resolve;
38812
+ const ready = new Promise((r2) => {
38813
+ resolve = r2;
38814
+ });
38799
38815
  return {
38800
38816
  sessionId: null,
38801
38817
  requestIdCounter: 0,
38802
- transportType: null
38818
+ transportType: null,
38819
+ _init: {
38820
+ ready,
38821
+ resolve,
38822
+ settled: false,
38823
+ failed: false
38824
+ }
38803
38825
  };
38804
38826
  }
38827
+ function resolveInit(context, failed) {
38828
+ if (context._init.settled) return;
38829
+ context._init.failed = failed;
38830
+ context._init.settled = true;
38831
+ context._init.resolve();
38832
+ }
38833
+ var INIT_TIMEOUT_MS = 3e4;
38834
+ async function waitForInit(context, timeoutMs = INIT_TIMEOUT_MS) {
38835
+ if (context._init.settled) {
38836
+ return context._init.failed ? { ready: false, reason: "failed" } : { ready: true };
38837
+ }
38838
+ let timer;
38839
+ const timeout = new Promise((resolve) => {
38840
+ timer = setTimeout(() => resolve("timeout"), timeoutMs);
38841
+ });
38842
+ const result = await Promise.race([context._init.ready.then(() => "ready"), timeout]);
38843
+ clearTimeout(timer);
38844
+ if (result === "timeout") {
38845
+ logger.error("Timed out waiting for initialization to complete", "INIT");
38846
+ return { ready: false, reason: "timeout" };
38847
+ }
38848
+ return context._init.failed ? { ready: false, reason: "failed" } : { ready: true };
38849
+ }
38805
38850
 
38806
38851
  // src/lib/transport-detection.ts
38807
38852
  async function detectTransportType(context, initParams) {
@@ -38970,6 +39015,11 @@ function convertAPIErrorToMcpError(error) {
38970
39015
  function createRequestHandler(config, context) {
38971
39016
  return async (request) => {
38972
39017
  logger.debug(`Processing ${config.name}Request`, "MCP");
39018
+ const init = await waitForInit(context);
39019
+ if (!init.ready) {
39020
+ const cause = init.reason === "timeout" ? "timed out waiting for" : "failed during";
39021
+ throw new Error(`Cannot process ${config.method}: WordPress connection ${cause} initialization`);
39022
+ }
38973
39023
  const wpParams = config.paramMapper(request);
38974
39024
  const requestData = prepareRequest(wpParams, request, context);
38975
39025
  const response = await wpRequest(requestData, context.transportType === "jsonrpc");
@@ -39156,6 +39206,7 @@ async function WordPressProxy() {
39156
39206
  try {
39157
39207
  logger.info("\u{1F504} Initializing WordPress connection with client parameters", "INIT");
39158
39208
  const { initResult } = await detectTransportType(sessionContext, request.params);
39209
+ resolveInit(sessionContext, false);
39159
39210
  const wordpressInitResponse = {
39160
39211
  protocolVersion: initResult.protocolVersion || "2025-06-18",
39161
39212
  serverInfo: initResult.serverInfo,
@@ -39166,9 +39217,15 @@ async function WordPressProxy() {
39166
39217
  logger.debug("Initialize response:", "INIT", wordpressInitResponse);
39167
39218
  return wordpressInitResponse;
39168
39219
  } catch (error) {
39169
- logger.error("\u274C Failed to initialize WordPress connection with client parameters", "INIT", error);
39220
+ logger.error(
39221
+ "\u274C Failed to initialize WordPress connection with client parameters",
39222
+ "INIT",
39223
+ error
39224
+ );
39225
+ resolveInit(sessionContext, true);
39226
+ const clientProtocolVersion = request?.params?.protocolVersion || "2025-06-18";
39170
39227
  const fallbackResponse = {
39171
- protocolVersion: "2025-06-18",
39228
+ protocolVersion: clientProtocolVersion,
39172
39229
  serverInfo: {
39173
39230
  name: "WordPress MCP Remote Proxy",
39174
39231
  version: MCP_WORDPRESS_REMOTE_VERSION
@@ -39186,24 +39243,62 @@ async function WordPressProxy() {
39186
39243
  return fallbackResponse;
39187
39244
  }
39188
39245
  });
39189
- server.setRequestHandler(ListToolsRequestSchema, createWrappedHandler(HANDLER_CONFIGS.listTools, sessionContext));
39190
- server.setRequestHandler(CallToolRequestSchema, createWrappedHandler(HANDLER_CONFIGS.callTool, sessionContext));
39191
- server.setRequestHandler(ListResourcesRequestSchema, createWrappedHandler(HANDLER_CONFIGS.listResources, sessionContext));
39192
- server.setRequestHandler(ListResourceTemplatesRequestSchema, createWrappedHandler(HANDLER_CONFIGS.listResourceTemplates, sessionContext));
39193
- server.setRequestHandler(ReadResourceRequestSchema, createWrappedHandler(HANDLER_CONFIGS.readResource, sessionContext));
39194
- server.setRequestHandler(SubscribeRequestSchema, createWrappedHandler(HANDLER_CONFIGS.subscribe, sessionContext));
39195
- server.setRequestHandler(UnsubscribeRequestSchema, createWrappedHandler(HANDLER_CONFIGS.unsubscribe, sessionContext));
39196
- server.setRequestHandler(ListPromptsRequestSchema, createWrappedHandler(HANDLER_CONFIGS.listPrompts, sessionContext));
39197
- server.setRequestHandler(GetPromptRequestSchema, createWrappedHandler(HANDLER_CONFIGS.getPrompt, sessionContext));
39198
- server.setRequestHandler(SetLevelRequestSchema, createWrappedHandler(HANDLER_CONFIGS.setLevel, sessionContext));
39199
- server.setRequestHandler(CompleteRequestSchema, createWrappedHandler(HANDLER_CONFIGS.complete, sessionContext));
39200
- server.setRequestHandler(ListRootsRequestSchema, createWrappedHandler(HANDLER_CONFIGS.listRoots, sessionContext));
39246
+ server.setRequestHandler(
39247
+ ListToolsRequestSchema,
39248
+ createWrappedHandler(HANDLER_CONFIGS.listTools, sessionContext)
39249
+ );
39250
+ server.setRequestHandler(
39251
+ CallToolRequestSchema,
39252
+ createWrappedHandler(HANDLER_CONFIGS.callTool, sessionContext)
39253
+ );
39254
+ server.setRequestHandler(
39255
+ ListResourcesRequestSchema,
39256
+ createWrappedHandler(HANDLER_CONFIGS.listResources, sessionContext)
39257
+ );
39258
+ server.setRequestHandler(
39259
+ ListResourceTemplatesRequestSchema,
39260
+ createWrappedHandler(HANDLER_CONFIGS.listResourceTemplates, sessionContext)
39261
+ );
39262
+ server.setRequestHandler(
39263
+ ReadResourceRequestSchema,
39264
+ createWrappedHandler(HANDLER_CONFIGS.readResource, sessionContext)
39265
+ );
39266
+ server.setRequestHandler(
39267
+ SubscribeRequestSchema,
39268
+ createWrappedHandler(HANDLER_CONFIGS.subscribe, sessionContext)
39269
+ );
39270
+ server.setRequestHandler(
39271
+ UnsubscribeRequestSchema,
39272
+ createWrappedHandler(HANDLER_CONFIGS.unsubscribe, sessionContext)
39273
+ );
39274
+ server.setRequestHandler(
39275
+ ListPromptsRequestSchema,
39276
+ createWrappedHandler(HANDLER_CONFIGS.listPrompts, sessionContext)
39277
+ );
39278
+ server.setRequestHandler(
39279
+ GetPromptRequestSchema,
39280
+ createWrappedHandler(HANDLER_CONFIGS.getPrompt, sessionContext)
39281
+ );
39282
+ server.setRequestHandler(
39283
+ SetLevelRequestSchema,
39284
+ createWrappedHandler(HANDLER_CONFIGS.setLevel, sessionContext)
39285
+ );
39286
+ server.setRequestHandler(
39287
+ CompleteRequestSchema,
39288
+ createWrappedHandler(HANDLER_CONFIGS.complete, sessionContext)
39289
+ );
39290
+ server.setRequestHandler(
39291
+ ListRootsRequestSchema,
39292
+ createWrappedHandler(HANDLER_CONFIGS.listRoots, sessionContext)
39293
+ );
39201
39294
  const transport = new StdioServerTransport();
39202
39295
  transport.onmessage = (message) => {
39203
39296
  const msg = message;
39204
39297
  const method = typeof msg?.method === "string" ? msg.method : "unknown";
39205
39298
  const id = msg?.id ?? "none";
39206
- const hasParams = Boolean(msg?.params && typeof msg.params === "object" && Object.keys(msg.params).length);
39299
+ const hasParams = Boolean(
39300
+ msg?.params && typeof msg.params === "object" && Object.keys(msg.params).length
39301
+ );
39207
39302
  logger.info("\u{1F4E5} Raw client message received", "TRANSPORT", {
39208
39303
  method,
39209
39304
  id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/mcp-wordpress-remote",
3
- "version": "0.2.19",
3
+ "version": "0.2.21",
4
4
  "description": "MCP WordPress Remote proxy server",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"