@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/README.md +1 -1
- package/dist/lib.d.ts +85 -2
- package/dist/lib.js +7844 -1075
- package/dist/proxy.js +421 -42
- package/package.json +11 -3
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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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("
|
|
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...", "
|
|
38587
|
-
const
|
|
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", "
|
|
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...", "
|
|
38594
|
-
logger.debug("JSON-RPC 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
|
|
38597
|
-
|
|
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", "
|
|
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", "
|
|
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
|
|
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
|
-
|
|
38631
|
-
|
|
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
|
|
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
|
|
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
|
|
38942
|
+
return JSONRPC_ERROR_CODES.INVALID_PARAMS;
|
|
38644
38943
|
case 500:
|
|
38645
|
-
|
|
38944
|
+
return JSONRPC_ERROR_CODES.INTERNAL_ERROR;
|
|
38646
38945
|
case 502:
|
|
38647
38946
|
// Bad Gateway
|
|
38648
38947
|
case 503:
|
|
38649
|
-
|
|
38948
|
+
return MCP_ERROR_CODES.SERVER_ERROR;
|
|
38650
38949
|
case 504:
|
|
38651
|
-
|
|
38950
|
+
return MCP_ERROR_CODES.TIMEOUT_ERROR;
|
|
38652
38951
|
default:
|
|
38653
|
-
return
|
|
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.
|
|
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
|
-
`
|
|
38686
|
-
"
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
38822
|
-
version:
|
|
39140
|
+
name: "WordPress MCP Remote Proxy",
|
|
39141
|
+
version: MCP_WORDPRESS_REMOTE_VERSION
|
|
38823
39142
|
},
|
|
38824
39143
|
{
|
|
38825
|
-
capabilities:
|
|
38826
|
-
|
|
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.
|
|
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,
|