@automattic/mcp-wordpress-remote 0.2.16 → 0.2.17

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.16";
36039
+ var MCP_WORDPRESS_REMOTE_VERSION = "0.2.17";
36040
36040
  var CONFIG = {
36041
36041
  // API Configuration
36042
36042
  WP_API_URL: process.env.WP_API_URL || "https://example.com",
@@ -36082,6 +36082,9 @@ var CONFIG = {
36082
36082
  JWT_TOKEN: process.env.JWT_TOKEN,
36083
36083
  WOO_CUSTOMER_KEY: process.env.WOO_CUSTOMER_KEY,
36084
36084
  WOO_CUSTOMER_SECRET: process.env.WOO_CUSTOMER_SECRET,
36085
+ // Custom Headers Configuration
36086
+ CUSTOM_HEADERS: process.env.CUSTOM_HEADERS || "",
36087
+ // JSON string or comma-separated header:value pairs
36085
36088
  // Environment
36086
36089
  NODE_ENV: process.env.NODE_ENV || "development"
36087
36090
  };
@@ -36095,17 +36098,54 @@ function getDefaultOAuthScopes() {
36095
36098
  const defaultScopes = ["read", "write"];
36096
36099
  return parseOAuthScopes(CONFIG.OAUTH_SCOPES, defaultScopes);
36097
36100
  }
36101
+ function parseCustomHeaders(customHeadersString) {
36102
+ if (!customHeadersString || customHeadersString.trim() === "") {
36103
+ return {};
36104
+ }
36105
+ try {
36106
+ if (customHeadersString.trim().startsWith("{")) {
36107
+ return JSON.parse(customHeadersString);
36108
+ }
36109
+ const headers = {};
36110
+ const pairs = customHeadersString.split(",");
36111
+ for (const pair of pairs) {
36112
+ const colonIndex = pair.indexOf(":");
36113
+ if (colonIndex > 0) {
36114
+ const key = pair.substring(0, colonIndex).trim();
36115
+ const value = pair.substring(colonIndex + 1).trim();
36116
+ if (key && value) {
36117
+ headers[key] = value;
36118
+ }
36119
+ }
36120
+ }
36121
+ return headers;
36122
+ } catch (error) {
36123
+ logger.error("Error parsing custom headers", "CONFIG", error);
36124
+ return {};
36125
+ }
36126
+ }
36127
+ function getCustomHeaders() {
36128
+ const customHeadersEnv = process.env.CUSTOM_HEADERS || "";
36129
+ return parseCustomHeaders(customHeadersEnv);
36130
+ }
36098
36131
  function validateConfig() {
36099
36132
  const errors = [];
36100
- const hasJWT = !!CONFIG.JWT_TOKEN;
36101
- const hasBasicAuth = !!(CONFIG.WP_API_USERNAME && CONFIG.WP_API_PASSWORD);
36102
- const hasOAuth = CONFIG.OAUTH_ENABLED;
36103
- if (!hasJWT && !hasBasicAuth && !hasOAuth) {
36133
+ const currentApiUrl = process.env.WP_API_URL || CONFIG.WP_API_URL;
36134
+ const currentCustomHeaders = process.env.CUSTOM_HEADERS || CONFIG.CUSTOM_HEADERS;
36135
+ const currentJwtToken = process.env.JWT_TOKEN || CONFIG.JWT_TOKEN;
36136
+ const currentUsername = process.env.WP_API_USERNAME || CONFIG.WP_API_USERNAME;
36137
+ const currentPassword = process.env.WP_API_PASSWORD || CONFIG.WP_API_PASSWORD;
36138
+ const currentOAuthEnabled = process.env.OAUTH_ENABLED === "true" || CONFIG.OAUTH_ENABLED;
36139
+ const hasJWT = !!currentJwtToken;
36140
+ const hasBasicAuth = !!(currentUsername && currentPassword);
36141
+ const hasOAuth = currentOAuthEnabled;
36142
+ const hasCustomHeaders = !!currentCustomHeaders && currentCustomHeaders.trim() !== "";
36143
+ if (!hasJWT && !hasBasicAuth && !hasOAuth && !hasCustomHeaders) {
36104
36144
  errors.push(
36105
- "No authentication method configured. Please set one of: JWT_TOKEN, WP_API_USERNAME+WP_API_PASSWORD, or enable OAuth"
36145
+ "No authentication method configured. Please set one of: JWT_TOKEN, WP_API_USERNAME+WP_API_PASSWORD, enable OAuth, or set CUSTOM_HEADERS"
36106
36146
  );
36107
36147
  }
36108
- if (!CONFIG.WP_API_URL || CONFIG.WP_API_URL === "https://example.com") {
36148
+ if (!currentApiUrl || currentApiUrl === "https://example.com") {
36109
36149
  errors.push("WP_API_URL must be set to your WordPress site URL");
36110
36150
  }
36111
36151
  if (CONFIG.OAUTH_ENABLED) {
@@ -36139,7 +36179,8 @@ function formatConfigError(error) {
36139
36179
  return `${error}. Configure one of these options:
36140
36180
  \u2022 JWT_TOKEN=your_jwt_token (preferred for APIs)
36141
36181
  \u2022 WP_API_USERNAME=username and WP_API_PASSWORD=app_password (for application passwords)
36142
- \u2022 Set OAUTH_ENABLED=true and WP_OAUTH_CLIENT_ID=your_client_id (for OAuth 2.1)`;
36182
+ \u2022 Set OAUTH_ENABLED=true and WP_OAUTH_CLIENT_ID=your_client_id (for OAuth 2.1)
36183
+ \u2022 CUSTOM_HEADERS='{"X-API-Key": "your_api_key"}' (for custom header authentication)`;
36143
36184
  }
36144
36185
  if (error.includes("OAUTH_CALLBACK_PORT")) {
36145
36186
  return `${error}. The port must be available for the OAuth callback server. Try a different port like 7777, 7890, or other ports in the safe 7000-7999 range.`;
@@ -36739,7 +36780,13 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl) {
36739
36780
  try {
36740
36781
  const metadataUrl = new URL("/.well-known/oauth-authorization-server", authorizationServerUrl);
36741
36782
  logger.oauth(`Discovering authorization server metadata: ${metadataUrl}`);
36742
- const response = await fetch(metadataUrl.toString());
36783
+ const customHeaders = getCustomHeaders();
36784
+ const response = await fetch(metadataUrl.toString(), {
36785
+ headers: {
36786
+ "Accept": "application/json",
36787
+ ...customHeaders
36788
+ }
36789
+ });
36743
36790
  if (!response.ok) {
36744
36791
  throw new OAuthError(
36745
36792
  `Failed to fetch authorization server metadata: ${response.status}`,
@@ -36770,7 +36817,13 @@ async function discoverProtectedResourceMetadata(resourceUrl) {
36770
36817
  const url = new URL(resourceUrl);
36771
36818
  const metadataUrl = new URL("/.well-known/oauth-protected-resource", url.origin);
36772
36819
  logger.oauth(`Discovering protected resource metadata: ${metadataUrl}`);
36773
- const response = await fetch(metadataUrl.toString());
36820
+ const customHeaders = getCustomHeaders();
36821
+ const response = await fetch(metadataUrl.toString(), {
36822
+ headers: {
36823
+ "Accept": "application/json",
36824
+ ...customHeaders
36825
+ }
36826
+ });
36774
36827
  if (!response.ok) {
36775
36828
  throw new OAuthError(
36776
36829
  `Failed to fetch protected resource metadata: ${response.status}`,
@@ -36830,10 +36883,12 @@ function parseWWWAuthenticateHeader(headerValue) {
36830
36883
  async function registerDynamicClient(registrationEndpoint, registrationRequest) {
36831
36884
  try {
36832
36885
  logger.oauth(`Attempting dynamic client registration: ${registrationEndpoint}`);
36886
+ const customHeaders = getCustomHeaders();
36833
36887
  const response = await fetch(registrationEndpoint, {
36834
36888
  method: "POST",
36835
36889
  headers: {
36836
- "Content-Type": "application/json"
36890
+ "Content-Type": "application/json",
36891
+ ...customHeaders
36837
36892
  },
36838
36893
  body: JSON.stringify(registrationRequest)
36839
36894
  });
@@ -36880,10 +36935,12 @@ async function exchangeAuthorizationCode(tokenEndpoint, code, redirectUri, clien
36880
36935
  if (resource) {
36881
36936
  params.set("resource", resource);
36882
36937
  }
36938
+ const customHeaders = getCustomHeaders();
36883
36939
  const response = await fetch(tokenEndpoint, {
36884
36940
  method: "POST",
36885
36941
  headers: {
36886
- "Content-Type": "application/x-www-form-urlencoded"
36942
+ "Content-Type": "application/x-www-form-urlencoded",
36943
+ ...customHeaders
36887
36944
  },
36888
36945
  body: params.toString()
36889
36946
  });
@@ -37346,9 +37403,11 @@ var MCPOAuthProvider = class {
37346
37403
  async discoverVia401Response() {
37347
37404
  try {
37348
37405
  logger.oauth("Attempting discovery via 401 response method");
37406
+ const customHeaders = getCustomHeaders();
37349
37407
  const response = await fetch(this.config.serverUrl, {
37350
37408
  headers: {
37351
- Accept: "application/json"
37409
+ Accept: "application/json",
37410
+ ...customHeaders
37352
37411
  }
37353
37412
  });
37354
37413
  if (response.status === 401) {
@@ -37357,7 +37416,12 @@ var MCPOAuthProvider = class {
37357
37416
  const authInfo = parseWWWAuthenticateHeader(wwwAuthHeader);
37358
37417
  logger.oauth("WWW-Authenticate header parsed successfully");
37359
37418
  if (authInfo.resource_metadata_url) {
37360
- const metadataResponse = await fetch(authInfo.resource_metadata_url);
37419
+ const metadataResponse = await fetch(authInfo.resource_metadata_url, {
37420
+ headers: {
37421
+ "Accept": "application/json",
37422
+ ...customHeaders
37423
+ }
37424
+ });
37361
37425
  if (metadataResponse.ok) {
37362
37426
  this.resourceMetadata = await metadataResponse.json();
37363
37427
  logger.oauth("Protected resource metadata obtained via 401 response");
@@ -38381,25 +38445,43 @@ async function wpRequest(requestData, useJsonRpc = true) {
38381
38445
  authHeader = `Basic ${auth2}`;
38382
38446
  logger.debug(`Auth header length: ${auth2.length}`, "AUTH");
38383
38447
  }
38384
- if (!authHeader) {
38448
+ const customHeaders = getCustomHeaders();
38449
+ const hasCustomHeaders = Object.keys(customHeaders).length > 0;
38450
+ if (!authHeader && !hasCustomHeaders) {
38385
38451
  throw new AuthError(
38386
- "No authentication method available. Please configure JWT_TOKEN, OAuth, or Basic Auth (WP_API_USERNAME+WP_API_PASSWORD).",
38452
+ "No authentication method available. Please configure JWT_TOKEN, OAuth, Basic Auth (WP_API_USERNAME+WP_API_PASSWORD), or CUSTOM_HEADERS.",
38387
38453
  "NO_AUTH_METHOD"
38388
38454
  );
38389
38455
  }
38456
+ const currentApiUrl = process.env.WP_API_URL || CONFIG.WP_API_URL;
38390
38457
  logger.debug(`Environment: ${CONFIG.NODE_ENV}`, "API");
38391
- logger.debug(`Base API URL: ${CONFIG.WP_API_URL}`, "API");
38392
- const url = constructApiUrl(CONFIG.WP_API_URL, endpoint);
38458
+ logger.debug(`Base API URL: ${currentApiUrl}`, "API");
38459
+ const url = constructApiUrl(currentApiUrl, endpoint);
38393
38460
  logger.debug(`Final requesting URL: ${url}`, "API");
38394
38461
  const headers = {
38395
- Authorization: authHeader,
38396
38462
  "Content-Type": "application/json",
38397
- "MCP-Protocol-Version": "2025-06-18"
38463
+ "MCP-Protocol-Version": "2025-06-18",
38398
38464
  // MCP protocol version
38465
+ ...customHeaders
38466
+ // Merge custom headers
38399
38467
  };
38468
+ if (authHeader) {
38469
+ headers.Authorization = authHeader;
38470
+ }
38400
38471
  if (globalSessionId) {
38401
38472
  headers["Mcp-Session-Id"] = globalSessionId;
38402
38473
  }
38474
+ if (authHeader) {
38475
+ logger.debug("Using Authorization header for authentication", "API");
38476
+ } else if (hasCustomHeaders) {
38477
+ logger.auth("Using custom headers for authentication (no Authorization header)");
38478
+ }
38479
+ if (hasCustomHeaders) {
38480
+ logger.debug(`Custom headers added: ${Object.keys(customHeaders).join(", ")}`, "API");
38481
+ for (const [key, value] of Object.entries(customHeaders)) {
38482
+ logger.debug(`Header ${key}: ${value.length} characters`, "API");
38483
+ }
38484
+ }
38403
38485
  const fetchOptions = {
38404
38486
  method,
38405
38487
  headers,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/mcp-wordpress-remote",
3
- "version": "0.2.16",
3
+ "version": "0.2.17",
4
4
  "description": "MCP WordPress Remote proxy server",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"