@automattic/mcp-wordpress-remote 0.2.17 → 0.2.19

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/dist/proxy.js CHANGED
@@ -36036,7 +36036,7 @@ async function selectCallbackPort(serverUrl, specifiedPort, _unused) {
36036
36036
  }
36037
36037
 
36038
36038
  // src/lib/config.ts
36039
- var MCP_WORDPRESS_REMOTE_VERSION = "0.2.17";
36039
+ var MCP_WORDPRESS_REMOTE_VERSION = "0.2.19";
36040
36040
  var CONFIG = {
36041
36041
  // API Configuration
36042
36042
  WP_API_URL: process.env.WP_API_URL || "https://example.com",
@@ -36086,8 +36086,57 @@ var CONFIG = {
36086
36086
  CUSTOM_HEADERS: process.env.CUSTOM_HEADERS || "",
36087
36087
  // JSON string or comma-separated header:value pairs
36088
36088
  // Environment
36089
- NODE_ENV: process.env.NODE_ENV || "development"
36089
+ NODE_ENV: process.env.NODE_ENV || "development",
36090
+ // Proxy Configuration
36091
+ USE_SYSTEM_PROXY: process.env.USE_SYSTEM_PROXY === "true"
36092
+ // Enable system proxy detection (PAC files, env vars)
36090
36093
  };
36094
+ var getConfig = () => ({
36095
+ /** WordPress site API endpoint */
36096
+ wpApiUrl: CONFIG.WP_API_URL,
36097
+ /** Whether OAuth authentication is enabled */
36098
+ oauthEnabled: CONFIG.OAUTH_ENABLED,
36099
+ /** Port for OAuth callback server (undefined for auto-detection on self-hosted sites) */
36100
+ oauthCallbackPort: CONFIG.OAUTH_CALLBACK_PORT,
36101
+ /** Hostname for OAuth callback */
36102
+ oauthHost: CONFIG.OAUTH_HOST,
36103
+ /** WordPress OAuth client ID */
36104
+ wpOAuthClientId: CONFIG.WP_OAUTH_CLIENT_ID,
36105
+ /** OAuth flow type (authorization_code recommended, implicit for legacy) */
36106
+ oauthFlowType: CONFIG.OAUTH_FLOW_TYPE,
36107
+ /** Whether to use PKCE (required for OAuth 2.1) */
36108
+ oauthUsePKCE: CONFIG.OAUTH_USE_PKCE,
36109
+ /** Whether to support dynamic client registration */
36110
+ oauthDynamicRegistration: CONFIG.OAUTH_DYNAMIC_REGISTRATION,
36111
+ /** Whether to use resource indicators (RFC 8707) */
36112
+ oauthResourceIndicator: CONFIG.OAUTH_RESOURCE_INDICATOR,
36113
+ /** Custom OAuth scopes (comma-separated) */
36114
+ oauthScopes: CONFIG.OAUTH_SCOPES,
36115
+ /** OAuth operation timeout in milliseconds */
36116
+ oauthTimeout: CONFIG.OAUTH_TIMEOUT,
36117
+ /** Lock operation timeout in milliseconds */
36118
+ lockTimeout: CONFIG.LOCK_TIMEOUT,
36119
+ /** Configuration directory path */
36120
+ configDir: CONFIG.WP_MCP_CONFIG_DIR,
36121
+ /** Log file path (null if not set) */
36122
+ logFile: CONFIG.LOG_FILE,
36123
+ /** WordPress API username (legacy) */
36124
+ wpApiUsername: CONFIG.WP_API_USERNAME,
36125
+ /** WordPress API password (legacy) */
36126
+ wpApiPassword: CONFIG.WP_API_PASSWORD,
36127
+ /** JWT token for authentication */
36128
+ jwtToken: CONFIG.JWT_TOKEN,
36129
+ /** WooCommerce customer key */
36130
+ wooCustomerKey: CONFIG.WOO_CUSTOMER_KEY,
36131
+ /** WooCommerce customer secret */
36132
+ wooCustomerSecret: CONFIG.WOO_CUSTOMER_SECRET,
36133
+ /** Custom headers for API requests */
36134
+ customHeaders: CONFIG.CUSTOM_HEADERS,
36135
+ /** Current environment */
36136
+ nodeEnv: CONFIG.NODE_ENV,
36137
+ /** Whether to use system proxy (PAC files on macOS, env vars on all platforms) */
36138
+ useSystemProxy: CONFIG.USE_SYSTEM_PROXY
36139
+ });
36091
36140
  function parseOAuthScopes(envScopes, defaultScopes) {
36092
36141
  if (!envScopes || envScopes.trim() === "") {
36093
36142
  return defaultScopes;
@@ -36218,7 +36267,9 @@ function log(message, level = 2 /* INFO */, category = "GENERAL", ...args) {
36218
36267
  const formattedArgs = args.length > 0 ? args.map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : arg).join(" ") : "";
36219
36268
  const logMessage = `${timestamp} [${levelName}] [${category}] ${message}${formattedArgs ? "\n" + formattedArgs : ""}
36220
36269
  `;
36221
- process.stderr.write(logMessage);
36270
+ if (process.env.LOG_TO_STDERR === "true") {
36271
+ process.stderr.write(logMessage);
36272
+ }
36222
36273
  if (process.env.LOG_FILE) {
36223
36274
  fs2.appendFileSync(process.env.LOG_FILE, logMessage);
36224
36275
  }
@@ -36248,6 +36299,165 @@ function validateNodeVersion(requiredVersion = 18) {
36248
36299
  }
36249
36300
  }
36250
36301
 
36302
+ // src/lib/proxy-utils.ts
36303
+ import { execSync } from "child_process";
36304
+ import { SocksProxyAgent } from "socks-proxy-agent";
36305
+ import { HttpsProxyAgent } from "https-proxy-agent";
36306
+ var proxyConfig = { type: "none" };
36307
+ var initializationPromise = null;
36308
+ function detectMacOsPac() {
36309
+ if (process.platform !== "darwin") return null;
36310
+ try {
36311
+ const output = execSync("scutil --proxy", { encoding: "utf-8", timeout: 3e3 });
36312
+ const pacEnabled = output.match(/ProxyAutoConfigEnable\s*:\s*(\d)/)?.[1] === "1";
36313
+ const pacUrl = output.match(/ProxyAutoConfigURLString\s*:\s*(\S+)/)?.[1];
36314
+ if (pacEnabled && pacUrl) {
36315
+ return pacUrl;
36316
+ }
36317
+ } catch {
36318
+ }
36319
+ return null;
36320
+ }
36321
+ function isSocksProxy(url) {
36322
+ return url.toLowerCase().startsWith("socks");
36323
+ }
36324
+ function sanitizeProxyUrl(url) {
36325
+ try {
36326
+ const parsed = new URL(url);
36327
+ if (parsed.password) parsed.password = "***";
36328
+ return parsed.toString();
36329
+ } catch {
36330
+ return url.replace(/\/\/[^:]+:[^@]+@/, "//***:***@");
36331
+ }
36332
+ }
36333
+ function shouldBypassProxy(targetUrl) {
36334
+ const noProxy = process.env.NO_PROXY || process.env.no_proxy;
36335
+ if (!noProxy) return false;
36336
+ let hostname2;
36337
+ try {
36338
+ hostname2 = new URL(targetUrl).hostname.toLowerCase();
36339
+ } catch {
36340
+ return false;
36341
+ }
36342
+ const rules = noProxy.split(",").map((r2) => r2.trim().toLowerCase()).filter((r2) => r2.length > 0);
36343
+ for (const rule of rules) {
36344
+ if (rule === "*") return true;
36345
+ if (hostname2 === rule) return true;
36346
+ if (rule.startsWith(".") && hostname2.endsWith(rule) || !rule.startsWith(".") && hostname2.endsWith(`.${rule}`)) {
36347
+ return true;
36348
+ }
36349
+ }
36350
+ return false;
36351
+ }
36352
+ function detectEnvProxy() {
36353
+ const socksProxy = process.env.SOCKS_PROXY || process.env.socks_proxy;
36354
+ if (socksProxy) {
36355
+ return { url: socksProxy, type: "socks" };
36356
+ }
36357
+ const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
36358
+ if (httpsProxy) {
36359
+ return { url: httpsProxy, type: isSocksProxy(httpsProxy) ? "socks" : "http" };
36360
+ }
36361
+ const allProxy = process.env.ALL_PROXY || process.env.all_proxy;
36362
+ if (allProxy) {
36363
+ return { url: allProxy, type: isSocksProxy(allProxy) ? "socks" : "http" };
36364
+ }
36365
+ const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy;
36366
+ if (httpProxy) {
36367
+ return { url: httpProxy, type: isSocksProxy(httpProxy) ? "socks" : "http" };
36368
+ }
36369
+ return null;
36370
+ }
36371
+ async function initializeProxy() {
36372
+ if (initializationPromise) {
36373
+ return initializationPromise;
36374
+ }
36375
+ initializationPromise = doInitializeProxy().catch((error) => {
36376
+ initializationPromise = null;
36377
+ throw error;
36378
+ });
36379
+ return initializationPromise;
36380
+ }
36381
+ async function doInitializeProxy() {
36382
+ const pacUrl = detectMacOsPac();
36383
+ if (pacUrl) {
36384
+ try {
36385
+ const response = await fetch(pacUrl);
36386
+ const pacScript = await response.text();
36387
+ const { getQuickJS } = await import("@tootallnate/quickjs-emscripten");
36388
+ const { createPacResolver } = await import("pac-resolver");
36389
+ const qjs = await getQuickJS();
36390
+ const resolver = createPacResolver(qjs, pacScript);
36391
+ proxyConfig = {
36392
+ type: "pac",
36393
+ pacResolver: resolver
36394
+ };
36395
+ logger.info(`PAC proxy initialized from ${sanitizeProxyUrl(pacUrl)}`, "PROXY");
36396
+ return;
36397
+ } catch (error) {
36398
+ logger.error(`Failed to initialize PAC proxy: ${error}`, "PROXY");
36399
+ }
36400
+ }
36401
+ const envProxy = detectEnvProxy();
36402
+ if (envProxy) {
36403
+ proxyConfig = { type: "env", envProxy };
36404
+ logger.info(`Proxy configured from environment: ${sanitizeProxyUrl(envProxy.url)}`, "PROXY");
36405
+ return;
36406
+ }
36407
+ logger.debug("No proxy configured", "PROXY");
36408
+ proxyConfig = { type: "none" };
36409
+ }
36410
+ async function getAgentForUrl(url) {
36411
+ if (proxyConfig.type === "none") {
36412
+ return void 0;
36413
+ }
36414
+ if (shouldBypassProxy(url)) {
36415
+ logger.debug(`Bypassing proxy for ${url} (matches NO_PROXY)`, "PROXY");
36416
+ return void 0;
36417
+ }
36418
+ if (proxyConfig.type === "pac" && proxyConfig.pacResolver) {
36419
+ try {
36420
+ const result = await proxyConfig.pacResolver(url);
36421
+ const directives = result.split(";");
36422
+ for (const rawDirective of directives) {
36423
+ const directive = rawDirective.trim();
36424
+ if (!directive) continue;
36425
+ if (directive.toUpperCase() === "DIRECT") {
36426
+ logger.debug(`PAC returned DIRECT for ${url}`, "PROXY");
36427
+ return void 0;
36428
+ }
36429
+ const socksMatch = directive.match(/SOCKS5?\s+(\S+):(\d+)/i);
36430
+ if (socksMatch) {
36431
+ const proxyUrl = `socks5://${socksMatch[1]}:${socksMatch[2]}`;
36432
+ logger.debug(`PAC returned SOCKS proxy for ${url}: ${sanitizeProxyUrl(proxyUrl)}`, "PROXY");
36433
+ return new SocksProxyAgent(proxyUrl);
36434
+ }
36435
+ const proxyMatch = directive.match(/PROXY\s+(\S+):(\d+)/i);
36436
+ if (proxyMatch) {
36437
+ const proxyUrl = `http://${proxyMatch[1]}:${proxyMatch[2]}`;
36438
+ logger.debug(`PAC returned HTTP proxy for ${url}: ${sanitizeProxyUrl(proxyUrl)}`, "PROXY");
36439
+ return new HttpsProxyAgent(proxyUrl);
36440
+ }
36441
+ }
36442
+ logger.debug(`PAC returned no usable proxy for ${url}: ${result}`, "PROXY");
36443
+ } catch (error) {
36444
+ logger.warn(`PAC evaluation failed for ${url}: ${error}`, "PROXY");
36445
+ }
36446
+ return void 0;
36447
+ }
36448
+ if (proxyConfig.type === "env" && proxyConfig.envProxy) {
36449
+ const { url: proxyUrl, type } = proxyConfig.envProxy;
36450
+ try {
36451
+ logger.debug(`Using env proxy ${sanitizeProxyUrl(proxyUrl)} for ${url}`, "PROXY");
36452
+ return type === "socks" ? new SocksProxyAgent(proxyUrl) : new HttpsProxyAgent(proxyUrl);
36453
+ } catch (error) {
36454
+ logger.error(`Invalid proxy URL "${proxyUrl}": ${error}`, "PROXY");
36455
+ return void 0;
36456
+ }
36457
+ }
36458
+ return void 0;
36459
+ }
36460
+
36251
36461
  // src/lib/fetch-utils.ts
36252
36462
  async function setupFetchPolyfill() {
36253
36463
  if (typeof globalThis.fetch !== "function") {
@@ -36267,6 +36477,22 @@ async function setupFetchPolyfill() {
36267
36477
  } else {
36268
36478
  logger.info("Using native fetch API", "SYSTEM");
36269
36479
  }
36480
+ if (getConfig().useSystemProxy) {
36481
+ await initializeProxy();
36482
+ } else {
36483
+ logger.debug("System proxy support disabled (USE_SYSTEM_PROXY=false)", "PROXY");
36484
+ }
36485
+ }
36486
+ async function proxyFetch(url, init) {
36487
+ if (!getConfig().useSystemProxy) {
36488
+ return fetch(url, init);
36489
+ }
36490
+ const agent = await getAgentForUrl(url);
36491
+ if (agent) {
36492
+ const nodeFetch = (await Promise.resolve().then(() => (init_src(), src_exports))).default;
36493
+ return nodeFetch(url, { ...init, agent });
36494
+ }
36495
+ return fetch(url, init);
36270
36496
  }
36271
36497
 
36272
36498
  // src/lib/wordpress-api.ts
@@ -36781,7 +37007,7 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl) {
36781
37007
  const metadataUrl = new URL("/.well-known/oauth-authorization-server", authorizationServerUrl);
36782
37008
  logger.oauth(`Discovering authorization server metadata: ${metadataUrl}`);
36783
37009
  const customHeaders = getCustomHeaders();
36784
- const response = await fetch(metadataUrl.toString(), {
37010
+ const response = await proxyFetch(metadataUrl.toString(), {
36785
37011
  headers: {
36786
37012
  "Accept": "application/json",
36787
37013
  ...customHeaders
@@ -36818,7 +37044,7 @@ async function discoverProtectedResourceMetadata(resourceUrl) {
36818
37044
  const metadataUrl = new URL("/.well-known/oauth-protected-resource", url.origin);
36819
37045
  logger.oauth(`Discovering protected resource metadata: ${metadataUrl}`);
36820
37046
  const customHeaders = getCustomHeaders();
36821
- const response = await fetch(metadataUrl.toString(), {
37047
+ const response = await proxyFetch(metadataUrl.toString(), {
36822
37048
  headers: {
36823
37049
  "Accept": "application/json",
36824
37050
  ...customHeaders
@@ -36884,7 +37110,7 @@ async function registerDynamicClient(registrationEndpoint, registrationRequest)
36884
37110
  try {
36885
37111
  logger.oauth(`Attempting dynamic client registration: ${registrationEndpoint}`);
36886
37112
  const customHeaders = getCustomHeaders();
36887
- const response = await fetch(registrationEndpoint, {
37113
+ const response = await proxyFetch(registrationEndpoint, {
36888
37114
  method: "POST",
36889
37115
  headers: {
36890
37116
  "Content-Type": "application/json",
@@ -36936,7 +37162,7 @@ async function exchangeAuthorizationCode(tokenEndpoint, code, redirectUri, clien
36936
37162
  params.set("resource", resource);
36937
37163
  }
36938
37164
  const customHeaders = getCustomHeaders();
36939
- const response = await fetch(tokenEndpoint, {
37165
+ const response = await proxyFetch(tokenEndpoint, {
36940
37166
  method: "POST",
36941
37167
  headers: {
36942
37168
  "Content-Type": "application/x-www-form-urlencoded",
@@ -37404,7 +37630,7 @@ var MCPOAuthProvider = class {
37404
37630
  try {
37405
37631
  logger.oauth("Attempting discovery via 401 response method");
37406
37632
  const customHeaders = getCustomHeaders();
37407
- const response = await fetch(this.config.serverUrl, {
37633
+ const response = await proxyFetch(this.config.serverUrl, {
37408
37634
  headers: {
37409
37635
  Accept: "application/json",
37410
37636
  ...customHeaders
@@ -37416,7 +37642,7 @@ var MCPOAuthProvider = class {
37416
37642
  const authInfo = parseWWWAuthenticateHeader(wwwAuthHeader);
37417
37643
  logger.oauth("WWW-Authenticate header parsed successfully");
37418
37644
  if (authInfo.resource_metadata_url) {
37419
- const metadataResponse = await fetch(authInfo.resource_metadata_url, {
37645
+ const metadataResponse = await proxyFetch(authInfo.resource_metadata_url, {
37420
37646
  headers: {
37421
37647
  "Accept": "application/json",
37422
37648
  ...customHeaders
@@ -38491,7 +38717,7 @@ async function wpRequest(requestData, useJsonRpc = true) {
38491
38717
  logger.api("Sending request to WordPress API...");
38492
38718
  logger.debug(`Request URL: ${url}`, "API");
38493
38719
  logger.debug(`Request method: ${method}`, "API");
38494
- const response = await fetch(url, fetchOptions);
38720
+ const response = await proxyFetch(url, fetchOptions);
38495
38721
  logger.debug(`Response status: ${response.status}`, "API");
38496
38722
  if (!response.ok) {
38497
38723
  const errorText = await response.text();
@@ -38578,28 +38804,83 @@ function createSessionContext() {
38578
38804
  }
38579
38805
 
38580
38806
  // src/lib/transport-detection.ts
38581
- async function detectTransportType(context) {
38582
- logger.info("Initializing connection to WordPress API with transport detection...", "PROXY");
38807
+ async function detectTransportType(context, initParams) {
38808
+ logger.info("\u{1F50D} Starting transport detection and WordPress API initialization...", "TRANSPORT_DETECT");
38583
38809
  let init;
38584
38810
  let transportType = null;
38811
+ const enhancedParams = initParams ? { ...initParams } : {};
38812
+ if (enhancedParams.clientInfo) {
38813
+ if (typeof enhancedParams.clientInfo === "object" && enhancedParams.clientInfo !== null && !Array.isArray(enhancedParams.clientInfo)) {
38814
+ const originalClient = enhancedParams.clientInfo?.name || "unknown";
38815
+ const newClientInfo = { ...enhancedParams.clientInfo };
38816
+ if (newClientInfo.proxied && typeof newClientInfo.proxied === "object") {
38817
+ newClientInfo.proxied = {
38818
+ ...newClientInfo.proxied,
38819
+ name: "@automattic/mcp-wordpress-remote",
38820
+ version: MCP_WORDPRESS_REMOTE_VERSION
38821
+ };
38822
+ } else {
38823
+ newClientInfo.proxied = {
38824
+ name: "@automattic/mcp-wordpress-remote",
38825
+ version: MCP_WORDPRESS_REMOTE_VERSION
38826
+ };
38827
+ }
38828
+ enhancedParams.clientInfo = newClientInfo;
38829
+ logger.info("\u{1F4CB} Added proxy information to clientInfo", "TRANSPORT_DETECT", {
38830
+ originalClient,
38831
+ proxyName: "@automattic/mcp-wordpress-remote",
38832
+ proxyVersion: MCP_WORDPRESS_REMOTE_VERSION
38833
+ });
38834
+ } else {
38835
+ logger.warn("clientInfo is present but not a valid object, skipping enhancement", "TRANSPORT_DETECT", {
38836
+ clientInfoType: typeof enhancedParams.clientInfo,
38837
+ isArray: Array.isArray(enhancedParams.clientInfo),
38838
+ isNull: enhancedParams.clientInfo === null
38839
+ });
38840
+ }
38841
+ } else {
38842
+ logger.debug("No clientInfo provided in initialize parameters", "TRANSPORT_DETECT");
38843
+ }
38585
38844
  try {
38586
- logger.info("Attempting JSON-RPC transport...", "PROXY");
38587
- const initMessage = addSessionInfo({ method: "initialize" }, {}, context);
38845
+ logger.info("\u{1F4E1} Attempting JSON-RPC transport...", "TRANSPORT_DETECT");
38846
+ const wpRequestParams = {
38847
+ method: "initialize",
38848
+ ...enhancedParams
38849
+ };
38850
+ const initMessage = addSessionInfo(wpRequestParams, {}, context);
38851
+ logger.info("Sending initialization message via JSON-RPC:", "TRANSPORT_DETECT", {
38852
+ method: initMessage.method,
38853
+ id: initMessage.id,
38854
+ jsonrpc: initMessage.jsonrpc,
38855
+ hasParams: !!initMessage.params && Object.keys(initMessage.params).length > 1
38856
+ // More than just _proxy_request_id
38857
+ });
38858
+ logger.debug("Complete JSON-RPC init message:", "TRANSPORT_DETECT", initMessage);
38588
38859
  const initResponse = await wpRequest(initMessage, true);
38589
38860
  init = initResponse;
38590
38861
  transportType = "jsonrpc";
38591
- logger.info("\u2705 JSON-RPC transport detected and working", "PROXY");
38862
+ logger.info("\u2705 JSON-RPC transport detected and working", "TRANSPORT_DETECT");
38863
+ logger.debug("JSON-RPC initialization response:", "TRANSPORT_DETECT", init);
38592
38864
  } catch (error) {
38593
- logger.warn("JSON-RPC transport failed, trying simple transport...", "PROXY");
38594
- logger.debug("JSON-RPC error:", "PROXY", error);
38865
+ logger.warn("\u26A0\uFE0F JSON-RPC transport failed, trying simple transport...", "TRANSPORT_DETECT");
38866
+ logger.debug("JSON-RPC error details:", "TRANSPORT_DETECT", error);
38595
38867
  try {
38596
- const simpleInitRequest = { method: "initialize" };
38597
- const initResponse = await wpRequest(simpleInitRequest, false);
38868
+ const simpleRequestParams = {
38869
+ method: "initialize",
38870
+ ...enhancedParams
38871
+ };
38872
+ logger.info("Sending initialization message via Simple transport:", "TRANSPORT_DETECT", {
38873
+ method: simpleRequestParams.method,
38874
+ hasParams: Object.keys(simpleRequestParams).length > 1
38875
+ });
38876
+ logger.debug("Complete Simple init message:", "TRANSPORT_DETECT", simpleRequestParams);
38877
+ const initResponse = await wpRequest(simpleRequestParams, false);
38598
38878
  init = initResponse;
38599
38879
  transportType = "simple";
38600
- logger.info("\u2705 Simple transport detected and working", "PROXY");
38880
+ logger.info("\u2705 Simple transport detected and working", "TRANSPORT_DETECT");
38881
+ logger.debug("Simple initialization response:", "TRANSPORT_DETECT", init);
38601
38882
  } catch (simpleError) {
38602
- logger.error("Both JSON-RPC and simple transports failed", "PROXY", simpleError);
38883
+ logger.error("\u274C Both JSON-RPC and simple transports failed", "TRANSPORT_DETECT", simpleError);
38603
38884
  throw new Error("Unable to establish connection with either transport type");
38604
38885
  }
38605
38886
  }
@@ -38621,36 +38902,54 @@ async function detectTransportType(context) {
38621
38902
 
38622
38903
  // src/lib/error-utils.ts
38623
38904
  function mapHttpStatusToMcpCode(statusCode) {
38624
- const MCP_ERROR_CODES = {
38905
+ const JSONRPC_ERROR_CODES = {
38625
38906
  PARSE_ERROR: -32700,
38626
38907
  INVALID_REQUEST: -32600,
38627
38908
  METHOD_NOT_FOUND: -32601,
38628
38909
  INVALID_PARAMS: -32602,
38629
- INTERNAL_ERROR: -32603,
38630
- UNAUTHORIZED: -32010,
38631
- PERMISSION_DENIED: -32008
38910
+ INTERNAL_ERROR: -32603
38911
+ };
38912
+ const MCP_ERROR_CODES = {
38913
+ SERVER_ERROR: -32e3,
38914
+ // Generic server error
38915
+ TIMEOUT_ERROR: -32001,
38916
+ // Request timeout
38917
+ RESOURCE_NOT_FOUND: -32002,
38918
+ // Resource not found
38919
+ TOOL_NOT_FOUND: -32003,
38920
+ // Tool not found
38921
+ PROMPT_NOT_FOUND: -32004,
38922
+ // Prompt not found
38923
+ PERMISSION_DENIED: -32008,
38924
+ // Access denied/forbidden
38925
+ UNAUTHORIZED: -32010
38926
+ // Authentication required
38632
38927
  };
38633
38928
  switch (statusCode) {
38634
38929
  case 400:
38635
- return MCP_ERROR_CODES.INVALID_REQUEST;
38930
+ return JSONRPC_ERROR_CODES.INVALID_REQUEST;
38636
38931
  case 401:
38637
38932
  return MCP_ERROR_CODES.UNAUTHORIZED;
38638
38933
  case 403:
38639
38934
  return MCP_ERROR_CODES.PERMISSION_DENIED;
38640
38935
  case 404:
38641
- return MCP_ERROR_CODES.METHOD_NOT_FOUND;
38936
+ return JSONRPC_ERROR_CODES.METHOD_NOT_FOUND;
38937
+ case 408:
38938
+ return MCP_ERROR_CODES.TIMEOUT_ERROR;
38939
+ case 413:
38940
+ // Payload Too Large
38642
38941
  case 422:
38643
- return MCP_ERROR_CODES.INVALID_PARAMS;
38942
+ return JSONRPC_ERROR_CODES.INVALID_PARAMS;
38644
38943
  case 500:
38645
- // Internal Server Error
38944
+ return JSONRPC_ERROR_CODES.INTERNAL_ERROR;
38646
38945
  case 502:
38647
38946
  // Bad Gateway
38648
38947
  case 503:
38649
- // Service Unavailable
38948
+ return MCP_ERROR_CODES.SERVER_ERROR;
38650
38949
  case 504:
38651
- // Gateway Timeout
38950
+ return MCP_ERROR_CODES.TIMEOUT_ERROR;
38652
38951
  default:
38653
- return MCP_ERROR_CODES.INTERNAL_ERROR;
38952
+ return JSONRPC_ERROR_CODES.INTERNAL_ERROR;
38654
38953
  }
38655
38954
  }
38656
38955
  function convertAPIErrorToMcpError(error) {
@@ -38680,17 +38979,38 @@ function createRequestHandler(config, context) {
38680
38979
  function createWrappedHandler(config, context) {
38681
38980
  const handler = createRequestHandler(config, context);
38682
38981
  return async (request) => {
38683
- logger.debug(`Received ${config.name} request`, "MCP", request);
38982
+ logger.info(`\u{1F4E9} Client Message: ${config.name}`, "CLIENT");
38983
+ logger.info(`Request ID: ${request.id || "none"} | Method: ${config.method}`, "CLIENT");
38984
+ if (request.params && Object.keys(request.params).length > 0) {
38985
+ logger.info(`Request parameters:`, "CLIENT", {
38986
+ paramCount: Object.keys(request.params).length,
38987
+ paramKeys: Object.keys(request.params)
38988
+ });
38989
+ logger.debug(`Full request parameters:`, "CLIENT", request.params);
38990
+ } else {
38991
+ logger.info(`No request parameters`, "CLIENT");
38992
+ }
38684
38993
  logger.debug(
38685
- `Adding session info - Session ID: ${context.sessionId}, MCP Request ID: ${request.id}`,
38686
- "SESSION"
38994
+ `Session context - ID: ${context.sessionId || "none"}, Transport: ${context.transportType || "detecting"}, Counter: ${context.requestIdCounter}`,
38995
+ "CLIENT"
38687
38996
  );
38997
+ logger.debug(`Complete client request object:`, "CLIENT", request);
38998
+ const startTime = Date.now();
38688
38999
  try {
38689
39000
  const response = await handler(request);
38690
- logger.debug(`${config.name} response sent`, "MCP");
39001
+ const duration = Date.now() - startTime;
39002
+ logger.info(`\u2705 Client Response: ${config.name} completed in ${duration}ms`, "CLIENT");
39003
+ logger.debug(`Response sent to client:`, "CLIENT", {
39004
+ hasResponse: !!response,
39005
+ responseKeys: response && typeof response === "object" ? Object.keys(response) : "primitive"
39006
+ });
38691
39007
  return response;
38692
39008
  } catch (error) {
38693
- logger.error(`Error handling ${config.name} request`, "MCP", error);
39009
+ const duration = Date.now() - startTime;
39010
+ logger.error(`\u274C Client Error: ${config.name} failed after ${duration}ms`, "CLIENT", {
39011
+ error: error instanceof Error ? error.message : String(error),
39012
+ requestId: request.id
39013
+ });
38694
39014
  if (isAPIError(error) && context.transportType === "simple") {
38695
39015
  logger.debug(`Converting APIError to MCP error format for ${config.name} (simple transport)`, "MCP", {
38696
39016
  statusCode: error.statusCode,
@@ -38815,17 +39135,57 @@ async function WordPressProxy() {
38815
39135
  logger.warn("Error cleaning up expired tokens", "PROXY", error);
38816
39136
  }
38817
39137
  const sessionContext = createSessionContext();
38818
- const { initResult } = await detectTransportType(sessionContext);
38819
39138
  const server = new Server(
38820
39139
  {
38821
- name: initResult.serverInfo.name,
38822
- version: initResult.serverInfo.version
39140
+ name: "WordPress MCP Remote Proxy",
39141
+ version: MCP_WORDPRESS_REMOTE_VERSION
38823
39142
  },
38824
39143
  {
38825
- capabilities: initResult.capabilities
38826
- // Type assertion to fix linter error
39144
+ capabilities: {
39145
+ tools: {},
39146
+ resources: {},
39147
+ prompts: {},
39148
+ logging: {},
39149
+ completions: {}
39150
+ }
38827
39151
  }
38828
39152
  );
39153
+ server.setRequestHandler(InitializeRequestSchema, async (request) => {
39154
+ logger.info("\u{1F4E9} Client Initialize Request received", "INIT");
39155
+ logger.debug("Initialize request details:", "INIT", request);
39156
+ try {
39157
+ logger.info("\u{1F504} Initializing WordPress connection with client parameters", "INIT");
39158
+ const { initResult } = await detectTransportType(sessionContext, request.params);
39159
+ const wordpressInitResponse = {
39160
+ protocolVersion: initResult.protocolVersion || "2025-06-18",
39161
+ serverInfo: initResult.serverInfo,
39162
+ capabilities: initResult.capabilities,
39163
+ instructions: initResult.instructions || "MCP WordPress Remote Proxy Server"
39164
+ };
39165
+ logger.info("\u2705 Returning WordPress server initialize response", "INIT");
39166
+ logger.debug("Initialize response:", "INIT", wordpressInitResponse);
39167
+ return wordpressInitResponse;
39168
+ } catch (error) {
39169
+ logger.error("\u274C Failed to initialize WordPress connection with client parameters", "INIT", error);
39170
+ const fallbackResponse = {
39171
+ protocolVersion: "2025-06-18",
39172
+ serverInfo: {
39173
+ name: "WordPress MCP Remote Proxy",
39174
+ version: MCP_WORDPRESS_REMOTE_VERSION
39175
+ },
39176
+ capabilities: {
39177
+ tools: {},
39178
+ resources: {},
39179
+ prompts: {},
39180
+ logging: {},
39181
+ completions: {}
39182
+ },
39183
+ instructions: "MCP WordPress Remote Proxy Server (Connection Failed)"
39184
+ };
39185
+ logger.warn("\u26A0\uFE0F Using fallback initialize response", "INIT");
39186
+ return fallbackResponse;
39187
+ }
39188
+ });
38829
39189
  server.setRequestHandler(ListToolsRequestSchema, createWrappedHandler(HANDLER_CONFIGS.listTools, sessionContext));
38830
39190
  server.setRequestHandler(CallToolRequestSchema, createWrappedHandler(HANDLER_CONFIGS.callTool, sessionContext));
38831
39191
  server.setRequestHandler(ListResourcesRequestSchema, createWrappedHandler(HANDLER_CONFIGS.listResources, sessionContext));
@@ -38839,6 +39199,25 @@ async function WordPressProxy() {
38839
39199
  server.setRequestHandler(CompleteRequestSchema, createWrappedHandler(HANDLER_CONFIGS.complete, sessionContext));
38840
39200
  server.setRequestHandler(ListRootsRequestSchema, createWrappedHandler(HANDLER_CONFIGS.listRoots, sessionContext));
38841
39201
  const transport = new StdioServerTransport();
39202
+ transport.onmessage = (message) => {
39203
+ const msg = message;
39204
+ const method = typeof msg?.method === "string" ? msg.method : "unknown";
39205
+ const id = msg?.id ?? "none";
39206
+ const hasParams = Boolean(msg?.params && typeof msg.params === "object" && Object.keys(msg.params).length);
39207
+ logger.info("\u{1F4E5} Raw client message received", "TRANSPORT", {
39208
+ method,
39209
+ id,
39210
+ hasParams,
39211
+ messageType: method === "unknown" ? "response/notification" : "request"
39212
+ });
39213
+ logger.debug("Complete raw message:", "TRANSPORT", message);
39214
+ };
39215
+ transport.onerror = (error) => {
39216
+ logger.error("\u274C Transport error:", "TRANSPORT", error);
39217
+ };
39218
+ transport.onclose = () => {
39219
+ logger.info("\u{1F50C} Transport connection closed", "TRANSPORT");
39220
+ };
38842
39221
  server.connect(transport).then(() => {
38843
39222
  logger.info("MCP server connected to transport successfully", "PROXY");
38844
39223
  }).catch((error) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/mcp-wordpress-remote",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "description": "MCP WordPress Remote proxy server",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -59,9 +59,13 @@
59
59
  },
60
60
  "dependencies": {
61
61
  "@modelcontextprotocol/sdk": "^1.8.0",
62
+ "@tootallnate/quickjs-emscripten": "^0.23.0",
62
63
  "express": "^4.18.2",
64
+ "https-proxy-agent": "^7.0.6",
63
65
  "node-fetch": "^3.3.2",
64
- "open": "^10.0.0"
66
+ "open": "^10.0.0",
67
+ "pac-resolver": "^7.0.1",
68
+ "socks-proxy-agent": "^8.0.5"
65
69
  },
66
70
  "devDependencies": {
67
71
  "@playwright/test": "^1.54.2",
@@ -101,7 +105,11 @@
101
105
  "open"
102
106
  ],
103
107
  "external": [
104
- "node:*"
108
+ "node:*",
109
+ "@tootallnate/quickjs-emscripten",
110
+ "pac-resolver",
111
+ "socks-proxy-agent",
112
+ "https-proxy-agent"
105
113
  ],
106
114
  "minify": false,
107
115
  "sourcemap": false,