@automattic/mcp-wordpress-remote 0.3.5 → 0.4.0
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/LICENSE +1 -1
- package/dist/lib.d.ts +45 -2
- package/dist/lib.js +54 -20
- package/dist/proxy.js +122 -43
- package/package.json +3 -2
package/LICENSE
CHANGED
package/dist/lib.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ interface WordPressResponse {
|
|
|
15
15
|
[key: string]: any;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
declare const MCP_WORDPRESS_REMOTE_VERSION = "0.
|
|
18
|
+
declare const MCP_WORDPRESS_REMOTE_VERSION = "0.4.0";
|
|
19
19
|
/**
|
|
20
20
|
* Centralized configuration for MCP WordPress Remote
|
|
21
21
|
* All default values are defined here and can be overridden via environment variables
|
|
@@ -327,4 +327,47 @@ declare function isProxyConfigured(): boolean;
|
|
|
327
327
|
*/
|
|
328
328
|
declare function getProxyType(): 'pac' | 'env' | 'none';
|
|
329
329
|
|
|
330
|
-
|
|
330
|
+
/**
|
|
331
|
+
* MCP Request Types for WordPress Remote Proxy
|
|
332
|
+
*
|
|
333
|
+
* Type definitions for all MCP JSON-RPC request schemas
|
|
334
|
+
*/
|
|
335
|
+
|
|
336
|
+
interface WPRequestParams {
|
|
337
|
+
method: string;
|
|
338
|
+
[key: string]: unknown;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Tool-call hooks for MCP WordPress Remote.
|
|
343
|
+
*
|
|
344
|
+
* Lets an embedding package observe completed `tools/call` requests and
|
|
345
|
+
* piggyback on the proxy's live, authenticated session — for example to send
|
|
346
|
+
* usage telemetry — without forking the proxy.
|
|
347
|
+
*
|
|
348
|
+
* The registry lives on a global symbol so it is a single instance even when a
|
|
349
|
+
* consumer registers through the `/lib` bundle while the handlers run in the
|
|
350
|
+
* separate `proxy` bundle.
|
|
351
|
+
*/
|
|
352
|
+
|
|
353
|
+
/** Context passed to each hook after a tool call completes. */
|
|
354
|
+
interface ToolCallContext {
|
|
355
|
+
/** Name of the tool the client just called. */
|
|
356
|
+
name: string;
|
|
357
|
+
/**
|
|
358
|
+
* Dispatch an additional request over the proxy's live, authenticated
|
|
359
|
+
* session. The request is prepared for the session's detected transport
|
|
360
|
+
* (JSON-RPC envelope or simple format) before it is sent, e.g.
|
|
361
|
+
* `wpRequest({ method: 'tools/call', name, arguments })`.
|
|
362
|
+
*/
|
|
363
|
+
wpRequest: (params: WPRequestParams) => Promise<WordPressResponse>;
|
|
364
|
+
}
|
|
365
|
+
/** A hook fired after each completed `tools/call`. May be async. */
|
|
366
|
+
type ToolCallHook = (context: ToolCallContext) => void | Promise<void>;
|
|
367
|
+
/**
|
|
368
|
+
* Register a hook fired after each completed `tools/call`. Returns a function
|
|
369
|
+
* that unregisters it.
|
|
370
|
+
*/
|
|
371
|
+
declare function registerToolCallHook(hook: ToolCallHook): () => void;
|
|
372
|
+
|
|
373
|
+
export { APIError, AuthError, CONFIG, ConfigError, LogLevel, MCP_WORDPRESS_REMOTE_VERSION, OAuthError, type TokenValidationResult, type ToolCallContext, type ToolCallHook, type WPClientInfo, type WPTokens, type WordPressRequestParams, type WordPressResponse, getAgentForUrl, getConfig, getCustomHeaders, getDefaultOAuthScopes, getFetchInfo, getProxyInfo, getProxyType, initializeProxy, isAPIError, isAuthError, isConfigError, isFetchAvailable, isOAuthError, isProxyConfigured, log, logger, parseCustomHeaders, proxyFetch, registerToolCallHook, setupFetchPolyfill, validateConfig, wpRequest };
|
package/dist/lib.js
CHANGED
|
@@ -20760,12 +20760,15 @@ var require_json = __commonJS({
|
|
|
20760
20760
|
var JSON_SYNTAX_REGEXP = /#+/g;
|
|
20761
20761
|
function json2(options) {
|
|
20762
20762
|
var opts = options || {};
|
|
20763
|
-
var limit = typeof opts.limit
|
|
20763
|
+
var limit = typeof opts.limit === "undefined" || opts.limit === null ? 102400 : bytes.parse(opts.limit);
|
|
20764
20764
|
var inflate = opts.inflate !== false;
|
|
20765
20765
|
var reviver = opts.reviver;
|
|
20766
20766
|
var strict = opts.strict !== false;
|
|
20767
20767
|
var type = opts.type || "application/json";
|
|
20768
20768
|
var verify = opts.verify || false;
|
|
20769
|
+
if (limit === null) {
|
|
20770
|
+
throw new TypeError('option limit "' + String(opts.limit) + '" is invalid');
|
|
20771
|
+
}
|
|
20769
20772
|
if (verify !== false && typeof verify !== "function") {
|
|
20770
20773
|
throw new TypeError("option verify must be function");
|
|
20771
20774
|
}
|
|
@@ -20887,9 +20890,12 @@ var require_raw = __commonJS({
|
|
|
20887
20890
|
function raw(options) {
|
|
20888
20891
|
var opts = options || {};
|
|
20889
20892
|
var inflate = opts.inflate !== false;
|
|
20890
|
-
var limit = typeof opts.limit
|
|
20893
|
+
var limit = typeof opts.limit === "undefined" || opts.limit === null ? 102400 : bytes.parse(opts.limit);
|
|
20891
20894
|
var type = opts.type || "application/octet-stream";
|
|
20892
20895
|
var verify = opts.verify || false;
|
|
20896
|
+
if (limit === null) {
|
|
20897
|
+
throw new TypeError('option limit "' + String(opts.limit) + '" is invalid');
|
|
20898
|
+
}
|
|
20893
20899
|
if (verify !== false && typeof verify !== "function") {
|
|
20894
20900
|
throw new TypeError("option verify must be function");
|
|
20895
20901
|
}
|
|
@@ -20945,9 +20951,12 @@ var require_text = __commonJS({
|
|
|
20945
20951
|
var opts = options || {};
|
|
20946
20952
|
var defaultCharset = opts.defaultCharset || "utf-8";
|
|
20947
20953
|
var inflate = opts.inflate !== false;
|
|
20948
|
-
var limit = typeof opts.limit
|
|
20954
|
+
var limit = typeof opts.limit === "undefined" || opts.limit === null ? 102400 : bytes.parse(opts.limit);
|
|
20949
20955
|
var type = opts.type || "text/plain";
|
|
20950
20956
|
var verify = opts.verify || false;
|
|
20957
|
+
if (limit === null) {
|
|
20958
|
+
throw new TypeError('option limit "' + String(opts.limit) + '" is invalid');
|
|
20959
|
+
}
|
|
20951
20960
|
if (verify !== false && typeof verify !== "function") {
|
|
20952
20961
|
throw new TypeError("option verify must be function");
|
|
20953
20962
|
}
|
|
@@ -23556,9 +23565,12 @@ var require_urlencoded = __commonJS({
|
|
|
23556
23565
|
}
|
|
23557
23566
|
var extended = opts.extended !== false;
|
|
23558
23567
|
var inflate = opts.inflate !== false;
|
|
23559
|
-
var limit = typeof opts.limit
|
|
23568
|
+
var limit = typeof opts.limit === "undefined" || opts.limit === null ? 102400 : bytes.parse(opts.limit);
|
|
23560
23569
|
var type = opts.type || "application/x-www-form-urlencoded";
|
|
23561
23570
|
var verify = opts.verify || false;
|
|
23571
|
+
if (limit === null) {
|
|
23572
|
+
throw new TypeError('option limit "' + String(opts.limit) + '" is invalid');
|
|
23573
|
+
}
|
|
23562
23574
|
if (verify !== false && typeof verify !== "function") {
|
|
23563
23575
|
throw new TypeError("option verify must be function");
|
|
23564
23576
|
}
|
|
@@ -47325,7 +47337,7 @@ async function selectCallbackPort(serverUrl, specifiedPort, _unused) {
|
|
|
47325
47337
|
}
|
|
47326
47338
|
|
|
47327
47339
|
// src/lib/config.ts
|
|
47328
|
-
var MCP_WORDPRESS_REMOTE_VERSION = "0.
|
|
47340
|
+
var MCP_WORDPRESS_REMOTE_VERSION = "0.4.0";
|
|
47329
47341
|
function parsePositiveIntEnv(value, defaultValue) {
|
|
47330
47342
|
if (!value) {
|
|
47331
47343
|
return defaultValue;
|
|
@@ -47760,13 +47772,19 @@ async function getAgentForUrl(url2) {
|
|
|
47760
47772
|
const socksMatch = directive.match(/SOCKS5?\s+(\S+):(\d+)/i);
|
|
47761
47773
|
if (socksMatch) {
|
|
47762
47774
|
const proxyUrl = `socks5h://${socksMatch[1]}:${socksMatch[2]}`;
|
|
47763
|
-
logger.debug(
|
|
47775
|
+
logger.debug(
|
|
47776
|
+
`PAC returned SOCKS proxy for ${url2}: ${sanitizeProxyUrl(proxyUrl)}`,
|
|
47777
|
+
"PROXY"
|
|
47778
|
+
);
|
|
47764
47779
|
return new SocksProxyAgent(proxyUrl);
|
|
47765
47780
|
}
|
|
47766
47781
|
const proxyMatch = directive.match(/PROXY\s+(\S+):(\d+)/i);
|
|
47767
47782
|
if (proxyMatch) {
|
|
47768
47783
|
const proxyUrl = `http://${proxyMatch[1]}:${proxyMatch[2]}`;
|
|
47769
|
-
logger.debug(
|
|
47784
|
+
logger.debug(
|
|
47785
|
+
`PAC returned HTTP proxy for ${url2}: ${sanitizeProxyUrl(proxyUrl)}`,
|
|
47786
|
+
"PROXY"
|
|
47787
|
+
);
|
|
47770
47788
|
return new HttpsProxyAgent(proxyUrl);
|
|
47771
47789
|
}
|
|
47772
47790
|
}
|
|
@@ -48443,7 +48461,7 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl) {
|
|
|
48443
48461
|
const customHeaders = getCustomHeaders();
|
|
48444
48462
|
const response = await proxyFetch(metadataUrl.toString(), {
|
|
48445
48463
|
headers: {
|
|
48446
|
-
|
|
48464
|
+
Accept: "application/json",
|
|
48447
48465
|
...customHeaders
|
|
48448
48466
|
}
|
|
48449
48467
|
});
|
|
@@ -48480,7 +48498,7 @@ async function discoverProtectedResourceMetadata(resourceUrl) {
|
|
|
48480
48498
|
const customHeaders = getCustomHeaders();
|
|
48481
48499
|
const response = await proxyFetch(metadataUrl.toString(), {
|
|
48482
48500
|
headers: {
|
|
48483
|
-
|
|
48501
|
+
Accept: "application/json",
|
|
48484
48502
|
...customHeaders
|
|
48485
48503
|
}
|
|
48486
48504
|
});
|
|
@@ -49075,7 +49093,7 @@ var MCPOAuthProvider = class {
|
|
|
49075
49093
|
if (authInfo.resource_metadata_url) {
|
|
49076
49094
|
const metadataResponse = await proxyFetch(authInfo.resource_metadata_url, {
|
|
49077
49095
|
headers: {
|
|
49078
|
-
|
|
49096
|
+
Accept: "application/json",
|
|
49079
49097
|
...customHeaders
|
|
49080
49098
|
}
|
|
49081
49099
|
});
|
|
@@ -50041,10 +50059,7 @@ async function getOAuthTokens() {
|
|
|
50041
50059
|
return null;
|
|
50042
50060
|
}
|
|
50043
50061
|
} else {
|
|
50044
|
-
logger.warn(
|
|
50045
|
-
"Using legacy OAuth provider. Consider enabling PKCE for MCP compliance",
|
|
50046
|
-
"AUTH"
|
|
50047
|
-
);
|
|
50062
|
+
logger.warn("Using legacy OAuth provider. Consider enabling PKCE for MCP compliance", "AUTH");
|
|
50048
50063
|
if (!authCoordinator) {
|
|
50049
50064
|
if (!globalEvents) {
|
|
50050
50065
|
globalEvents = new EventEmitter3();
|
|
@@ -50287,7 +50302,10 @@ async function executeWordPressRequest(requestData, useJsonRpc, sessionIdUsed) {
|
|
|
50287
50302
|
}
|
|
50288
50303
|
async function refreshSession(failedSessionId) {
|
|
50289
50304
|
if (failedSessionId && globalSessionId && globalSessionId !== failedSessionId) {
|
|
50290
|
-
logger.info(
|
|
50305
|
+
logger.info(
|
|
50306
|
+
"Detected newer session while handling invalid-session error; skipping refresh",
|
|
50307
|
+
"SESSION"
|
|
50308
|
+
);
|
|
50291
50309
|
return;
|
|
50292
50310
|
}
|
|
50293
50311
|
if (sessionRefreshPromise) {
|
|
@@ -50341,11 +50359,7 @@ async function wpRequest(requestData, useJsonRpc = true, options = {}) {
|
|
|
50341
50359
|
sessionIdUsed: sessionIdUsed || "none"
|
|
50342
50360
|
});
|
|
50343
50361
|
await refreshSession(sessionIdUsed);
|
|
50344
|
-
const retriedResult = await executeWordPressRequest(
|
|
50345
|
-
requestData,
|
|
50346
|
-
useJsonRpc,
|
|
50347
|
-
globalSessionId
|
|
50348
|
-
);
|
|
50362
|
+
const retriedResult = await executeWordPressRequest(requestData, useJsonRpc, globalSessionId);
|
|
50349
50363
|
return retriedResult.responseData;
|
|
50350
50364
|
}
|
|
50351
50365
|
if (error51 instanceof APIError) {
|
|
@@ -50357,6 +50371,25 @@ async function wpRequest(requestData, useJsonRpc = true, options = {}) {
|
|
|
50357
50371
|
throw new APIError(errorMessage, 0, getRequestUrl(), void 0, code);
|
|
50358
50372
|
}
|
|
50359
50373
|
}
|
|
50374
|
+
|
|
50375
|
+
// src/lib/tool-call-hooks.ts
|
|
50376
|
+
var REGISTRY_KEY = Symbol.for("@automattic/mcp-wordpress-remote:tool-call-hooks");
|
|
50377
|
+
function getRegistry() {
|
|
50378
|
+
const globalObject = globalThis;
|
|
50379
|
+
let registry2 = globalObject[REGISTRY_KEY];
|
|
50380
|
+
if (!registry2) {
|
|
50381
|
+
registry2 = /* @__PURE__ */ new Set();
|
|
50382
|
+
globalObject[REGISTRY_KEY] = registry2;
|
|
50383
|
+
}
|
|
50384
|
+
return registry2;
|
|
50385
|
+
}
|
|
50386
|
+
function registerToolCallHook(hook) {
|
|
50387
|
+
const registry2 = getRegistry();
|
|
50388
|
+
registry2.add(hook);
|
|
50389
|
+
return () => {
|
|
50390
|
+
registry2.delete(hook);
|
|
50391
|
+
};
|
|
50392
|
+
}
|
|
50360
50393
|
export {
|
|
50361
50394
|
APIError,
|
|
50362
50395
|
AuthError,
|
|
@@ -50383,6 +50416,7 @@ export {
|
|
|
50383
50416
|
logger,
|
|
50384
50417
|
parseCustomHeaders,
|
|
50385
50418
|
proxyFetch,
|
|
50419
|
+
registerToolCallHook,
|
|
50386
50420
|
setupFetchPolyfill,
|
|
50387
50421
|
validateConfig,
|
|
50388
50422
|
wpRequest
|
package/dist/proxy.js
CHANGED
|
@@ -3775,6 +3775,7 @@ var require_fast_uri = __commonJS({
|
|
|
3775
3775
|
return uriTokens.join("");
|
|
3776
3776
|
}
|
|
3777
3777
|
var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
|
|
3778
|
+
var AUTHORITY_PREFIX = /^(?:[^#/:?]+:)?\/\/([^/?#]*)/;
|
|
3778
3779
|
function getParseError(parsed, matches) {
|
|
3779
3780
|
if (matches[2] !== void 0 && parsed.path && parsed.path[0] !== "/") {
|
|
3780
3781
|
return 'URI path must start with "/" when authority is present.';
|
|
@@ -3804,6 +3805,11 @@ var require_fast_uri = __commonJS({
|
|
|
3804
3805
|
uri = "//" + uri;
|
|
3805
3806
|
}
|
|
3806
3807
|
}
|
|
3808
|
+
const authorityMatch = uri.match(AUTHORITY_PREFIX);
|
|
3809
|
+
if (authorityMatch !== null && authorityMatch[1].indexOf("\\") !== -1) {
|
|
3810
|
+
parsed.error = "URI authority must not contain a literal backslash.";
|
|
3811
|
+
malformedAuthorityOrPort = true;
|
|
3812
|
+
}
|
|
3807
3813
|
const matches = uri.match(URI_PARSE);
|
|
3808
3814
|
if (matches) {
|
|
3809
3815
|
parsed.scheme = matches[1];
|
|
@@ -3847,7 +3853,7 @@ var require_fast_uri = __commonJS({
|
|
|
3847
3853
|
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
|
|
3848
3854
|
if (parsed.host && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP2 === false && nonSimpleDomain(parsed.host)) {
|
|
3849
3855
|
try {
|
|
3850
|
-
parsed.host = URL
|
|
3856
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
3851
3857
|
} catch (e2) {
|
|
3852
3858
|
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e2;
|
|
3853
3859
|
}
|
|
@@ -27617,12 +27623,15 @@ var require_json = __commonJS({
|
|
|
27617
27623
|
var JSON_SYNTAX_REGEXP = /#+/g;
|
|
27618
27624
|
function json2(options) {
|
|
27619
27625
|
var opts = options || {};
|
|
27620
|
-
var limit = typeof opts.limit
|
|
27626
|
+
var limit = typeof opts.limit === "undefined" || opts.limit === null ? 102400 : bytes.parse(opts.limit);
|
|
27621
27627
|
var inflate = opts.inflate !== false;
|
|
27622
27628
|
var reviver = opts.reviver;
|
|
27623
27629
|
var strict = opts.strict !== false;
|
|
27624
27630
|
var type = opts.type || "application/json";
|
|
27625
27631
|
var verify = opts.verify || false;
|
|
27632
|
+
if (limit === null) {
|
|
27633
|
+
throw new TypeError('option limit "' + String(opts.limit) + '" is invalid');
|
|
27634
|
+
}
|
|
27626
27635
|
if (verify !== false && typeof verify !== "function") {
|
|
27627
27636
|
throw new TypeError("option verify must be function");
|
|
27628
27637
|
}
|
|
@@ -27744,9 +27753,12 @@ var require_raw = __commonJS({
|
|
|
27744
27753
|
function raw(options) {
|
|
27745
27754
|
var opts = options || {};
|
|
27746
27755
|
var inflate = opts.inflate !== false;
|
|
27747
|
-
var limit = typeof opts.limit
|
|
27756
|
+
var limit = typeof opts.limit === "undefined" || opts.limit === null ? 102400 : bytes.parse(opts.limit);
|
|
27748
27757
|
var type = opts.type || "application/octet-stream";
|
|
27749
27758
|
var verify = opts.verify || false;
|
|
27759
|
+
if (limit === null) {
|
|
27760
|
+
throw new TypeError('option limit "' + String(opts.limit) + '" is invalid');
|
|
27761
|
+
}
|
|
27750
27762
|
if (verify !== false && typeof verify !== "function") {
|
|
27751
27763
|
throw new TypeError("option verify must be function");
|
|
27752
27764
|
}
|
|
@@ -27802,9 +27814,12 @@ var require_text = __commonJS({
|
|
|
27802
27814
|
var opts = options || {};
|
|
27803
27815
|
var defaultCharset = opts.defaultCharset || "utf-8";
|
|
27804
27816
|
var inflate = opts.inflate !== false;
|
|
27805
|
-
var limit = typeof opts.limit
|
|
27817
|
+
var limit = typeof opts.limit === "undefined" || opts.limit === null ? 102400 : bytes.parse(opts.limit);
|
|
27806
27818
|
var type = opts.type || "text/plain";
|
|
27807
27819
|
var verify = opts.verify || false;
|
|
27820
|
+
if (limit === null) {
|
|
27821
|
+
throw new TypeError('option limit "' + String(opts.limit) + '" is invalid');
|
|
27822
|
+
}
|
|
27808
27823
|
if (verify !== false && typeof verify !== "function") {
|
|
27809
27824
|
throw new TypeError("option verify must be function");
|
|
27810
27825
|
}
|
|
@@ -30413,9 +30428,12 @@ var require_urlencoded = __commonJS({
|
|
|
30413
30428
|
}
|
|
30414
30429
|
var extended = opts.extended !== false;
|
|
30415
30430
|
var inflate = opts.inflate !== false;
|
|
30416
|
-
var limit = typeof opts.limit
|
|
30431
|
+
var limit = typeof opts.limit === "undefined" || opts.limit === null ? 102400 : bytes.parse(opts.limit);
|
|
30417
30432
|
var type = opts.type || "application/x-www-form-urlencoded";
|
|
30418
30433
|
var verify = opts.verify || false;
|
|
30434
|
+
if (limit === null) {
|
|
30435
|
+
throw new TypeError('option limit "' + String(opts.limit) + '" is invalid');
|
|
30436
|
+
}
|
|
30419
30437
|
if (verify !== false && typeof verify !== "function") {
|
|
30420
30438
|
throw new TypeError("option verify must be function");
|
|
30421
30439
|
}
|
|
@@ -55942,7 +55960,7 @@ async function selectCallbackPort(serverUrl, specifiedPort, _unused) {
|
|
|
55942
55960
|
}
|
|
55943
55961
|
|
|
55944
55962
|
// src/lib/config.ts
|
|
55945
|
-
var MCP_WORDPRESS_REMOTE_VERSION = "0.
|
|
55963
|
+
var MCP_WORDPRESS_REMOTE_VERSION = "0.4.0";
|
|
55946
55964
|
function parsePositiveIntEnv(value, defaultValue) {
|
|
55947
55965
|
if (!value) {
|
|
55948
55966
|
return defaultValue;
|
|
@@ -56387,13 +56405,19 @@ async function getAgentForUrl(url2) {
|
|
|
56387
56405
|
const socksMatch = directive.match(/SOCKS5?\s+(\S+):(\d+)/i);
|
|
56388
56406
|
if (socksMatch) {
|
|
56389
56407
|
const proxyUrl = `socks5h://${socksMatch[1]}:${socksMatch[2]}`;
|
|
56390
|
-
logger.debug(
|
|
56408
|
+
logger.debug(
|
|
56409
|
+
`PAC returned SOCKS proxy for ${url2}: ${sanitizeProxyUrl(proxyUrl)}`,
|
|
56410
|
+
"PROXY"
|
|
56411
|
+
);
|
|
56391
56412
|
return new SocksProxyAgent(proxyUrl);
|
|
56392
56413
|
}
|
|
56393
56414
|
const proxyMatch = directive.match(/PROXY\s+(\S+):(\d+)/i);
|
|
56394
56415
|
if (proxyMatch) {
|
|
56395
56416
|
const proxyUrl = `http://${proxyMatch[1]}:${proxyMatch[2]}`;
|
|
56396
|
-
logger.debug(
|
|
56417
|
+
logger.debug(
|
|
56418
|
+
`PAC returned HTTP proxy for ${url2}: ${sanitizeProxyUrl(proxyUrl)}`,
|
|
56419
|
+
"PROXY"
|
|
56420
|
+
);
|
|
56397
56421
|
return new HttpsProxyAgent(proxyUrl);
|
|
56398
56422
|
}
|
|
56399
56423
|
}
|
|
@@ -56574,7 +56598,7 @@ function mapHttpStatusToMcpCode(statusCode) {
|
|
|
56574
56598
|
RESOURCE_NOT_FOUND: -32002,
|
|
56575
56599
|
// Resource not found
|
|
56576
56600
|
TOOL_NOT_FOUND: -32003,
|
|
56577
|
-
// Tool not found
|
|
56601
|
+
// Tool not found
|
|
56578
56602
|
PROMPT_NOT_FOUND: -32004,
|
|
56579
56603
|
// Prompt not found
|
|
56580
56604
|
PERMISSION_DENIED: -32008,
|
|
@@ -56642,7 +56666,11 @@ function mcpErrorParts(error51) {
|
|
|
56642
56666
|
if (wpError) {
|
|
56643
56667
|
return { code: wpError.code, message: wpError.message ?? error51.message, data: wpError.data };
|
|
56644
56668
|
}
|
|
56645
|
-
return {
|
|
56669
|
+
return {
|
|
56670
|
+
code: deriveMcpErrorCode(error51),
|
|
56671
|
+
message: error51.message,
|
|
56672
|
+
data: buildApiErrorData(error51)
|
|
56673
|
+
};
|
|
56646
56674
|
}
|
|
56647
56675
|
function convertAPIErrorToMcpError(error51) {
|
|
56648
56676
|
return { error: mcpErrorParts(error51) };
|
|
@@ -57130,7 +57158,7 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl) {
|
|
|
57130
57158
|
const customHeaders = getCustomHeaders();
|
|
57131
57159
|
const response = await proxyFetch(metadataUrl.toString(), {
|
|
57132
57160
|
headers: {
|
|
57133
|
-
|
|
57161
|
+
Accept: "application/json",
|
|
57134
57162
|
...customHeaders
|
|
57135
57163
|
}
|
|
57136
57164
|
});
|
|
@@ -57167,7 +57195,7 @@ async function discoverProtectedResourceMetadata(resourceUrl) {
|
|
|
57167
57195
|
const customHeaders = getCustomHeaders();
|
|
57168
57196
|
const response = await proxyFetch(metadataUrl.toString(), {
|
|
57169
57197
|
headers: {
|
|
57170
|
-
|
|
57198
|
+
Accept: "application/json",
|
|
57171
57199
|
...customHeaders
|
|
57172
57200
|
}
|
|
57173
57201
|
});
|
|
@@ -57762,7 +57790,7 @@ var MCPOAuthProvider = class {
|
|
|
57762
57790
|
if (authInfo.resource_metadata_url) {
|
|
57763
57791
|
const metadataResponse = await proxyFetch(authInfo.resource_metadata_url, {
|
|
57764
57792
|
headers: {
|
|
57765
|
-
|
|
57793
|
+
Accept: "application/json",
|
|
57766
57794
|
...customHeaders
|
|
57767
57795
|
}
|
|
57768
57796
|
});
|
|
@@ -58728,10 +58756,7 @@ async function getOAuthTokens() {
|
|
|
58728
58756
|
return null;
|
|
58729
58757
|
}
|
|
58730
58758
|
} else {
|
|
58731
|
-
logger.warn(
|
|
58732
|
-
"Using legacy OAuth provider. Consider enabling PKCE for MCP compliance",
|
|
58733
|
-
"AUTH"
|
|
58734
|
-
);
|
|
58759
|
+
logger.warn("Using legacy OAuth provider. Consider enabling PKCE for MCP compliance", "AUTH");
|
|
58735
58760
|
if (!authCoordinator) {
|
|
58736
58761
|
if (!globalEvents) {
|
|
58737
58762
|
globalEvents = new EventEmitter3();
|
|
@@ -58977,7 +59002,10 @@ async function executeWordPressRequest(requestData, useJsonRpc, sessionIdUsed) {
|
|
|
58977
59002
|
}
|
|
58978
59003
|
async function refreshSession(failedSessionId) {
|
|
58979
59004
|
if (failedSessionId && globalSessionId && globalSessionId !== failedSessionId) {
|
|
58980
|
-
logger.info(
|
|
59005
|
+
logger.info(
|
|
59006
|
+
"Detected newer session while handling invalid-session error; skipping refresh",
|
|
59007
|
+
"SESSION"
|
|
59008
|
+
);
|
|
58981
59009
|
return;
|
|
58982
59010
|
}
|
|
58983
59011
|
if (sessionRefreshPromise) {
|
|
@@ -59031,11 +59059,7 @@ async function wpRequest(requestData, useJsonRpc = true, options = {}) {
|
|
|
59031
59059
|
sessionIdUsed: sessionIdUsed || "none"
|
|
59032
59060
|
});
|
|
59033
59061
|
await refreshSession(sessionIdUsed);
|
|
59034
|
-
const retriedResult = await executeWordPressRequest(
|
|
59035
|
-
requestData,
|
|
59036
|
-
useJsonRpc,
|
|
59037
|
-
globalSessionId
|
|
59038
|
-
);
|
|
59062
|
+
const retriedResult = await executeWordPressRequest(requestData, useJsonRpc, globalSessionId);
|
|
59039
59063
|
return retriedResult.responseData;
|
|
59040
59064
|
}
|
|
59041
59065
|
if (error51 instanceof APIError) {
|
|
@@ -59123,7 +59147,10 @@ async function waitForInit(context, timeoutMs = INIT_TIMEOUT_MS) {
|
|
|
59123
59147
|
|
|
59124
59148
|
// src/lib/transport-detection.ts
|
|
59125
59149
|
async function detectTransportType(context, initParams) {
|
|
59126
|
-
logger.info(
|
|
59150
|
+
logger.info(
|
|
59151
|
+
"\u{1F50D} Starting transport detection and WordPress API initialization...",
|
|
59152
|
+
"TRANSPORT_DETECT"
|
|
59153
|
+
);
|
|
59127
59154
|
let init;
|
|
59128
59155
|
let transportType = null;
|
|
59129
59156
|
const enhancedParams = initParams ? { ...initParams } : {};
|
|
@@ -59150,11 +59177,15 @@ async function detectTransportType(context, initParams) {
|
|
|
59150
59177
|
proxyVersion: MCP_WORDPRESS_REMOTE_VERSION
|
|
59151
59178
|
});
|
|
59152
59179
|
} else {
|
|
59153
|
-
logger.warn(
|
|
59154
|
-
|
|
59155
|
-
|
|
59156
|
-
|
|
59157
|
-
|
|
59180
|
+
logger.warn(
|
|
59181
|
+
"clientInfo is present but not a valid object, skipping enhancement",
|
|
59182
|
+
"TRANSPORT_DETECT",
|
|
59183
|
+
{
|
|
59184
|
+
clientInfoType: typeof enhancedParams.clientInfo,
|
|
59185
|
+
isArray: Array.isArray(enhancedParams.clientInfo),
|
|
59186
|
+
isNull: enhancedParams.clientInfo === null
|
|
59187
|
+
}
|
|
59188
|
+
);
|
|
59158
59189
|
}
|
|
59159
59190
|
} else {
|
|
59160
59191
|
logger.debug("No clientInfo provided in initialize parameters", "TRANSPORT_DETECT");
|
|
@@ -59208,8 +59239,14 @@ async function detectTransportType(context, initParams) {
|
|
|
59208
59239
|
logger.info("\u2705 Simple transport detected and working", "TRANSPORT_DETECT");
|
|
59209
59240
|
logger.debug("Simple initialization response:", "TRANSPORT_DETECT", init);
|
|
59210
59241
|
} catch (simpleError) {
|
|
59211
|
-
logger.error(
|
|
59212
|
-
|
|
59242
|
+
logger.error(
|
|
59243
|
+
"\u274C Both JSON-RPC and simple transports failed",
|
|
59244
|
+
"TRANSPORT_DETECT",
|
|
59245
|
+
simpleError
|
|
59246
|
+
);
|
|
59247
|
+
const connectionError = new Error(
|
|
59248
|
+
"Unable to establish connection with either transport type"
|
|
59249
|
+
);
|
|
59213
59250
|
connectionError.cause = simpleError;
|
|
59214
59251
|
throw connectionError;
|
|
59215
59252
|
}
|
|
@@ -59222,7 +59259,10 @@ async function detectTransportType(context, initParams) {
|
|
|
59222
59259
|
} else {
|
|
59223
59260
|
logger.warn("No session ID received from WordPress - continuing without session", "PROXY");
|
|
59224
59261
|
}
|
|
59225
|
-
logger.info(
|
|
59262
|
+
logger.info(
|
|
59263
|
+
`WordPress connection initialized successfully using ${transportType} transport`,
|
|
59264
|
+
"PROXY"
|
|
59265
|
+
);
|
|
59226
59266
|
return {
|
|
59227
59267
|
transportType,
|
|
59228
59268
|
initResult: init,
|
|
@@ -59230,6 +59270,31 @@ async function detectTransportType(context, initParams) {
|
|
|
59230
59270
|
};
|
|
59231
59271
|
}
|
|
59232
59272
|
|
|
59273
|
+
// src/lib/tool-call-hooks.ts
|
|
59274
|
+
var REGISTRY_KEY = Symbol.for("@automattic/mcp-wordpress-remote:tool-call-hooks");
|
|
59275
|
+
function getRegistry() {
|
|
59276
|
+
const globalObject = globalThis;
|
|
59277
|
+
let registry2 = globalObject[REGISTRY_KEY];
|
|
59278
|
+
if (!registry2) {
|
|
59279
|
+
registry2 = /* @__PURE__ */ new Set();
|
|
59280
|
+
globalObject[REGISTRY_KEY] = registry2;
|
|
59281
|
+
}
|
|
59282
|
+
return registry2;
|
|
59283
|
+
}
|
|
59284
|
+
function runToolCallHooks(context) {
|
|
59285
|
+
const hooks = [...getRegistry()];
|
|
59286
|
+
if (hooks.length === 0) return;
|
|
59287
|
+
setImmediate(() => {
|
|
59288
|
+
for (const hook of hooks) {
|
|
59289
|
+
void Promise.resolve().then(() => hook(context)).catch((error51) => {
|
|
59290
|
+
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
59291
|
+
logger.error(`Tool-call hook failed: ${message}`, "HOOKS");
|
|
59292
|
+
}).catch(() => {
|
|
59293
|
+
});
|
|
59294
|
+
}
|
|
59295
|
+
});
|
|
59296
|
+
}
|
|
59297
|
+
|
|
59233
59298
|
// src/lib/request-handler-factory.ts
|
|
59234
59299
|
function createRequestHandler(config2, context) {
|
|
59235
59300
|
return async (request) => {
|
|
@@ -59251,6 +59316,10 @@ function createRequestHandler(config2, context) {
|
|
|
59251
59316
|
const wpParams = config2.paramMapper(request);
|
|
59252
59317
|
const requestData = prepareRequest(wpParams, request, context);
|
|
59253
59318
|
const response = await wpRequest(requestData, context.transportType === "jsonrpc");
|
|
59319
|
+
if (config2.method === "tools/call") {
|
|
59320
|
+
const hookWpRequest = (params) => wpRequest(prepareRequest(params, {}, context), context.transportType === "jsonrpc");
|
|
59321
|
+
runToolCallHooks({ name: String(wpParams.name ?? ""), wpRequest: hookWpRequest });
|
|
59322
|
+
}
|
|
59254
59323
|
return response;
|
|
59255
59324
|
};
|
|
59256
59325
|
}
|
|
@@ -59291,19 +59360,27 @@ function createWrappedHandler(config2, context) {
|
|
|
59291
59360
|
});
|
|
59292
59361
|
if (isAPIError(error51)) {
|
|
59293
59362
|
if (context.transportType === "simple") {
|
|
59294
|
-
logger.debug(
|
|
59363
|
+
logger.debug(
|
|
59364
|
+
`Converting APIError to MCP error format for ${config2.name} (simple transport)`,
|
|
59365
|
+
"MCP",
|
|
59366
|
+
{
|
|
59367
|
+
statusCode: error51.statusCode,
|
|
59368
|
+
endpoint: error51.endpoint,
|
|
59369
|
+
message: error51.message
|
|
59370
|
+
}
|
|
59371
|
+
);
|
|
59372
|
+
return convertAPIErrorToMcpError(error51);
|
|
59373
|
+
}
|
|
59374
|
+
logger.debug(
|
|
59375
|
+
`Converting APIError to McpError for ${config2.name} (jsonrpc transport)`,
|
|
59376
|
+
"MCP",
|
|
59377
|
+
{
|
|
59295
59378
|
statusCode: error51.statusCode,
|
|
59379
|
+
code: error51.code,
|
|
59296
59380
|
endpoint: error51.endpoint,
|
|
59297
59381
|
message: error51.message
|
|
59298
|
-
}
|
|
59299
|
-
|
|
59300
|
-
}
|
|
59301
|
-
logger.debug(`Converting APIError to McpError for ${config2.name} (jsonrpc transport)`, "MCP", {
|
|
59302
|
-
statusCode: error51.statusCode,
|
|
59303
|
-
code: error51.code,
|
|
59304
|
-
endpoint: error51.endpoint,
|
|
59305
|
-
message: error51.message
|
|
59306
|
-
});
|
|
59382
|
+
}
|
|
59383
|
+
);
|
|
59307
59384
|
throw apiErrorToMcpError(error51);
|
|
59308
59385
|
}
|
|
59309
59386
|
throw error51;
|
|
@@ -59473,7 +59550,9 @@ async function WordPressProxy() {
|
|
|
59473
59550
|
version: MCP_WORDPRESS_REMOTE_VERSION
|
|
59474
59551
|
},
|
|
59475
59552
|
capabilities: {
|
|
59476
|
-
experimental: {
|
|
59553
|
+
experimental: {
|
|
59554
|
+
connectionFailed: connectionError.code ? { code: connectionError.code } : {}
|
|
59555
|
+
}
|
|
59477
59556
|
},
|
|
59478
59557
|
instructions: `MCP WordPress Remote Proxy Server (Connection Failed${connectionError.code ? `: ${connectionError.code}` : ""})`
|
|
59479
59558
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/mcp-wordpress-remote",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "MCP WordPress Remote proxy server",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"proxy"
|
|
13
13
|
],
|
|
14
14
|
"author": "Automattic Inc.",
|
|
15
|
+
"license": "MIT",
|
|
15
16
|
"repository": {
|
|
16
17
|
"type": "git",
|
|
17
18
|
"url": "git+https://github.com/Automattic/mcp-wordpress-remote.git"
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
"scripts": {
|
|
40
41
|
"build": "tsup",
|
|
41
42
|
"build:watch": "tsup --watch",
|
|
42
|
-
"check": "prettier --check
|
|
43
|
+
"check": "prettier --check src && tsc --noEmit",
|
|
43
44
|
"start": "NODE_ENV=development tsup --watch",
|
|
44
45
|
"dev": "NODE_ENV=development node dist/proxy.js",
|
|
45
46
|
"test": "jest",
|