@automattic/mcp-wordpress-remote 0.5.1 → 0.5.3
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/Docs/authentication.md +45 -0
- package/README.md +5 -5
- package/dist/lib.d.ts +18 -12
- package/dist/lib.js +597 -415
- package/dist/proxy.js +854 -642
- package/package.json +7 -3
package/dist/proxy.js
CHANGED
|
@@ -4939,7 +4939,7 @@ async function toFormData(Body2, ct) {
|
|
|
4939
4939
|
let headerValue2;
|
|
4940
4940
|
let entryValue;
|
|
4941
4941
|
let entryName;
|
|
4942
|
-
let
|
|
4942
|
+
let contentType2;
|
|
4943
4943
|
let filename;
|
|
4944
4944
|
const entryChunks = [];
|
|
4945
4945
|
const formData = new FormData();
|
|
@@ -4950,7 +4950,7 @@ async function toFormData(Body2, ct) {
|
|
|
4950
4950
|
entryChunks.push(ui8a);
|
|
4951
4951
|
};
|
|
4952
4952
|
const appendFileToFormData = () => {
|
|
4953
|
-
const file2 = new file_default(entryChunks, filename, { type:
|
|
4953
|
+
const file2 = new file_default(entryChunks, filename, { type: contentType2 });
|
|
4954
4954
|
formData.append(entryName, file2);
|
|
4955
4955
|
};
|
|
4956
4956
|
const appendEntryToFormData = () => {
|
|
@@ -4965,7 +4965,7 @@ async function toFormData(Body2, ct) {
|
|
|
4965
4965
|
headerValue2 = "";
|
|
4966
4966
|
entryValue = "";
|
|
4967
4967
|
entryName = "";
|
|
4968
|
-
|
|
4968
|
+
contentType2 = "";
|
|
4969
4969
|
filename = null;
|
|
4970
4970
|
entryChunks.length = 0;
|
|
4971
4971
|
};
|
|
@@ -4989,7 +4989,7 @@ async function toFormData(Body2, ct) {
|
|
|
4989
4989
|
parser.onPartEnd = appendFileToFormData;
|
|
4990
4990
|
}
|
|
4991
4991
|
} else if (headerField === "content-type") {
|
|
4992
|
-
|
|
4992
|
+
contentType2 = headerValue2;
|
|
4993
4993
|
}
|
|
4994
4994
|
headerValue2 = "";
|
|
4995
4995
|
headerField = "";
|
|
@@ -5749,9 +5749,9 @@ var init_response = __esm({
|
|
|
5749
5749
|
const status = options.status != null ? options.status : 200;
|
|
5750
5750
|
const headers = new Headers2(options.headers);
|
|
5751
5751
|
if (body !== null && !headers.has("Content-Type")) {
|
|
5752
|
-
const
|
|
5753
|
-
if (
|
|
5754
|
-
headers.append("Content-Type",
|
|
5752
|
+
const contentType2 = extractContentType(body, this);
|
|
5753
|
+
if (contentType2) {
|
|
5754
|
+
headers.append("Content-Type", contentType2);
|
|
5755
5755
|
}
|
|
5756
5756
|
}
|
|
5757
5757
|
this[INTERNALS2] = {
|
|
@@ -6073,9 +6073,9 @@ var init_request = __esm({
|
|
|
6073
6073
|
});
|
|
6074
6074
|
const headers = new Headers2(init.headers || input.headers || {});
|
|
6075
6075
|
if (inputBody !== null && !headers.has("Content-Type")) {
|
|
6076
|
-
const
|
|
6077
|
-
if (
|
|
6078
|
-
headers.set("Content-Type",
|
|
6076
|
+
const contentType2 = extractContentType(inputBody, this);
|
|
6077
|
+
if (contentType2) {
|
|
6078
|
+
headers.set("Content-Type", contentType2);
|
|
6079
6079
|
}
|
|
6080
6080
|
}
|
|
6081
6081
|
let signal = isRequest(input) ? input.signal : null;
|
|
@@ -6547,6 +6547,110 @@ var init_src = __esm({
|
|
|
6547
6547
|
}
|
|
6548
6548
|
});
|
|
6549
6549
|
|
|
6550
|
+
// node_modules/content-type/index.js
|
|
6551
|
+
var require_content_type = __commonJS({
|
|
6552
|
+
"node_modules/content-type/index.js"(exports) {
|
|
6553
|
+
"use strict";
|
|
6554
|
+
var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g;
|
|
6555
|
+
var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/;
|
|
6556
|
+
var TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
6557
|
+
var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g;
|
|
6558
|
+
var QUOTE_REGEXP = /([\\"])/g;
|
|
6559
|
+
var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
6560
|
+
exports.format = format;
|
|
6561
|
+
exports.parse = parse3;
|
|
6562
|
+
function format(obj) {
|
|
6563
|
+
if (!obj || typeof obj !== "object") {
|
|
6564
|
+
throw new TypeError("argument obj is required");
|
|
6565
|
+
}
|
|
6566
|
+
var parameters = obj.parameters;
|
|
6567
|
+
var type = obj.type;
|
|
6568
|
+
if (!type || !TYPE_REGEXP.test(type)) {
|
|
6569
|
+
throw new TypeError("invalid type");
|
|
6570
|
+
}
|
|
6571
|
+
var string4 = type;
|
|
6572
|
+
if (parameters && typeof parameters === "object") {
|
|
6573
|
+
var param;
|
|
6574
|
+
var params = Object.keys(parameters).sort();
|
|
6575
|
+
for (var i2 = 0; i2 < params.length; i2++) {
|
|
6576
|
+
param = params[i2];
|
|
6577
|
+
if (!TOKEN_REGEXP.test(param)) {
|
|
6578
|
+
throw new TypeError("invalid parameter name");
|
|
6579
|
+
}
|
|
6580
|
+
string4 += "; " + param + "=" + qstring(parameters[param]);
|
|
6581
|
+
}
|
|
6582
|
+
}
|
|
6583
|
+
return string4;
|
|
6584
|
+
}
|
|
6585
|
+
function parse3(string4) {
|
|
6586
|
+
if (!string4) {
|
|
6587
|
+
throw new TypeError("argument string is required");
|
|
6588
|
+
}
|
|
6589
|
+
var header = typeof string4 === "object" ? getcontenttype(string4) : string4;
|
|
6590
|
+
if (typeof header !== "string") {
|
|
6591
|
+
throw new TypeError("argument string is required to be a string");
|
|
6592
|
+
}
|
|
6593
|
+
var index = header.indexOf(";");
|
|
6594
|
+
var type = index !== -1 ? header.slice(0, index).trim() : header.trim();
|
|
6595
|
+
if (!TYPE_REGEXP.test(type)) {
|
|
6596
|
+
throw new TypeError("invalid media type");
|
|
6597
|
+
}
|
|
6598
|
+
var obj = new ContentType(type.toLowerCase());
|
|
6599
|
+
if (index !== -1) {
|
|
6600
|
+
var key;
|
|
6601
|
+
var match;
|
|
6602
|
+
var value;
|
|
6603
|
+
PARAM_REGEXP.lastIndex = index;
|
|
6604
|
+
while (match = PARAM_REGEXP.exec(header)) {
|
|
6605
|
+
if (match.index !== index) {
|
|
6606
|
+
throw new TypeError("invalid parameter format");
|
|
6607
|
+
}
|
|
6608
|
+
index += match[0].length;
|
|
6609
|
+
key = match[1].toLowerCase();
|
|
6610
|
+
value = match[2];
|
|
6611
|
+
if (value.charCodeAt(0) === 34) {
|
|
6612
|
+
value = value.slice(1, -1);
|
|
6613
|
+
if (value.indexOf("\\") !== -1) {
|
|
6614
|
+
value = value.replace(QESC_REGEXP, "$1");
|
|
6615
|
+
}
|
|
6616
|
+
}
|
|
6617
|
+
obj.parameters[key] = value;
|
|
6618
|
+
}
|
|
6619
|
+
if (index !== header.length) {
|
|
6620
|
+
throw new TypeError("invalid parameter format");
|
|
6621
|
+
}
|
|
6622
|
+
}
|
|
6623
|
+
return obj;
|
|
6624
|
+
}
|
|
6625
|
+
function getcontenttype(obj) {
|
|
6626
|
+
var header;
|
|
6627
|
+
if (typeof obj.getHeader === "function") {
|
|
6628
|
+
header = obj.getHeader("content-type");
|
|
6629
|
+
} else if (typeof obj.headers === "object") {
|
|
6630
|
+
header = obj.headers && obj.headers["content-type"];
|
|
6631
|
+
}
|
|
6632
|
+
if (typeof header !== "string") {
|
|
6633
|
+
throw new TypeError("content-type header is missing from object");
|
|
6634
|
+
}
|
|
6635
|
+
return header;
|
|
6636
|
+
}
|
|
6637
|
+
function qstring(val) {
|
|
6638
|
+
var str = String(val);
|
|
6639
|
+
if (TOKEN_REGEXP.test(str)) {
|
|
6640
|
+
return str;
|
|
6641
|
+
}
|
|
6642
|
+
if (str.length > 0 && !TEXT_REGEXP.test(str)) {
|
|
6643
|
+
throw new TypeError("invalid parameter value");
|
|
6644
|
+
}
|
|
6645
|
+
return '"' + str.replace(QUOTE_REGEXP, "\\$1") + '"';
|
|
6646
|
+
}
|
|
6647
|
+
function ContentType(type) {
|
|
6648
|
+
this.parameters = /* @__PURE__ */ Object.create(null);
|
|
6649
|
+
this.type = type;
|
|
6650
|
+
}
|
|
6651
|
+
}
|
|
6652
|
+
});
|
|
6653
|
+
|
|
6550
6654
|
// node_modules/ms/index.js
|
|
6551
6655
|
var require_ms = __commonJS({
|
|
6552
6656
|
"node_modules/ms/index.js"(exports, module) {
|
|
@@ -21818,7 +21922,7 @@ var require_mime_types = __commonJS({
|
|
|
21818
21922
|
var TEXT_TYPE_REGEXP = /^text\//i;
|
|
21819
21923
|
exports.charset = charset;
|
|
21820
21924
|
exports.charsets = { lookup: charset };
|
|
21821
|
-
exports.contentType =
|
|
21925
|
+
exports.contentType = contentType2;
|
|
21822
21926
|
exports.extension = extension;
|
|
21823
21927
|
exports.extensions = /* @__PURE__ */ Object.create(null);
|
|
21824
21928
|
exports.lookup = lookup;
|
|
@@ -21839,7 +21943,7 @@ var require_mime_types = __commonJS({
|
|
|
21839
21943
|
}
|
|
21840
21944
|
return false;
|
|
21841
21945
|
}
|
|
21842
|
-
function
|
|
21946
|
+
function contentType2(str) {
|
|
21843
21947
|
if (!str || typeof str !== "string") {
|
|
21844
21948
|
return false;
|
|
21845
21949
|
}
|
|
@@ -21981,7 +22085,7 @@ var require_media_typer = __commonJS({
|
|
|
21981
22085
|
var require_type_is = __commonJS({
|
|
21982
22086
|
"node_modules/type-is/index.js"(exports, module) {
|
|
21983
22087
|
"use strict";
|
|
21984
|
-
var
|
|
22088
|
+
var contentType2 = require_dist();
|
|
21985
22089
|
var mime = require_mime_types();
|
|
21986
22090
|
var typer = require_media_typer();
|
|
21987
22091
|
module.exports = typeofrequest;
|
|
@@ -22062,7 +22166,7 @@ var require_type_is = __commonJS({
|
|
|
22062
22166
|
}
|
|
22063
22167
|
function normalizeType(value) {
|
|
22064
22168
|
if (!value) return null;
|
|
22065
|
-
var type =
|
|
22169
|
+
var type = contentType2.parse(value, { parameters: false }).type;
|
|
22066
22170
|
return typer.test(type) ? type : null;
|
|
22067
22171
|
}
|
|
22068
22172
|
}
|
|
@@ -22212,7 +22316,7 @@ var require_utils = __commonJS({
|
|
|
22212
22316
|
"node_modules/body-parser/lib/utils.js"(exports, module) {
|
|
22213
22317
|
"use strict";
|
|
22214
22318
|
var bytes = require_bytes();
|
|
22215
|
-
var
|
|
22319
|
+
var contentType2 = require_dist2();
|
|
22216
22320
|
var typeis = require_type_is();
|
|
22217
22321
|
module.exports = {
|
|
22218
22322
|
getCharset,
|
|
@@ -22222,7 +22326,7 @@ var require_utils = __commonJS({
|
|
|
22222
22326
|
function getCharset(req) {
|
|
22223
22327
|
const header = req.headers["content-type"];
|
|
22224
22328
|
if (!header) return void 0;
|
|
22225
|
-
return
|
|
22329
|
+
return contentType2.parse(header).parameters.charset?.toLowerCase();
|
|
22226
22330
|
}
|
|
22227
22331
|
function typeChecker(type) {
|
|
22228
22332
|
return function checkType(req) {
|
|
@@ -25646,110 +25750,6 @@ var require_view = __commonJS({
|
|
|
25646
25750
|
}
|
|
25647
25751
|
});
|
|
25648
25752
|
|
|
25649
|
-
// node_modules/content-type/index.js
|
|
25650
|
-
var require_content_type = __commonJS({
|
|
25651
|
-
"node_modules/content-type/index.js"(exports) {
|
|
25652
|
-
"use strict";
|
|
25653
|
-
var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g;
|
|
25654
|
-
var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/;
|
|
25655
|
-
var TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
25656
|
-
var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g;
|
|
25657
|
-
var QUOTE_REGEXP = /([\\"])/g;
|
|
25658
|
-
var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
25659
|
-
exports.format = format;
|
|
25660
|
-
exports.parse = parse3;
|
|
25661
|
-
function format(obj) {
|
|
25662
|
-
if (!obj || typeof obj !== "object") {
|
|
25663
|
-
throw new TypeError("argument obj is required");
|
|
25664
|
-
}
|
|
25665
|
-
var parameters = obj.parameters;
|
|
25666
|
-
var type = obj.type;
|
|
25667
|
-
if (!type || !TYPE_REGEXP.test(type)) {
|
|
25668
|
-
throw new TypeError("invalid type");
|
|
25669
|
-
}
|
|
25670
|
-
var string4 = type;
|
|
25671
|
-
if (parameters && typeof parameters === "object") {
|
|
25672
|
-
var param;
|
|
25673
|
-
var params = Object.keys(parameters).sort();
|
|
25674
|
-
for (var i2 = 0; i2 < params.length; i2++) {
|
|
25675
|
-
param = params[i2];
|
|
25676
|
-
if (!TOKEN_REGEXP.test(param)) {
|
|
25677
|
-
throw new TypeError("invalid parameter name");
|
|
25678
|
-
}
|
|
25679
|
-
string4 += "; " + param + "=" + qstring(parameters[param]);
|
|
25680
|
-
}
|
|
25681
|
-
}
|
|
25682
|
-
return string4;
|
|
25683
|
-
}
|
|
25684
|
-
function parse3(string4) {
|
|
25685
|
-
if (!string4) {
|
|
25686
|
-
throw new TypeError("argument string is required");
|
|
25687
|
-
}
|
|
25688
|
-
var header = typeof string4 === "object" ? getcontenttype(string4) : string4;
|
|
25689
|
-
if (typeof header !== "string") {
|
|
25690
|
-
throw new TypeError("argument string is required to be a string");
|
|
25691
|
-
}
|
|
25692
|
-
var index = header.indexOf(";");
|
|
25693
|
-
var type = index !== -1 ? header.slice(0, index).trim() : header.trim();
|
|
25694
|
-
if (!TYPE_REGEXP.test(type)) {
|
|
25695
|
-
throw new TypeError("invalid media type");
|
|
25696
|
-
}
|
|
25697
|
-
var obj = new ContentType(type.toLowerCase());
|
|
25698
|
-
if (index !== -1) {
|
|
25699
|
-
var key;
|
|
25700
|
-
var match;
|
|
25701
|
-
var value;
|
|
25702
|
-
PARAM_REGEXP.lastIndex = index;
|
|
25703
|
-
while (match = PARAM_REGEXP.exec(header)) {
|
|
25704
|
-
if (match.index !== index) {
|
|
25705
|
-
throw new TypeError("invalid parameter format");
|
|
25706
|
-
}
|
|
25707
|
-
index += match[0].length;
|
|
25708
|
-
key = match[1].toLowerCase();
|
|
25709
|
-
value = match[2];
|
|
25710
|
-
if (value.charCodeAt(0) === 34) {
|
|
25711
|
-
value = value.slice(1, -1);
|
|
25712
|
-
if (value.indexOf("\\") !== -1) {
|
|
25713
|
-
value = value.replace(QESC_REGEXP, "$1");
|
|
25714
|
-
}
|
|
25715
|
-
}
|
|
25716
|
-
obj.parameters[key] = value;
|
|
25717
|
-
}
|
|
25718
|
-
if (index !== header.length) {
|
|
25719
|
-
throw new TypeError("invalid parameter format");
|
|
25720
|
-
}
|
|
25721
|
-
}
|
|
25722
|
-
return obj;
|
|
25723
|
-
}
|
|
25724
|
-
function getcontenttype(obj) {
|
|
25725
|
-
var header;
|
|
25726
|
-
if (typeof obj.getHeader === "function") {
|
|
25727
|
-
header = obj.getHeader("content-type");
|
|
25728
|
-
} else if (typeof obj.headers === "object") {
|
|
25729
|
-
header = obj.headers && obj.headers["content-type"];
|
|
25730
|
-
}
|
|
25731
|
-
if (typeof header !== "string") {
|
|
25732
|
-
throw new TypeError("content-type header is missing from object");
|
|
25733
|
-
}
|
|
25734
|
-
return header;
|
|
25735
|
-
}
|
|
25736
|
-
function qstring(val) {
|
|
25737
|
-
var str = String(val);
|
|
25738
|
-
if (TOKEN_REGEXP.test(str)) {
|
|
25739
|
-
return str;
|
|
25740
|
-
}
|
|
25741
|
-
if (str.length > 0 && !TEXT_REGEXP.test(str)) {
|
|
25742
|
-
throw new TypeError("invalid parameter value");
|
|
25743
|
-
}
|
|
25744
|
-
return '"' + str.replace(QUOTE_REGEXP, "\\$1") + '"';
|
|
25745
|
-
}
|
|
25746
|
-
function ContentType(type) {
|
|
25747
|
-
this.parameters = /* @__PURE__ */ Object.create(null);
|
|
25748
|
-
this.type = type;
|
|
25749
|
-
}
|
|
25750
|
-
}
|
|
25751
|
-
});
|
|
25752
|
-
|
|
25753
25753
|
// node_modules/etag/index.js
|
|
25754
25754
|
var require_etag = __commonJS({
|
|
25755
25755
|
"node_modules/etag/index.js"(exports, module) {
|
|
@@ -35204,7 +35204,7 @@ var require_mime_types2 = __commonJS({
|
|
|
35204
35204
|
var TEXT_TYPE_REGEXP = /^text\//i;
|
|
35205
35205
|
exports.charset = charset;
|
|
35206
35206
|
exports.charsets = { lookup: charset };
|
|
35207
|
-
exports.contentType =
|
|
35207
|
+
exports.contentType = contentType2;
|
|
35208
35208
|
exports.extension = extension;
|
|
35209
35209
|
exports.extensions = /* @__PURE__ */ Object.create(null);
|
|
35210
35210
|
exports.lookup = lookup;
|
|
@@ -35225,7 +35225,7 @@ var require_mime_types2 = __commonJS({
|
|
|
35225
35225
|
}
|
|
35226
35226
|
return false;
|
|
35227
35227
|
}
|
|
35228
|
-
function
|
|
35228
|
+
function contentType2(str) {
|
|
35229
35229
|
if (!str || typeof str !== "string") {
|
|
35230
35230
|
return false;
|
|
35231
35231
|
}
|
|
@@ -36149,7 +36149,7 @@ var require_utils3 = __commonJS({
|
|
|
36149
36149
|
"node_modules/express/lib/utils.js"(exports) {
|
|
36150
36150
|
"use strict";
|
|
36151
36151
|
var { METHODS } = __require("node:http");
|
|
36152
|
-
var
|
|
36152
|
+
var contentType2 = require_content_type();
|
|
36153
36153
|
var etag = require_etag();
|
|
36154
36154
|
var mime = require_mime_types2();
|
|
36155
36155
|
var proxyaddr = require_proxy_addr();
|
|
@@ -36253,9 +36253,9 @@ var require_utils3 = __commonJS({
|
|
|
36253
36253
|
if (!type || !charset) {
|
|
36254
36254
|
return type;
|
|
36255
36255
|
}
|
|
36256
|
-
var parsed =
|
|
36256
|
+
var parsed = contentType2.parse(type);
|
|
36257
36257
|
parsed.parameters.charset = charset;
|
|
36258
|
-
return
|
|
36258
|
+
return contentType2.format(parsed);
|
|
36259
36259
|
};
|
|
36260
36260
|
function createETagGenerator(options) {
|
|
36261
36261
|
return function generateETag(body, encoding) {
|
|
@@ -37800,14 +37800,14 @@ var require_dist4 = __commonJS({
|
|
|
37800
37800
|
var require_accept = __commonJS({
|
|
37801
37801
|
"node_modules/negotiator/lib/accept.js"(exports, module) {
|
|
37802
37802
|
"use strict";
|
|
37803
|
-
var
|
|
37803
|
+
var contentType2 = require_dist4();
|
|
37804
37804
|
module.exports = parseAccept;
|
|
37805
37805
|
function parseAccept(header) {
|
|
37806
37806
|
var values = [];
|
|
37807
37807
|
var index = 0;
|
|
37808
37808
|
while (index < header.length) {
|
|
37809
37809
|
var start = skipOptionalWhitespace(header, index);
|
|
37810
|
-
var parsed =
|
|
37810
|
+
var parsed = contentType2.parse(header, { comma: true, start });
|
|
37811
37811
|
parsed.type = header.slice(start, start + parsed.type.length);
|
|
37812
37812
|
values.push(parsed);
|
|
37813
37813
|
index = parsed.index + 1;
|
|
@@ -38000,7 +38000,7 @@ var require_encoding = __commonJS({
|
|
|
38000
38000
|
var require_language = __commonJS({
|
|
38001
38001
|
"node_modules/negotiator/lib/language.js"(exports, module) {
|
|
38002
38002
|
"use strict";
|
|
38003
|
-
var
|
|
38003
|
+
var contentType2 = require_dist4();
|
|
38004
38004
|
var parseAccept = require_accept();
|
|
38005
38005
|
module.exports = preferredLanguages;
|
|
38006
38006
|
module.exports.preferredLanguages = preferredLanguages;
|
|
@@ -38037,7 +38037,7 @@ var require_language = __commonJS({
|
|
|
38037
38037
|
return priority;
|
|
38038
38038
|
}
|
|
38039
38039
|
function specify(language, spec, index) {
|
|
38040
|
-
var p = formatLanguage(
|
|
38040
|
+
var p = formatLanguage(contentType2.parse(language), 0);
|
|
38041
38041
|
if (!p) return null;
|
|
38042
38042
|
var s2 = 0;
|
|
38043
38043
|
if (spec.full.toLowerCase() === p.full.toLowerCase()) {
|
|
@@ -38084,7 +38084,7 @@ var require_language = __commonJS({
|
|
|
38084
38084
|
var require_mediaType = __commonJS({
|
|
38085
38085
|
"node_modules/negotiator/lib/mediaType.js"(exports, module) {
|
|
38086
38086
|
"use strict";
|
|
38087
|
-
var
|
|
38087
|
+
var contentType2 = require_dist4();
|
|
38088
38088
|
var parseAcceptHeader = require_accept();
|
|
38089
38089
|
module.exports = preferredMediaTypes;
|
|
38090
38090
|
module.exports.preferredMediaTypes = preferredMediaTypes;
|
|
@@ -38121,7 +38121,7 @@ var require_mediaType = __commonJS({
|
|
|
38121
38121
|
return priority;
|
|
38122
38122
|
}
|
|
38123
38123
|
function specify(type, spec, index) {
|
|
38124
|
-
var p = formatMediaType(
|
|
38124
|
+
var p = formatMediaType(contentType2.parse(type), 0);
|
|
38125
38125
|
var s2 = 0;
|
|
38126
38126
|
if (!p) {
|
|
38127
38127
|
return null;
|
|
@@ -47645,7 +47645,7 @@ var require_mime_types3 = __commonJS({
|
|
|
47645
47645
|
var TEXT_TYPE_REGEXP = /^text\//i;
|
|
47646
47646
|
exports.charset = charset;
|
|
47647
47647
|
exports.charsets = { lookup: charset };
|
|
47648
|
-
exports.contentType =
|
|
47648
|
+
exports.contentType = contentType2;
|
|
47649
47649
|
exports.extension = extension;
|
|
47650
47650
|
exports.extensions = /* @__PURE__ */ Object.create(null);
|
|
47651
47651
|
exports.lookup = lookup;
|
|
@@ -47666,7 +47666,7 @@ var require_mime_types3 = __commonJS({
|
|
|
47666
47666
|
}
|
|
47667
47667
|
return false;
|
|
47668
47668
|
}
|
|
47669
|
-
function
|
|
47669
|
+
function contentType2(str) {
|
|
47670
47670
|
if (!str || typeof str !== "string") {
|
|
47671
47671
|
return false;
|
|
47672
47672
|
}
|
|
@@ -57927,7 +57927,7 @@ var require_mime_types4 = __commonJS({
|
|
|
57927
57927
|
var TEXT_TYPE_REGEXP = /^text\//i;
|
|
57928
57928
|
exports.charset = charset;
|
|
57929
57929
|
exports.charsets = { lookup: charset };
|
|
57930
|
-
exports.contentType =
|
|
57930
|
+
exports.contentType = contentType2;
|
|
57931
57931
|
exports.extension = extension;
|
|
57932
57932
|
exports.extensions = /* @__PURE__ */ Object.create(null);
|
|
57933
57933
|
exports.lookup = lookup;
|
|
@@ -57948,7 +57948,7 @@ var require_mime_types4 = __commonJS({
|
|
|
57948
57948
|
}
|
|
57949
57949
|
return false;
|
|
57950
57950
|
}
|
|
57951
|
-
function
|
|
57951
|
+
function contentType2(str) {
|
|
57952
57952
|
if (!str || typeof str !== "string") {
|
|
57953
57953
|
return false;
|
|
57954
57954
|
}
|
|
@@ -58809,7 +58809,7 @@ var require_response = __commonJS({
|
|
|
58809
58809
|
var fullPath = !opts.root ? resolve(path7) : path7;
|
|
58810
58810
|
return this.sendFile(fullPath, opts, done);
|
|
58811
58811
|
};
|
|
58812
|
-
res.contentType = res.type = function
|
|
58812
|
+
res.contentType = res.type = function contentType2(type) {
|
|
58813
58813
|
var ct = type.indexOf("/") === -1 ? mime.contentType(type) || "application/octet-stream" : type;
|
|
58814
58814
|
return this.set("Content-Type", ct);
|
|
58815
58815
|
};
|
|
@@ -73726,10 +73726,9 @@ var ProgressTokenSchema = union([string2(), number2().int()]);
|
|
|
73726
73726
|
var CursorSchema = string2();
|
|
73727
73727
|
var TaskCreationParamsSchema = looseObject({
|
|
73728
73728
|
/**
|
|
73729
|
-
*
|
|
73730
|
-
* If null, the task has unlimited lifetime until manually cleaned up.
|
|
73729
|
+
* Requested duration in milliseconds to retain task from creation.
|
|
73731
73730
|
*/
|
|
73732
|
-
ttl:
|
|
73731
|
+
ttl: number2().optional(),
|
|
73733
73732
|
/**
|
|
73734
73733
|
* Time in milliseconds to wait between task status requests.
|
|
73735
73734
|
*/
|
|
@@ -74026,7 +74025,11 @@ var ClientCapabilitiesSchema = object({
|
|
|
74026
74025
|
/**
|
|
74027
74026
|
* Present if the client supports task creation.
|
|
74028
74027
|
*/
|
|
74029
|
-
tasks: ClientTasksCapabilitySchema.optional()
|
|
74028
|
+
tasks: ClientTasksCapabilitySchema.optional(),
|
|
74029
|
+
/**
|
|
74030
|
+
* Extensions that the client supports. Keys are extension identifiers (vendor-prefix/extension-name).
|
|
74031
|
+
*/
|
|
74032
|
+
extensions: record(string2(), AssertObjectSchema).optional()
|
|
74030
74033
|
});
|
|
74031
74034
|
var InitializeRequestParamsSchema = BaseRequestParamsSchema.extend({
|
|
74032
74035
|
/**
|
|
@@ -74087,7 +74090,11 @@ var ServerCapabilitiesSchema = object({
|
|
|
74087
74090
|
/**
|
|
74088
74091
|
* Present if the server supports task creation.
|
|
74089
74092
|
*/
|
|
74090
|
-
tasks: ServerTasksCapabilitySchema.optional()
|
|
74093
|
+
tasks: ServerTasksCapabilitySchema.optional(),
|
|
74094
|
+
/**
|
|
74095
|
+
* Extensions that the server supports. Keys are extension identifiers (vendor-prefix/extension-name).
|
|
74096
|
+
*/
|
|
74097
|
+
extensions: record(string2(), AssertObjectSchema).optional()
|
|
74091
74098
|
});
|
|
74092
74099
|
var InitializeResultSchema = ResultSchema.extend({
|
|
74093
74100
|
/**
|
|
@@ -74280,6 +74287,12 @@ var ResourceSchema = object({
|
|
|
74280
74287
|
* The MIME type of this resource, if known.
|
|
74281
74288
|
*/
|
|
74282
74289
|
mimeType: optional(string2()),
|
|
74290
|
+
/**
|
|
74291
|
+
* The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known.
|
|
74292
|
+
*
|
|
74293
|
+
* This can be used by Hosts to display file sizes and estimate context window usage.
|
|
74294
|
+
*/
|
|
74295
|
+
size: optional(number2()),
|
|
74283
74296
|
/**
|
|
74284
74297
|
* Optional annotations for the client.
|
|
74285
74298
|
*/
|
|
@@ -75221,8 +75234,17 @@ var UrlElicitationRequiredError = class extends McpError {
|
|
|
75221
75234
|
};
|
|
75222
75235
|
|
|
75223
75236
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
|
|
75237
|
+
var STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
|
|
75224
75238
|
var ReadBuffer = class {
|
|
75239
|
+
constructor(options) {
|
|
75240
|
+
this._maxBufferSize = options?.maxBufferSize ?? STDIO_DEFAULT_MAX_BUFFER_SIZE;
|
|
75241
|
+
}
|
|
75225
75242
|
append(chunk) {
|
|
75243
|
+
const newSize = (this._buffer?.length ?? 0) + chunk.length;
|
|
75244
|
+
if (newSize > this._maxBufferSize) {
|
|
75245
|
+
this.clear();
|
|
75246
|
+
throw new Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`);
|
|
75247
|
+
}
|
|
75226
75248
|
this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
|
|
75227
75249
|
}
|
|
75228
75250
|
readMessage() {
|
|
@@ -75250,18 +75272,24 @@ function serializeMessage(message) {
|
|
|
75250
75272
|
|
|
75251
75273
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
75252
75274
|
var StdioServerTransport = class {
|
|
75253
|
-
constructor(_stdin = process3.stdin, _stdout = process3.stdout) {
|
|
75275
|
+
constructor(_stdin = process3.stdin, _stdout = process3.stdout, options) {
|
|
75254
75276
|
this._stdin = _stdin;
|
|
75255
75277
|
this._stdout = _stdout;
|
|
75256
|
-
this._readBuffer = new ReadBuffer();
|
|
75257
75278
|
this._started = false;
|
|
75258
75279
|
this._ondata = (chunk) => {
|
|
75259
|
-
|
|
75260
|
-
|
|
75280
|
+
try {
|
|
75281
|
+
this._readBuffer.append(chunk);
|
|
75282
|
+
this.processReadBuffer();
|
|
75283
|
+
} catch (error51) {
|
|
75284
|
+
this.onerror?.(error51);
|
|
75285
|
+
this.close().catch(() => {
|
|
75286
|
+
});
|
|
75287
|
+
}
|
|
75261
75288
|
};
|
|
75262
75289
|
this._onerror = (error51) => {
|
|
75263
75290
|
this.onerror?.(error51);
|
|
75264
75291
|
};
|
|
75292
|
+
this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize });
|
|
75265
75293
|
}
|
|
75266
75294
|
/**
|
|
75267
75295
|
* Starts listening for messages on stdin.
|
|
@@ -75580,7 +75608,12 @@ var OAuthTokensSchema = object({
|
|
|
75580
75608
|
token_type: string2(),
|
|
75581
75609
|
expires_in: coerce_exports.number().optional(),
|
|
75582
75610
|
scope: string2().optional(),
|
|
75583
|
-
refresh_token: string2().optional()
|
|
75611
|
+
refresh_token: string2().optional(),
|
|
75612
|
+
/**
|
|
75613
|
+
* Not part of the wire format: the authorization server this value was obtained from, added by
|
|
75614
|
+
* the client's `auth()` before it is stored and compared when it is read back.
|
|
75615
|
+
*/
|
|
75616
|
+
issuer: string2().optional().catch(void 0)
|
|
75584
75617
|
}).strip();
|
|
75585
75618
|
var OAuthErrorResponseSchema = object({
|
|
75586
75619
|
error: string2(),
|
|
@@ -75610,7 +75643,12 @@ var OAuthClientInformationSchema = object({
|
|
|
75610
75643
|
client_id: string2(),
|
|
75611
75644
|
client_secret: string2().optional(),
|
|
75612
75645
|
client_id_issued_at: number2().optional(),
|
|
75613
|
-
client_secret_expires_at: number2().optional()
|
|
75646
|
+
client_secret_expires_at: number2().optional(),
|
|
75647
|
+
/**
|
|
75648
|
+
* Not part of the wire format: the authorization server this value was obtained from, added by
|
|
75649
|
+
* the client's `auth()` before it is stored and compared when it is read back.
|
|
75650
|
+
*/
|
|
75651
|
+
issuer: string2().optional().catch(void 0)
|
|
75614
75652
|
}).strip();
|
|
75615
75653
|
var OAuthClientInformationFullSchema = OAuthClientMetadataSchema.merge(OAuthClientInformationSchema);
|
|
75616
75654
|
var OAuthClientRegistrationErrorSchema = object({
|
|
@@ -75750,12 +75788,12 @@ var AUTHORIZATION_CODE_RESPONSE_TYPE = "code";
|
|
|
75750
75788
|
var AUTHORIZATION_CODE_CHALLENGE_METHOD = "S256";
|
|
75751
75789
|
function selectClientAuthMethod(clientInformation, supportedMethods) {
|
|
75752
75790
|
const hasClientSecret = clientInformation.client_secret !== void 0;
|
|
75753
|
-
if (supportedMethods.length === 0) {
|
|
75754
|
-
return hasClientSecret ? "client_secret_post" : "none";
|
|
75755
|
-
}
|
|
75756
|
-
if ("token_endpoint_auth_method" in clientInformation && clientInformation.token_endpoint_auth_method && isClientAuthMethod(clientInformation.token_endpoint_auth_method) && supportedMethods.includes(clientInformation.token_endpoint_auth_method)) {
|
|
75791
|
+
if ("token_endpoint_auth_method" in clientInformation && clientInformation.token_endpoint_auth_method && isClientAuthMethod(clientInformation.token_endpoint_auth_method) && (supportedMethods.length === 0 || supportedMethods.includes(clientInformation.token_endpoint_auth_method))) {
|
|
75757
75792
|
return clientInformation.token_endpoint_auth_method;
|
|
75758
75793
|
}
|
|
75794
|
+
if (supportedMethods.length === 0) {
|
|
75795
|
+
return hasClientSecret ? "client_secret_basic" : "none";
|
|
75796
|
+
}
|
|
75759
75797
|
if (hasClientSecret && supportedMethods.includes("client_secret_basic")) {
|
|
75760
75798
|
return "client_secret_basic";
|
|
75761
75799
|
}
|
|
@@ -75812,6 +75850,26 @@ async function parseErrorResponse(input) {
|
|
|
75812
75850
|
return new ServerError(errorMessage);
|
|
75813
75851
|
}
|
|
75814
75852
|
}
|
|
75853
|
+
function issuersMatch(a, b) {
|
|
75854
|
+
let [x2, y] = [a, b];
|
|
75855
|
+
try {
|
|
75856
|
+
[x2, y] = [new URL(a).href, new URL(b).href];
|
|
75857
|
+
} catch {
|
|
75858
|
+
}
|
|
75859
|
+
return x2 === y || x2.endsWith("/") && x2.slice(0, -1) === y || y.endsWith("/") && y.slice(0, -1) === x2;
|
|
75860
|
+
}
|
|
75861
|
+
function discardIfIssuerMismatch(stored, issuer) {
|
|
75862
|
+
if (!stored)
|
|
75863
|
+
return void 0;
|
|
75864
|
+
if (typeof stored.issuer !== "string")
|
|
75865
|
+
return stored.issuer == null ? stored : { ...stored, issuer: void 0 };
|
|
75866
|
+
return issuersMatch(stored.issuer, issuer) ? stored : void 0;
|
|
75867
|
+
}
|
|
75868
|
+
var TokenResponseSchema = OAuthTokensSchema.omit({ issuer: true });
|
|
75869
|
+
var RegistrationResponseSchema = OAuthClientInformationFullSchema.omit({ issuer: true });
|
|
75870
|
+
function boundElsewhereError(stored, issuer) {
|
|
75871
|
+
return new Error(`OAuth client information is bound to authorization server ${stored.issuer} and is not presented to ${issuer}. Clear the stored client information, or correct \`expectedIssuer\`, if the authorization server has moved.`);
|
|
75872
|
+
}
|
|
75815
75873
|
async function auth(provider, options) {
|
|
75816
75874
|
try {
|
|
75817
75875
|
return await authInternal(provider, options);
|
|
@@ -75827,23 +75885,62 @@ async function auth(provider, options) {
|
|
|
75827
75885
|
}
|
|
75828
75886
|
}
|
|
75829
75887
|
async function authInternal(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl, fetchFn }) {
|
|
75888
|
+
const cachedState = await provider.discoveryState?.();
|
|
75830
75889
|
let resourceMetadata;
|
|
75831
75890
|
let authorizationServerUrl;
|
|
75832
|
-
|
|
75833
|
-
|
|
75834
|
-
|
|
75835
|
-
|
|
75891
|
+
let metadata;
|
|
75892
|
+
let effectiveResourceMetadataUrl = resourceMetadataUrl;
|
|
75893
|
+
if (!effectiveResourceMetadataUrl && cachedState?.resourceMetadataUrl) {
|
|
75894
|
+
effectiveResourceMetadataUrl = new URL(cachedState.resourceMetadataUrl);
|
|
75895
|
+
}
|
|
75896
|
+
if (cachedState?.authorizationServerUrl) {
|
|
75897
|
+
authorizationServerUrl = cachedState.authorizationServerUrl;
|
|
75898
|
+
resourceMetadata = cachedState.resourceMetadata;
|
|
75899
|
+
metadata = cachedState.authorizationServerMetadata ?? await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn });
|
|
75900
|
+
if (!resourceMetadata) {
|
|
75901
|
+
try {
|
|
75902
|
+
resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl: effectiveResourceMetadataUrl }, fetchFn);
|
|
75903
|
+
} catch {
|
|
75904
|
+
}
|
|
75836
75905
|
}
|
|
75837
|
-
|
|
75838
|
-
|
|
75839
|
-
|
|
75840
|
-
|
|
75906
|
+
if (metadata !== cachedState.authorizationServerMetadata || resourceMetadata !== cachedState.resourceMetadata) {
|
|
75907
|
+
await provider.saveDiscoveryState?.({
|
|
75908
|
+
authorizationServerUrl: String(authorizationServerUrl),
|
|
75909
|
+
resourceMetadataUrl: effectiveResourceMetadataUrl?.toString(),
|
|
75910
|
+
resourceMetadata,
|
|
75911
|
+
authorizationServerMetadata: metadata
|
|
75912
|
+
});
|
|
75913
|
+
}
|
|
75914
|
+
} else {
|
|
75915
|
+
const serverInfo = await discoverOAuthServerInfo(serverUrl, { resourceMetadataUrl: effectiveResourceMetadataUrl, fetchFn });
|
|
75916
|
+
authorizationServerUrl = serverInfo.authorizationServerUrl;
|
|
75917
|
+
metadata = serverInfo.authorizationServerMetadata;
|
|
75918
|
+
resourceMetadata = serverInfo.resourceMetadata;
|
|
75919
|
+
await provider.saveDiscoveryState?.({
|
|
75920
|
+
authorizationServerUrl: String(authorizationServerUrl),
|
|
75921
|
+
resourceMetadataUrl: effectiveResourceMetadataUrl?.toString(),
|
|
75922
|
+
resourceMetadata,
|
|
75923
|
+
authorizationServerMetadata: metadata
|
|
75924
|
+
});
|
|
75841
75925
|
}
|
|
75842
|
-
const
|
|
75843
|
-
const
|
|
75844
|
-
|
|
75845
|
-
|
|
75846
|
-
|
|
75926
|
+
const issuer = String(authorizationServerUrl);
|
|
75927
|
+
const selectedResource = await selectResourceURL(serverUrl, provider, resourceMetadata);
|
|
75928
|
+
const resource = selectedResource && resourceMetadata && !provider.validateResourceURL ? resourceMetadata.resource : selectedResource;
|
|
75929
|
+
const resolvedScope = scope || resourceMetadata?.scopes_supported?.join(" ") || provider.clientMetadata.scope;
|
|
75930
|
+
const storedClientInformation = await Promise.resolve(provider.clientInformation());
|
|
75931
|
+
let clientInformation = discardIfIssuerMismatch(storedClientInformation, issuer);
|
|
75932
|
+
const canRegisterAgain = provider.saveClientInformation !== void 0 && !!provider.redirectUrl;
|
|
75933
|
+
if (storedClientInformation && !clientInformation && !canRegisterAgain) {
|
|
75934
|
+
throw boundElsewhereError(storedClientInformation, issuer);
|
|
75935
|
+
}
|
|
75936
|
+
const unstampedClientInformation = clientInformation?.issuer == null ? clientInformation : void 0;
|
|
75937
|
+
const bindClientInformation = async () => {
|
|
75938
|
+
try {
|
|
75939
|
+
if (unstampedClientInformation)
|
|
75940
|
+
await provider.saveClientInformation?.({ ...unstampedClientInformation, issuer });
|
|
75941
|
+
} catch {
|
|
75942
|
+
}
|
|
75943
|
+
};
|
|
75847
75944
|
if (!clientInformation) {
|
|
75848
75945
|
if (authorizationCode !== void 0) {
|
|
75849
75946
|
throw new Error("Existing OAuth client information is required when exchanging an authorization code");
|
|
@@ -75855,9 +75952,7 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
75855
75952
|
}
|
|
75856
75953
|
const shouldUseUrlBasedClientId = supportsUrlBasedClientId && clientMetadataUrl;
|
|
75857
75954
|
if (shouldUseUrlBasedClientId) {
|
|
75858
|
-
clientInformation = {
|
|
75859
|
-
client_id: clientMetadataUrl
|
|
75860
|
-
};
|
|
75955
|
+
clientInformation = { client_id: clientMetadataUrl, issuer };
|
|
75861
75956
|
await provider.saveClientInformation?.(clientInformation);
|
|
75862
75957
|
} else {
|
|
75863
75958
|
if (!provider.saveClientInformation) {
|
|
@@ -75866,10 +75961,11 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
75866
75961
|
const fullInformation = await registerClient(authorizationServerUrl, {
|
|
75867
75962
|
metadata,
|
|
75868
75963
|
clientMetadata: provider.clientMetadata,
|
|
75964
|
+
scope: resolvedScope,
|
|
75869
75965
|
fetchFn
|
|
75870
75966
|
});
|
|
75871
|
-
|
|
75872
|
-
clientInformation
|
|
75967
|
+
clientInformation = { ...fullInformation, issuer };
|
|
75968
|
+
await provider.saveClientInformation(clientInformation);
|
|
75873
75969
|
}
|
|
75874
75970
|
}
|
|
75875
75971
|
const nonInteractiveFlow = !provider.redirectUrl;
|
|
@@ -75880,10 +75976,14 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
75880
75976
|
authorizationCode,
|
|
75881
75977
|
fetchFn
|
|
75882
75978
|
});
|
|
75883
|
-
await
|
|
75979
|
+
await bindClientInformation();
|
|
75980
|
+
await provider.saveTokens({ ...tokens2, issuer });
|
|
75884
75981
|
return "AUTHORIZED";
|
|
75885
75982
|
}
|
|
75886
|
-
const tokens = await provider.tokens();
|
|
75983
|
+
const tokens = discardIfIssuerMismatch(await provider.tokens(), issuer);
|
|
75984
|
+
if (tokens?.refresh_token && tokens.issuer == null) {
|
|
75985
|
+
console.warn("[mcp-sdk] stored OAuth tokens have no 'issuer' property (saved by an earlier version, or by a provider that does not keep it) and are used as-is; make sure your OAuthClientProvider stores what saveTokens() and saveClientInformation() receive unchanged.");
|
|
75986
|
+
}
|
|
75887
75987
|
if (tokens?.refresh_token) {
|
|
75888
75988
|
try {
|
|
75889
75989
|
const newTokens = await refreshAuthorization(authorizationServerUrl, {
|
|
@@ -75894,7 +75994,8 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
75894
75994
|
addClientAuthentication: provider.addClientAuthentication,
|
|
75895
75995
|
fetchFn
|
|
75896
75996
|
});
|
|
75897
|
-
await
|
|
75997
|
+
await bindClientInformation();
|
|
75998
|
+
await provider.saveTokens({ ...newTokens, issuer });
|
|
75898
75999
|
return "AUTHORIZED";
|
|
75899
76000
|
} catch (error51) {
|
|
75900
76001
|
if (!(error51 instanceof OAuthError) || error51 instanceof ServerError) {
|
|
@@ -75909,7 +76010,7 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
75909
76010
|
clientInformation,
|
|
75910
76011
|
state,
|
|
75911
76012
|
redirectUrl: provider.redirectUrl,
|
|
75912
|
-
scope:
|
|
76013
|
+
scope: resolvedScope,
|
|
75913
76014
|
resource
|
|
75914
76015
|
});
|
|
75915
76016
|
await provider.saveCodeVerifier(codeVerifier);
|
|
@@ -76097,6 +76198,29 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, { fet
|
|
|
76097
76198
|
}
|
|
76098
76199
|
return void 0;
|
|
76099
76200
|
}
|
|
76201
|
+
async function discoverOAuthServerInfo(serverUrl, opts) {
|
|
76202
|
+
let resourceMetadata;
|
|
76203
|
+
let authorizationServerUrl;
|
|
76204
|
+
try {
|
|
76205
|
+
resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl: opts?.resourceMetadataUrl }, opts?.fetchFn);
|
|
76206
|
+
if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) {
|
|
76207
|
+
authorizationServerUrl = resourceMetadata.authorization_servers[0];
|
|
76208
|
+
}
|
|
76209
|
+
} catch {
|
|
76210
|
+
}
|
|
76211
|
+
if (!authorizationServerUrl) {
|
|
76212
|
+
authorizationServerUrl = String(new URL("/", serverUrl));
|
|
76213
|
+
}
|
|
76214
|
+
const authorizationServerMetadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn: opts?.fetchFn });
|
|
76215
|
+
return {
|
|
76216
|
+
authorizationServerUrl,
|
|
76217
|
+
authorizationServerMetadata,
|
|
76218
|
+
resourceMetadata
|
|
76219
|
+
};
|
|
76220
|
+
}
|
|
76221
|
+
function resourceIndicatorToString(resource) {
|
|
76222
|
+
return typeof resource === "string" ? resource : resource.href;
|
|
76223
|
+
}
|
|
76100
76224
|
async function startAuthorization(authorizationServerUrl, { metadata, clientInformation, redirectUrl, scope, state, resource }) {
|
|
76101
76225
|
let authorizationUrl;
|
|
76102
76226
|
if (metadata) {
|
|
@@ -76128,7 +76252,7 @@ async function startAuthorization(authorizationServerUrl, { metadata, clientInfo
|
|
|
76128
76252
|
authorizationUrl.searchParams.append("prompt", "consent");
|
|
76129
76253
|
}
|
|
76130
76254
|
if (resource) {
|
|
76131
|
-
authorizationUrl.searchParams.set("resource", resource
|
|
76255
|
+
authorizationUrl.searchParams.set("resource", resourceIndicatorToString(resource));
|
|
76132
76256
|
}
|
|
76133
76257
|
return { authorizationUrl, codeVerifier };
|
|
76134
76258
|
}
|
|
@@ -76147,7 +76271,7 @@ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequ
|
|
|
76147
76271
|
Accept: "application/json"
|
|
76148
76272
|
});
|
|
76149
76273
|
if (resource) {
|
|
76150
|
-
tokenRequestParams.set("resource", resource
|
|
76274
|
+
tokenRequestParams.set("resource", resourceIndicatorToString(resource));
|
|
76151
76275
|
}
|
|
76152
76276
|
if (addClientAuthentication) {
|
|
76153
76277
|
await addClientAuthentication(headers, tokenRequestParams, tokenUrl, metadata);
|
|
@@ -76164,7 +76288,7 @@ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequ
|
|
|
76164
76288
|
if (!response.ok) {
|
|
76165
76289
|
throw await parseErrorResponse(response);
|
|
76166
76290
|
}
|
|
76167
|
-
return
|
|
76291
|
+
return TokenResponseSchema.parse(await response.json());
|
|
76168
76292
|
}
|
|
76169
76293
|
async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, fetchFn }) {
|
|
76170
76294
|
const tokenRequestParams = new URLSearchParams({
|
|
@@ -76182,6 +76306,15 @@ async function refreshAuthorization(authorizationServerUrl, { metadata, clientIn
|
|
|
76182
76306
|
return { refresh_token: refreshToken, ...tokens };
|
|
76183
76307
|
}
|
|
76184
76308
|
async function fetchToken(provider, authorizationServerUrl, { metadata, resource, authorizationCode, fetchFn } = {}) {
|
|
76309
|
+
const readClientInformation = async () => {
|
|
76310
|
+
const storedClientInformation = await provider.clientInformation();
|
|
76311
|
+
const checked = discardIfIssuerMismatch(storedClientInformation, String(authorizationServerUrl));
|
|
76312
|
+
if (storedClientInformation && !checked) {
|
|
76313
|
+
throw boundElsewhereError(storedClientInformation, String(authorizationServerUrl));
|
|
76314
|
+
}
|
|
76315
|
+
return checked;
|
|
76316
|
+
};
|
|
76317
|
+
let clientInformation = await readClientInformation();
|
|
76185
76318
|
const scope = provider.clientMetadata.scope;
|
|
76186
76319
|
let tokenRequestParams;
|
|
76187
76320
|
if (provider.prepareTokenRequest) {
|
|
@@ -76197,17 +76330,17 @@ async function fetchToken(provider, authorizationServerUrl, { metadata, resource
|
|
|
76197
76330
|
const codeVerifier = await provider.codeVerifier();
|
|
76198
76331
|
tokenRequestParams = prepareAuthorizationCodeRequest(authorizationCode, codeVerifier, provider.redirectUrl);
|
|
76199
76332
|
}
|
|
76200
|
-
|
|
76333
|
+
clientInformation ?? (clientInformation = await readClientInformation());
|
|
76201
76334
|
return executeTokenRequest(authorizationServerUrl, {
|
|
76202
76335
|
metadata,
|
|
76203
76336
|
tokenRequestParams,
|
|
76204
|
-
clientInformation
|
|
76337
|
+
clientInformation,
|
|
76205
76338
|
addClientAuthentication: provider.addClientAuthentication,
|
|
76206
76339
|
resource,
|
|
76207
76340
|
fetchFn
|
|
76208
76341
|
});
|
|
76209
76342
|
}
|
|
76210
|
-
async function registerClient(authorizationServerUrl, { metadata, clientMetadata, fetchFn }) {
|
|
76343
|
+
async function registerClient(authorizationServerUrl, { metadata, clientMetadata, scope, fetchFn }) {
|
|
76211
76344
|
let registrationUrl;
|
|
76212
76345
|
if (metadata) {
|
|
76213
76346
|
if (!metadata.registration_endpoint) {
|
|
@@ -76222,12 +76355,15 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
|
|
|
76222
76355
|
headers: {
|
|
76223
76356
|
"Content-Type": "application/json"
|
|
76224
76357
|
},
|
|
76225
|
-
body: JSON.stringify(
|
|
76358
|
+
body: JSON.stringify({
|
|
76359
|
+
...clientMetadata,
|
|
76360
|
+
...scope !== void 0 ? { scope } : {}
|
|
76361
|
+
})
|
|
76226
76362
|
});
|
|
76227
76363
|
if (!response.ok) {
|
|
76228
76364
|
throw await parseErrorResponse(response);
|
|
76229
76365
|
}
|
|
76230
|
-
return
|
|
76366
|
+
return RegistrationResponseSchema.parse(await response.json());
|
|
76231
76367
|
}
|
|
76232
76368
|
|
|
76233
76369
|
// src/lib/utils.ts
|
|
@@ -76245,7 +76381,6 @@ import crypto3 from "crypto";
|
|
|
76245
76381
|
// src/lib/persistent-auth-config.ts
|
|
76246
76382
|
import path from "path";
|
|
76247
76383
|
import fs from "fs/promises";
|
|
76248
|
-
import fsSync from "fs";
|
|
76249
76384
|
import crypto2 from "crypto";
|
|
76250
76385
|
function getConfigDir() {
|
|
76251
76386
|
const baseConfigDir = CONFIG.WP_MCP_CONFIG_DIR;
|
|
@@ -76342,21 +76477,25 @@ async function writeTokens(serverUrlHash, tokens) {
|
|
|
76342
76477
|
...tokens,
|
|
76343
76478
|
obtained_at: Date.now()
|
|
76344
76479
|
};
|
|
76345
|
-
await
|
|
76480
|
+
await ensureConfigDir();
|
|
76481
|
+
const file2 = getConfigFilePath(serverUrlHash, "tokens.json");
|
|
76482
|
+
const temporary = `${file2}.${crypto2.randomUUID()}.tmp`;
|
|
76483
|
+
try {
|
|
76484
|
+
await fs.writeFile(temporary, JSON.stringify(tokensWithTimestamp, null, 2), {
|
|
76485
|
+
encoding: "utf-8",
|
|
76486
|
+
mode: 384,
|
|
76487
|
+
flag: "wx"
|
|
76488
|
+
});
|
|
76489
|
+
await fs.rename(temporary, file2);
|
|
76490
|
+
} finally {
|
|
76491
|
+
await fs.rm(temporary, { force: true });
|
|
76492
|
+
}
|
|
76346
76493
|
logger.info(`Stored tokens for server hash: ${serverUrlHash}`, "AUTH");
|
|
76347
76494
|
} catch (error51) {
|
|
76348
76495
|
logger.error(`Error writing tokens for ${serverUrlHash}`, "AUTH", error51);
|
|
76349
76496
|
throw error51;
|
|
76350
76497
|
}
|
|
76351
76498
|
}
|
|
76352
|
-
async function deleteTokens(serverUrlHash) {
|
|
76353
|
-
try {
|
|
76354
|
-
await deleteConfigFile(serverUrlHash, "tokens.json");
|
|
76355
|
-
logger.info(`Deleted tokens for server hash: ${serverUrlHash}`, "AUTH");
|
|
76356
|
-
} catch (error51) {
|
|
76357
|
-
logger.error(`Error deleting tokens for ${serverUrlHash}`, "AUTH", error51);
|
|
76358
|
-
}
|
|
76359
|
-
}
|
|
76360
76499
|
async function readClientInfo(serverUrlHash) {
|
|
76361
76500
|
try {
|
|
76362
76501
|
const clientInfo = await readJsonFile(serverUrlHash, "client_info.json");
|
|
@@ -76383,7 +76522,7 @@ function isTokenValid(tokens) {
|
|
|
76383
76522
|
if (!tokens?.access_token) {
|
|
76384
76523
|
return { isValid: false, error: "No access token" };
|
|
76385
76524
|
}
|
|
76386
|
-
if (
|
|
76525
|
+
if (tokens.expires_in === void 0 || tokens.obtained_at === void 0) {
|
|
76387
76526
|
return { isValid: true };
|
|
76388
76527
|
}
|
|
76389
76528
|
const now = Date.now();
|
|
@@ -76415,30 +76554,6 @@ async function getValidTokens(serverUrlHash) {
|
|
|
76415
76554
|
}
|
|
76416
76555
|
return tokens;
|
|
76417
76556
|
}
|
|
76418
|
-
async function cleanupExpiredTokens() {
|
|
76419
|
-
try {
|
|
76420
|
-
const configDir = getConfigDir();
|
|
76421
|
-
if (!fsSync.existsSync(configDir)) {
|
|
76422
|
-
return;
|
|
76423
|
-
}
|
|
76424
|
-
const files = await fs.readdir(configDir);
|
|
76425
|
-
const tokenFiles = files.filter((file2) => file2.endsWith("_tokens.json"));
|
|
76426
|
-
let cleaned = 0;
|
|
76427
|
-
for (const file2 of tokenFiles) {
|
|
76428
|
-
const serverHash = file2.replace("_tokens.json", "");
|
|
76429
|
-
const tokens = await readTokens(serverHash);
|
|
76430
|
-
if (tokens && !isTokenValid(tokens).isValid) {
|
|
76431
|
-
await deleteTokens(serverHash);
|
|
76432
|
-
cleaned++;
|
|
76433
|
-
}
|
|
76434
|
-
}
|
|
76435
|
-
if (cleaned > 0) {
|
|
76436
|
-
logger.info(`Cleaned up ${cleaned} expired token files`, "AUTH");
|
|
76437
|
-
}
|
|
76438
|
-
} catch (error51) {
|
|
76439
|
-
logger.error("Error during token cleanup", "AUTH", error51);
|
|
76440
|
-
}
|
|
76441
|
-
}
|
|
76442
76557
|
|
|
76443
76558
|
// src/lib/port-utils.ts
|
|
76444
76559
|
var OAuthClientInfoSchema = external_exports.object({
|
|
@@ -76446,12 +76561,12 @@ var OAuthClientInfoSchema = external_exports.object({
|
|
|
76446
76561
|
client_id: external_exports.string().optional(),
|
|
76447
76562
|
client_secret: external_exports.string().optional()
|
|
76448
76563
|
});
|
|
76449
|
-
async function findAvailablePort(preferredPort) {
|
|
76564
|
+
async function findAvailablePort(preferredPort, host = "127.0.0.1") {
|
|
76450
76565
|
return new Promise((resolve, reject) => {
|
|
76451
76566
|
const server = net.createServer();
|
|
76452
76567
|
server.on("error", (err) => {
|
|
76453
76568
|
if (err.code === "EADDRINUSE") {
|
|
76454
|
-
server.listen(0);
|
|
76569
|
+
server.listen(0, host);
|
|
76455
76570
|
} else {
|
|
76456
76571
|
reject(err);
|
|
76457
76572
|
}
|
|
@@ -76462,7 +76577,7 @@ async function findAvailablePort(preferredPort) {
|
|
|
76462
76577
|
resolve(port);
|
|
76463
76578
|
});
|
|
76464
76579
|
});
|
|
76465
|
-
server.listen(preferredPort || 0);
|
|
76580
|
+
server.listen(preferredPort || 0, host);
|
|
76466
76581
|
});
|
|
76467
76582
|
}
|
|
76468
76583
|
function calculateDefaultPort(serverUrlHash) {
|
|
@@ -76490,24 +76605,17 @@ async function findExistingClientPort(serverUrlHash) {
|
|
|
76490
76605
|
function getServerUrlHash(serverUrl) {
|
|
76491
76606
|
return crypto3.createHash("md5").update(serverUrl).digest("hex");
|
|
76492
76607
|
}
|
|
76493
|
-
async function selectCallbackPort(serverUrl, specifiedPort, _unused) {
|
|
76608
|
+
async function selectCallbackPort(serverUrl, specifiedPort, _unused, host = "127.0.0.1") {
|
|
76494
76609
|
const serverUrlHash = getServerUrlHash(serverUrl);
|
|
76495
76610
|
if (specifiedPort) {
|
|
76496
76611
|
return specifiedPort;
|
|
76497
76612
|
}
|
|
76498
|
-
const
|
|
76499
|
-
|
|
76500
|
-
findExistingClientPort(serverUrlHash),
|
|
76501
|
-
findAvailablePort(defaultPort)
|
|
76502
|
-
]);
|
|
76503
|
-
if (existingClientPort) {
|
|
76504
|
-
return existingClientPort;
|
|
76505
|
-
}
|
|
76506
|
-
return availablePort;
|
|
76613
|
+
const existingClientPort = await findExistingClientPort(serverUrlHash);
|
|
76614
|
+
return findAvailablePort(existingClientPort ?? calculateDefaultPort(serverUrlHash), host);
|
|
76507
76615
|
}
|
|
76508
76616
|
|
|
76509
76617
|
// src/lib/config.ts
|
|
76510
|
-
var MCP_WORDPRESS_REMOTE_VERSION = "0.5.
|
|
76618
|
+
var MCP_WORDPRESS_REMOTE_VERSION = "0.5.3";
|
|
76511
76619
|
function parsePositiveIntEnv(value, defaultValue) {
|
|
76512
76620
|
if (!value) {
|
|
76513
76621
|
return defaultValue;
|
|
@@ -76708,8 +76816,8 @@ async function getOAuthCallbackPort() {
|
|
|
76708
76816
|
return selectCallbackPort(
|
|
76709
76817
|
CONFIG.WP_API_URL,
|
|
76710
76818
|
CONFIG.OAUTH_CALLBACK_PORT,
|
|
76711
|
-
false
|
|
76712
|
-
|
|
76819
|
+
false,
|
|
76820
|
+
CONFIG.OAUTH_HOST
|
|
76713
76821
|
);
|
|
76714
76822
|
}
|
|
76715
76823
|
function formatConfigError(error51) {
|
|
@@ -77080,6 +77188,23 @@ async function proxyFetch(url2, init) {
|
|
|
77080
77188
|
// src/lib/wordpress-transport.ts
|
|
77081
77189
|
import { Readable } from "node:stream";
|
|
77082
77190
|
|
|
77191
|
+
// node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.js
|
|
77192
|
+
var import_content_type = __toESM(require_content_type(), 1);
|
|
77193
|
+
function mediaTypeEssence(header) {
|
|
77194
|
+
if (!header) {
|
|
77195
|
+
return void 0;
|
|
77196
|
+
}
|
|
77197
|
+
try {
|
|
77198
|
+
return import_content_type.default.parse(header).type;
|
|
77199
|
+
} catch {
|
|
77200
|
+
const essence = (header.split(";", 1)[0] ?? "").trim().toLowerCase();
|
|
77201
|
+
if (essence === "" || header.slice(essence.length).includes(",")) {
|
|
77202
|
+
return void 0;
|
|
77203
|
+
}
|
|
77204
|
+
return essence;
|
|
77205
|
+
}
|
|
77206
|
+
}
|
|
77207
|
+
|
|
77083
77208
|
// node_modules/eventsource-parser/dist/stream.js
|
|
77084
77209
|
var EventSourceParserStream = class extends TransformStream {
|
|
77085
77210
|
constructor({ onError, onRetry, onComment } = {}) {
|
|
@@ -77227,13 +77352,13 @@ var StreamableHTTPClientTransport = class {
|
|
|
77227
77352
|
this.onerror?.(new Error(`Maximum reconnection attempts (${maxRetries}) exceeded.`));
|
|
77228
77353
|
return;
|
|
77229
77354
|
}
|
|
77230
|
-
const
|
|
77355
|
+
const delay2 = this._getNextReconnectionDelay(attemptCount);
|
|
77231
77356
|
this._reconnectionTimeout = setTimeout(() => {
|
|
77232
77357
|
this._startOrAuthSse(options).catch((error51) => {
|
|
77233
77358
|
this.onerror?.(new Error(`Failed to reconnect SSE stream: ${error51 instanceof Error ? error51.message : String(error51)}`));
|
|
77234
77359
|
this._scheduleReconnection(options, attemptCount + 1);
|
|
77235
77360
|
});
|
|
77236
|
-
},
|
|
77361
|
+
}, delay2);
|
|
77237
77362
|
}
|
|
77238
77363
|
_handleSseStream(stream, options, isReconnectable) {
|
|
77239
77364
|
if (!stream) {
|
|
@@ -77420,11 +77545,12 @@ var StreamableHTTPClientTransport = class {
|
|
|
77420
77545
|
}
|
|
77421
77546
|
const messages = Array.isArray(message) ? message : [message];
|
|
77422
77547
|
const hasRequests = messages.filter((msg) => "method" in msg && "id" in msg && msg.id !== void 0).length > 0;
|
|
77423
|
-
const
|
|
77548
|
+
const contentType2 = response.headers.get("content-type");
|
|
77549
|
+
const responseMediaType = mediaTypeEssence(contentType2);
|
|
77424
77550
|
if (hasRequests) {
|
|
77425
|
-
if (
|
|
77551
|
+
if (responseMediaType === "text/event-stream") {
|
|
77426
77552
|
this._handleSseStream(response.body, { onresumptiontoken }, false);
|
|
77427
|
-
} else if (
|
|
77553
|
+
} else if (responseMediaType === "application/json") {
|
|
77428
77554
|
const data = await response.json();
|
|
77429
77555
|
const responseMessages = Array.isArray(data) ? data.map((msg) => JSONRPCMessageSchema.parse(msg)) : [JSONRPCMessageSchema.parse(data)];
|
|
77430
77556
|
for (const msg of responseMessages) {
|
|
@@ -77432,7 +77558,7 @@ var StreamableHTTPClientTransport = class {
|
|
|
77432
77558
|
}
|
|
77433
77559
|
} else {
|
|
77434
77560
|
await response.body?.cancel();
|
|
77435
|
-
throw new StreamableHTTPError(-1, `Unexpected content type: ${
|
|
77561
|
+
throw new StreamableHTTPError(-1, `Unexpected content type: ${contentType2}`);
|
|
77436
77562
|
}
|
|
77437
77563
|
} else {
|
|
77438
77564
|
await response.body?.cancel();
|
|
@@ -78138,10 +78264,48 @@ defineLazyProperty(apps, "browserPrivate", () => "browserPrivate");
|
|
|
78138
78264
|
var open_default = open;
|
|
78139
78265
|
|
|
78140
78266
|
// src/lib/mcp-oauth-provider.ts
|
|
78267
|
+
import lockfile from "proper-lockfile";
|
|
78268
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
78141
78269
|
import { EventEmitter } from "node:events";
|
|
78142
78270
|
|
|
78143
78271
|
// src/lib/mcp-oauth-utils.ts
|
|
78144
78272
|
import crypto4 from "crypto";
|
|
78273
|
+
|
|
78274
|
+
// src/lib/oauth-http.ts
|
|
78275
|
+
function validateOAuthUrl(value) {
|
|
78276
|
+
let url2;
|
|
78277
|
+
try {
|
|
78278
|
+
url2 = new URL(value);
|
|
78279
|
+
} catch {
|
|
78280
|
+
throw new OAuthError2("Invalid OAuth URL", "INVALID_OAUTH_URL");
|
|
78281
|
+
}
|
|
78282
|
+
const loopback = url2.hostname === "localhost" || url2.hostname === "[::1]" || /^127(?:\.\d{1,3}){3}$/.test(url2.hostname);
|
|
78283
|
+
if (url2.protocol !== "https:" && !(url2.protocol === "http:" && loopback) || url2.username || url2.password || url2.hash) {
|
|
78284
|
+
throw new OAuthError2(
|
|
78285
|
+
"OAuth URLs require HTTPS (HTTP is allowed only on loopback)",
|
|
78286
|
+
"INSECURE_OAUTH_URL"
|
|
78287
|
+
);
|
|
78288
|
+
}
|
|
78289
|
+
return url2;
|
|
78290
|
+
}
|
|
78291
|
+
async function oauthFetch(value, init = {}) {
|
|
78292
|
+
const url2 = validateOAuthUrl(value);
|
|
78293
|
+
const headers = new Headers(
|
|
78294
|
+
url2.origin === new URL(CONFIG.WP_API_URL).origin ? getCustomHeaders() : {}
|
|
78295
|
+
);
|
|
78296
|
+
new Headers(init.headers).forEach((value2, key) => headers.set(key, value2));
|
|
78297
|
+
const response = await proxyFetch(url2.toString(), {
|
|
78298
|
+
...init,
|
|
78299
|
+
headers,
|
|
78300
|
+
redirect: "error",
|
|
78301
|
+
signal: init.signal ?? AbortSignal.timeout(CONFIG.OAUTH_TIMEOUT)
|
|
78302
|
+
});
|
|
78303
|
+
if (response.status >= 300 && response.status < 400)
|
|
78304
|
+
throw new OAuthError2("OAuth endpoint redirects are not accepted", "OAUTH_REDIRECT");
|
|
78305
|
+
return response;
|
|
78306
|
+
}
|
|
78307
|
+
|
|
78308
|
+
// src/lib/mcp-oauth-utils.ts
|
|
78145
78309
|
function generatePKCE() {
|
|
78146
78310
|
const codeVerifier = crypto4.randomBytes(64).toString("base64url").substring(0, 128);
|
|
78147
78311
|
const codeChallenge = crypto4.createHash("sha256").update(codeVerifier).digest("base64url");
|
|
@@ -78169,118 +78333,99 @@ function generateCanonicalResourceURI(serverUrl) {
|
|
|
78169
78333
|
}
|
|
78170
78334
|
}
|
|
78171
78335
|
async function discoverAuthorizationServerMetadata2(authorizationServerUrl) {
|
|
78172
|
-
|
|
78173
|
-
|
|
78174
|
-
|
|
78175
|
-
const
|
|
78176
|
-
|
|
78177
|
-
|
|
78178
|
-
Accept: "application/json",
|
|
78179
|
-
...customHeaders
|
|
78180
|
-
}
|
|
78181
|
-
});
|
|
78182
|
-
if (!response.ok) {
|
|
78336
|
+
const issuer = validateOAuthUrl(authorizationServerUrl);
|
|
78337
|
+
if (issuer.search) throw new OAuthError2("Issuer must not contain a query", "INVALID_METADATA");
|
|
78338
|
+
for (const { url: url2 } of buildDiscoveryUrls(issuer)) {
|
|
78339
|
+
const response = await oauthFetch(url2.toString(), { headers: { Accept: "application/json" } });
|
|
78340
|
+
if ([404, 405].includes(response.status)) continue;
|
|
78341
|
+
if (!response.ok)
|
|
78183
78342
|
throw new OAuthError2(
|
|
78184
|
-
`
|
|
78343
|
+
`Metadata request failed (${response.status})`,
|
|
78185
78344
|
"METADATA_DISCOVERY_FAILED"
|
|
78186
78345
|
);
|
|
78187
|
-
|
|
78188
|
-
|
|
78189
|
-
if (!metadata.authorization_endpoint || !metadata.token_endpoint) {
|
|
78346
|
+
const parsed = OAuthMetadataSchema.safeParse(await response.json());
|
|
78347
|
+
if (!parsed.success || parsed.data.issuer !== authorizationServerUrl) {
|
|
78190
78348
|
throw new OAuthError2(
|
|
78191
|
-
"Authorization
|
|
78349
|
+
"Authorization metadata has an invalid or mismatched issuer",
|
|
78192
78350
|
"INVALID_METADATA"
|
|
78193
78351
|
);
|
|
78194
78352
|
}
|
|
78195
|
-
|
|
78353
|
+
const metadata = parsed.data;
|
|
78354
|
+
validateOAuthUrl(metadata.issuer);
|
|
78355
|
+
validateOAuthUrl(metadata.authorization_endpoint);
|
|
78356
|
+
validateOAuthUrl(metadata.token_endpoint);
|
|
78357
|
+
if (metadata.registration_endpoint) validateOAuthUrl(metadata.registration_endpoint);
|
|
78196
78358
|
return metadata;
|
|
78197
|
-
} catch (error51) {
|
|
78198
|
-
if (error51 instanceof OAuthError2) {
|
|
78199
|
-
throw error51;
|
|
78200
|
-
}
|
|
78201
|
-
throw new OAuthError2(
|
|
78202
|
-
`Error discovering authorization server metadata: ${error51 instanceof Error ? error51.message : String(error51)}`,
|
|
78203
|
-
"METADATA_DISCOVERY_ERROR"
|
|
78204
|
-
);
|
|
78205
78359
|
}
|
|
78360
|
+
throw new OAuthError2("No authorization server metadata found", "METADATA_DISCOVERY_FAILED");
|
|
78206
78361
|
}
|
|
78207
|
-
async function discoverProtectedResourceMetadata(resourceUrl) {
|
|
78208
|
-
|
|
78209
|
-
|
|
78210
|
-
|
|
78211
|
-
|
|
78212
|
-
|
|
78213
|
-
|
|
78214
|
-
headers: {
|
|
78215
|
-
Accept: "application/json",
|
|
78216
|
-
...customHeaders
|
|
78362
|
+
async function discoverProtectedResourceMetadata(resourceUrl, resourceMetadataUrl) {
|
|
78363
|
+
const resource = validateOAuthUrl(resourceUrl);
|
|
78364
|
+
const candidates = resourceMetadataUrl ? [{ url: resourceMetadataUrl, expected: resourceUrl }] : [
|
|
78365
|
+
...resource.pathname !== "/" ? [
|
|
78366
|
+
{
|
|
78367
|
+
url: `${resource.origin}/.well-known/oauth-protected-resource${resource.pathname}`,
|
|
78368
|
+
expected: resourceUrl
|
|
78217
78369
|
}
|
|
78218
|
-
|
|
78219
|
-
|
|
78370
|
+
] : [],
|
|
78371
|
+
{
|
|
78372
|
+
url: `${resource.origin}/.well-known/oauth-protected-resource`,
|
|
78373
|
+
expected: resource.pathname === "/" ? resourceUrl : resource.origin
|
|
78374
|
+
}
|
|
78375
|
+
];
|
|
78376
|
+
for (const candidate of candidates) {
|
|
78377
|
+
const response = await oauthFetch(candidate.url, { headers: { Accept: "application/json" } });
|
|
78378
|
+
if (!resourceMetadataUrl && [404, 405].includes(response.status)) continue;
|
|
78379
|
+
if (!response.ok)
|
|
78220
78380
|
throw new OAuthError2(
|
|
78221
|
-
`
|
|
78381
|
+
`Resource metadata request failed (${response.status})`,
|
|
78222
78382
|
"RESOURCE_METADATA_DISCOVERY_FAILED"
|
|
78223
78383
|
);
|
|
78224
|
-
|
|
78225
|
-
|
|
78226
|
-
if (!metadata.authorization_servers || metadata.authorization_servers.length === 0) {
|
|
78384
|
+
const parsed = OAuthProtectedResourceMetadataSchema.safeParse(await response.json());
|
|
78385
|
+
if (!parsed.success || parsed.data.resource !== candidate.expected || !parsed.data.authorization_servers?.length) {
|
|
78227
78386
|
throw new OAuthError2(
|
|
78228
|
-
"Protected resource metadata
|
|
78387
|
+
"Protected resource metadata has an invalid or mismatched resource",
|
|
78229
78388
|
"INVALID_RESOURCE_METADATA"
|
|
78230
78389
|
);
|
|
78231
78390
|
}
|
|
78232
|
-
|
|
78233
|
-
return
|
|
78234
|
-
} catch (error51) {
|
|
78235
|
-
if (error51 instanceof OAuthError2) {
|
|
78236
|
-
throw error51;
|
|
78237
|
-
}
|
|
78238
|
-
throw new OAuthError2(
|
|
78239
|
-
`Error discovering protected resource metadata: ${error51 instanceof Error ? error51.message : String(error51)}`,
|
|
78240
|
-
"RESOURCE_METADATA_DISCOVERY_ERROR"
|
|
78241
|
-
);
|
|
78391
|
+
for (const issuer of parsed.data.authorization_servers) validateOAuthUrl(issuer);
|
|
78392
|
+
return parsed.data;
|
|
78242
78393
|
}
|
|
78394
|
+
throw new OAuthError2(
|
|
78395
|
+
"No protected resource metadata found",
|
|
78396
|
+
"RESOURCE_METADATA_DISCOVERY_FAILED"
|
|
78397
|
+
);
|
|
78243
78398
|
}
|
|
78244
78399
|
function parseWWWAuthenticateHeader(headerValue2) {
|
|
78245
|
-
const
|
|
78246
|
-
const
|
|
78247
|
-
|
|
78248
|
-
const
|
|
78249
|
-
const
|
|
78250
|
-
|
|
78251
|
-
|
|
78252
|
-
|
|
78253
|
-
|
|
78254
|
-
|
|
78255
|
-
|
|
78256
|
-
|
|
78257
|
-
|
|
78258
|
-
|
|
78259
|
-
|
|
78260
|
-
|
|
78261
|
-
|
|
78262
|
-
|
|
78263
|
-
|
|
78264
|
-
break;
|
|
78265
|
-
case "error_uri":
|
|
78266
|
-
result.error_uri = value;
|
|
78267
|
-
break;
|
|
78268
|
-
case "resource_metadata_url":
|
|
78269
|
-
result.resource_metadata_url = value;
|
|
78270
|
-
break;
|
|
78271
|
-
}
|
|
78400
|
+
const bearer = /(?:^|,)\s*Bearer(?:\s+|$)/i.exec(headerValue2);
|
|
78401
|
+
const result = { scheme: bearer ? "Bearer" : headerValue2.split(/\s+/)[0] };
|
|
78402
|
+
if (!bearer) return result;
|
|
78403
|
+
const parameters = headerValue2.slice(bearer.index + bearer[0].length).split(/,\s*(?=[A-Za-z][\w-]*\s+(?![=]))/)[0];
|
|
78404
|
+
const known = /* @__PURE__ */ new Set([
|
|
78405
|
+
"realm",
|
|
78406
|
+
"scope",
|
|
78407
|
+
"error",
|
|
78408
|
+
"error_description",
|
|
78409
|
+
"error_uri",
|
|
78410
|
+
"resource_metadata"
|
|
78411
|
+
]);
|
|
78412
|
+
for (const match of parameters.matchAll(/([\w-]+)\s*=\s*(?:"((?:[^"\\]|\\.)*)"|([^,\s]+))/g)) {
|
|
78413
|
+
const key = match[1].toLowerCase();
|
|
78414
|
+
if (known.has(key))
|
|
78415
|
+
result[key] = (match[2] ?? match[3]).replace(
|
|
78416
|
+
/\\(.)/g,
|
|
78417
|
+
"$1"
|
|
78418
|
+
);
|
|
78272
78419
|
}
|
|
78273
78420
|
return result;
|
|
78274
78421
|
}
|
|
78275
78422
|
async function registerDynamicClient(registrationEndpoint, registrationRequest) {
|
|
78276
78423
|
try {
|
|
78277
78424
|
logger.oauth(`Attempting dynamic client registration: ${registrationEndpoint}`);
|
|
78278
|
-
const
|
|
78279
|
-
const response = await proxyFetch(registrationEndpoint, {
|
|
78425
|
+
const response = await oauthFetch(registrationEndpoint, {
|
|
78280
78426
|
method: "POST",
|
|
78281
78427
|
headers: {
|
|
78282
|
-
"Content-Type": "application/json"
|
|
78283
|
-
...customHeaders
|
|
78428
|
+
"Content-Type": "application/json"
|
|
78284
78429
|
},
|
|
78285
78430
|
body: JSON.stringify(registrationRequest)
|
|
78286
78431
|
});
|
|
@@ -78292,12 +78437,26 @@ async function registerDynamicClient(registrationEndpoint, registrationRequest)
|
|
|
78292
78437
|
);
|
|
78293
78438
|
}
|
|
78294
78439
|
const registrationResponse = await response.json();
|
|
78295
|
-
if (!registrationResponse.client_id) {
|
|
78440
|
+
if (typeof registrationResponse.client_id !== "string" || !registrationResponse.client_id) {
|
|
78296
78441
|
throw new OAuthError2(
|
|
78297
78442
|
"Dynamic client registration response missing client_id",
|
|
78298
78443
|
"INVALID_REGISTRATION_RESPONSE"
|
|
78299
78444
|
);
|
|
78300
78445
|
}
|
|
78446
|
+
if (registrationResponse.token_endpoint_auth_method && registrationResponse.token_endpoint_auth_method !== registrationRequest.token_endpoint_auth_method) {
|
|
78447
|
+
throw new OAuthError2(
|
|
78448
|
+
"Authorization server changed the requested client authentication method",
|
|
78449
|
+
"INVALID_REGISTRATION_RESPONSE"
|
|
78450
|
+
);
|
|
78451
|
+
}
|
|
78452
|
+
if (registrationResponse.redirect_uris && (!Array.isArray(registrationResponse.redirect_uris) || !registrationRequest.redirect_uris.every(
|
|
78453
|
+
(uri) => registrationResponse.redirect_uris.includes(uri)
|
|
78454
|
+
))) {
|
|
78455
|
+
throw new OAuthError2(
|
|
78456
|
+
"Authorization server changed the registered callback URI",
|
|
78457
|
+
"INVALID_REGISTRATION_RESPONSE"
|
|
78458
|
+
);
|
|
78459
|
+
}
|
|
78301
78460
|
logger.oauth("Dynamic client registration successful");
|
|
78302
78461
|
logger.debug("Client ID obtained", "OAUTH", {
|
|
78303
78462
|
client_id: registrationResponse.client_id,
|
|
@@ -78327,12 +78486,10 @@ async function exchangeAuthorizationCode(tokenEndpoint, code, redirectUri, clien
|
|
|
78327
78486
|
if (resource) {
|
|
78328
78487
|
params.set("resource", resource);
|
|
78329
78488
|
}
|
|
78330
|
-
const
|
|
78331
|
-
const response = await proxyFetch(tokenEndpoint, {
|
|
78489
|
+
const response = await oauthFetch(tokenEndpoint, {
|
|
78332
78490
|
method: "POST",
|
|
78333
78491
|
headers: {
|
|
78334
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
78335
|
-
...customHeaders
|
|
78492
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
78336
78493
|
},
|
|
78337
78494
|
body: params.toString()
|
|
78338
78495
|
});
|
|
@@ -78343,7 +78500,9 @@ async function exchangeAuthorizationCode(tokenEndpoint, code, redirectUri, clien
|
|
|
78343
78500
|
"TOKEN_EXCHANGE_FAILED"
|
|
78344
78501
|
);
|
|
78345
78502
|
}
|
|
78346
|
-
const tokenResponse = await response.json();
|
|
78503
|
+
const tokenResponse = OAuthTokensSchema.parse(await response.json());
|
|
78504
|
+
if (tokenResponse.token_type.toLowerCase() !== "bearer")
|
|
78505
|
+
throw new OAuthError2("Unsupported token type", "INVALID_TOKEN_RESPONSE");
|
|
78347
78506
|
if (!tokenResponse.access_token) {
|
|
78348
78507
|
throw new OAuthError2("Token response missing access_token", "INVALID_TOKEN_RESPONSE");
|
|
78349
78508
|
}
|
|
@@ -78372,15 +78531,18 @@ function buildAuthorizationUrl(authorizationEndpoint, clientId, redirectUri, sco
|
|
|
78372
78531
|
// OAuth 2.1 uses authorization code flow
|
|
78373
78532
|
client_id: clientId,
|
|
78374
78533
|
redirect_uri: redirectUri,
|
|
78375
|
-
scope: scopes.join(" "),
|
|
78376
78534
|
state,
|
|
78377
78535
|
code_challenge: codeChallenge,
|
|
78378
78536
|
code_challenge_method: "S256"
|
|
78379
78537
|
});
|
|
78538
|
+
if (scopes.length) params.set("scope", scopes.join(" "));
|
|
78380
78539
|
if (resource) {
|
|
78381
78540
|
params.set("resource", resource);
|
|
78382
78541
|
}
|
|
78383
|
-
|
|
78542
|
+
validateOAuthUrl(authorizationEndpoint);
|
|
78543
|
+
const url2 = new URL(authorizationEndpoint);
|
|
78544
|
+
params.forEach((value, key) => url2.searchParams.set(key, value));
|
|
78545
|
+
return url2.toString();
|
|
78384
78546
|
}
|
|
78385
78547
|
function generateSecureState() {
|
|
78386
78548
|
return crypto4.randomBytes(32).toString("base64url");
|
|
@@ -78461,110 +78623,26 @@ var AUTHORIZATION_CODE_HTML = `
|
|
|
78461
78623
|
</div>
|
|
78462
78624
|
|
|
78463
78625
|
<script>
|
|
78464
|
-
|
|
78465
|
-
|
|
78466
|
-
|
|
78467
|
-
|
|
78468
|
-
|
|
78469
|
-
|
|
78470
|
-
|
|
78471
|
-
|
|
78472
|
-
|
|
78473
|
-
|
|
78474
|
-
|
|
78475
|
-
|
|
78476
|
-
|
|
78477
|
-
|
|
78478
|
-
|
|
78479
|
-
|
|
78480
|
-
|
|
78481
|
-
|
|
78482
|
-
|
|
78483
|
-
|
|
78484
|
-
// Check for authorization code first (OAuth 2.1 flow)
|
|
78485
|
-
if (urlParams.has('code')) {
|
|
78486
|
-
const authData = {
|
|
78487
|
-
code: urlParams.get('code'),
|
|
78488
|
-
state: urlParams.get('state'),
|
|
78489
|
-
// Additional parameters for validation
|
|
78490
|
-
iss: urlParams.get('iss'),
|
|
78491
|
-
};
|
|
78492
|
-
|
|
78493
|
-
// Send authorization code to server for token exchange
|
|
78494
|
-
fetch('/oauth/callback', {
|
|
78495
|
-
method: 'POST',
|
|
78496
|
-
headers: {
|
|
78497
|
-
'Content-Type': 'application/json'
|
|
78498
|
-
},
|
|
78499
|
-
body: JSON.stringify(authData)
|
|
78500
|
-
})
|
|
78501
|
-
.then(response => {
|
|
78502
|
-
if (response.ok) {
|
|
78503
|
-
displayStatus('\u2705 Authorization successful!', 'success');
|
|
78504
|
-
displayDetails('You can safely close this window.');
|
|
78505
|
-
} else {
|
|
78506
|
-
return response.json().then(err => {
|
|
78507
|
-
throw new Error(err.error || 'Failed to exchange authorization code');
|
|
78508
|
-
});
|
|
78509
|
-
}
|
|
78510
|
-
})
|
|
78511
|
-
.catch(error => {
|
|
78512
|
-
displayStatus('\u274C Error completing authorization', 'error');
|
|
78513
|
-
displayDetails(error.message + '. Please try again.');
|
|
78514
|
-
});
|
|
78515
|
-
}
|
|
78516
|
-
// Check for access token in URL fragment (implicit flow)
|
|
78517
|
-
else if (hashParams.has('access_token')) {
|
|
78518
|
-
const tokens = {
|
|
78519
|
-
access_token: hashParams.get('access_token'),
|
|
78520
|
-
token_type: hashParams.get('token_type') || 'Bearer',
|
|
78521
|
-
expires_in: hashParams.get('expires_in') ? parseInt(hashParams.get('expires_in')) : 3600,
|
|
78522
|
-
scope: hashParams.get('scope'),
|
|
78523
|
-
state: hashParams.get('state'),
|
|
78524
|
-
obtained_at: Date.now()
|
|
78525
|
-
};
|
|
78526
|
-
|
|
78527
|
-
// Send tokens to server for storage
|
|
78528
|
-
fetch('/oauth/tokens', {
|
|
78529
|
-
method: 'POST',
|
|
78530
|
-
headers: {
|
|
78531
|
-
'Content-Type': 'application/json'
|
|
78532
|
-
},
|
|
78533
|
-
body: JSON.stringify(tokens)
|
|
78534
|
-
})
|
|
78535
|
-
.then(response => {
|
|
78536
|
-
if (response.ok) {
|
|
78537
|
-
displayStatus('\u2705 Authorization successful!', 'success');
|
|
78538
|
-
displayDetails('You can safely close this window.');
|
|
78539
|
-
} else {
|
|
78540
|
-
return response.json().then(err => {
|
|
78541
|
-
throw new Error(err.error || 'Failed to store access token');
|
|
78542
|
-
});
|
|
78543
|
-
}
|
|
78544
|
-
})
|
|
78545
|
-
.catch(error => {
|
|
78546
|
-
displayStatus('\u274C Error completing authorization', 'error');
|
|
78547
|
-
displayDetails(error.message + '. Please try again.');
|
|
78548
|
-
});
|
|
78549
|
-
}
|
|
78550
|
-
// Check for errors in query parameters
|
|
78551
|
-
else if (urlParams.has('error')) {
|
|
78552
|
-
const error = urlParams.get('error');
|
|
78553
|
-
const errorDescription = urlParams.get('error_description');
|
|
78554
|
-
displayStatus('\u274C Authorization failed', 'error');
|
|
78555
|
-
displayDetails(\`Error: \${error}\${errorDescription ? ' - ' + errorDescription : ''}\`);
|
|
78556
|
-
}
|
|
78557
|
-
// Check for errors in URL fragment (implicit flow errors)
|
|
78558
|
-
else if (hashParams.has('error')) {
|
|
78559
|
-
const error = hashParams.get('error');
|
|
78560
|
-
const errorDescription = hashParams.get('error_description');
|
|
78561
|
-
displayStatus('\u274C Authorization failed', 'error');
|
|
78562
|
-
displayDetails(\`Error: \${error}\${errorDescription ? ' - ' + errorDescription : ''}\`);
|
|
78563
|
-
}
|
|
78564
|
-
// No authorization code or access token found
|
|
78565
|
-
else {
|
|
78566
|
-
displayStatus('\u274C No authorization code or access token received', 'error');
|
|
78567
|
-
displayDetails('Please try the authorization process again.');
|
|
78626
|
+
const query = new URLSearchParams(window.location.search);
|
|
78627
|
+
const fragment = new URLSearchParams(window.location.hash.substring(1));
|
|
78628
|
+
const status = document.getElementById('status');
|
|
78629
|
+
const details = document.getElementById('details');
|
|
78630
|
+
const data = Object.fromEntries(query.has('code') || query.has('error') ? query : fragment);
|
|
78631
|
+
const endpoint = data.access_token ? '/oauth/tokens' : '/oauth/callback';
|
|
78632
|
+
if (data.code || data.error || data.access_token) {
|
|
78633
|
+
fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) })
|
|
78634
|
+
.then(async response => {
|
|
78635
|
+
const result = await response.json();
|
|
78636
|
+
if (!response.ok) throw new Error(result.error || 'Authorization response was rejected');
|
|
78637
|
+
status.textContent = data.access_token ? 'Authorization successful' : 'Authorization code received';
|
|
78638
|
+
status.className = 'success';
|
|
78639
|
+
details.textContent = data.access_token ? 'You can close this window.' : 'Return to your app to check the connection. Token exchange may still fail.';
|
|
78640
|
+
})
|
|
78641
|
+
.catch(error => { status.textContent = 'Authorization failed'; status.className = 'error'; details.textContent = error.message; })
|
|
78642
|
+
.finally(() => { document.getElementById('spinner').style.display = 'none'; });
|
|
78643
|
+
} else {
|
|
78644
|
+
status.textContent = 'No authorization response received';
|
|
78645
|
+
document.getElementById('spinner').style.display = 'none';
|
|
78568
78646
|
}
|
|
78569
78647
|
</script>
|
|
78570
78648
|
</body>
|
|
@@ -78579,6 +78657,17 @@ var OAuthCallbackServer = class {
|
|
|
78579
78657
|
this.setupRoutes();
|
|
78580
78658
|
}
|
|
78581
78659
|
setupRoutes() {
|
|
78660
|
+
this.app.use((req, res, next) => {
|
|
78661
|
+
const host = this.options.host === "::1" ? "[::1]" : this.options.host;
|
|
78662
|
+
const origin = req.headers.origin;
|
|
78663
|
+
const port = this.server?.address();
|
|
78664
|
+
const expectedOrigin = `http://${host}:${port && typeof port !== "string" ? port.port : this.options.port}`;
|
|
78665
|
+
if (req.hostname !== host || origin && origin !== expectedOrigin) {
|
|
78666
|
+
res.status(403).json({ error: "Untrusted callback origin" });
|
|
78667
|
+
return;
|
|
78668
|
+
}
|
|
78669
|
+
next();
|
|
78670
|
+
});
|
|
78582
78671
|
this.app.use(import_express.default.json());
|
|
78583
78672
|
this.app.get("/oauth/callback", (req, res) => {
|
|
78584
78673
|
logger.oauth("OAuth 2.1 authorization callback page requested");
|
|
@@ -78586,46 +78675,47 @@ var OAuthCallbackServer = class {
|
|
|
78586
78675
|
});
|
|
78587
78676
|
this.app.post("/oauth/callback", async (req, res) => {
|
|
78588
78677
|
try {
|
|
78589
|
-
const { code, state, iss } = req.body;
|
|
78590
|
-
|
|
78591
|
-
|
|
78592
|
-
|
|
78593
|
-
|
|
78594
|
-
|
|
78595
|
-
|
|
78596
|
-
state: state || "none",
|
|
78597
|
-
issuer: iss || "none"
|
|
78598
|
-
});
|
|
78678
|
+
const { code, state, iss, error: error51 } = req.body;
|
|
78679
|
+
this.validateResponse(state, iss);
|
|
78680
|
+
if (error51) throw new OAuthError2("Authorization denied or failed", "AUTH_DENIED");
|
|
78681
|
+
if (this.options.flow === "implicit")
|
|
78682
|
+
throw new OAuthError2("Authorization-code callback is disabled", "WRONG_FLOW");
|
|
78683
|
+
if (typeof code !== "string" || !code)
|
|
78684
|
+
throw new OAuthError2("No authorization code received", "INVALID_CODE");
|
|
78599
78685
|
this.events.emit("oauth-code-received", { code, state, iss });
|
|
78600
|
-
res.json({
|
|
78686
|
+
res.json({
|
|
78687
|
+
success: true,
|
|
78688
|
+
message: "Authorization code received; check connection status in the app"
|
|
78689
|
+
});
|
|
78601
78690
|
} catch (error51) {
|
|
78602
|
-
|
|
78603
|
-
|
|
78604
|
-
|
|
78605
|
-
res.status(400).json({ error: errorMessage });
|
|
78691
|
+
const failure = error51 instanceof OAuthError2 ? error51 : new OAuthError2("Invalid authorization response");
|
|
78692
|
+
if (failure.code !== "INVALID_STATE") this.events.emit("oauth-error", failure);
|
|
78693
|
+
res.status(400).json({ error: failure.message });
|
|
78606
78694
|
}
|
|
78607
78695
|
});
|
|
78608
78696
|
this.app.post("/oauth/tokens", async (req, res) => {
|
|
78697
|
+
if (this.options.flow !== "implicit") {
|
|
78698
|
+
res.status(404).json({ error: "Implicit token callback is disabled" });
|
|
78699
|
+
return;
|
|
78700
|
+
}
|
|
78609
78701
|
try {
|
|
78610
|
-
|
|
78611
|
-
if (!
|
|
78612
|
-
throw new OAuthError2("
|
|
78613
|
-
|
|
78614
|
-
|
|
78615
|
-
|
|
78616
|
-
|
|
78617
|
-
|
|
78618
|
-
|
|
78619
|
-
|
|
78620
|
-
});
|
|
78702
|
+
this.validateResponse(req.body.state, req.body.iss);
|
|
78703
|
+
if (typeof req.body.access_token !== "string" || !req.body.access_token || req.body.token_type && req.body.token_type.toLowerCase() !== "bearer")
|
|
78704
|
+
throw new OAuthError2("Invalid implicit token response");
|
|
78705
|
+
const tokens = {
|
|
78706
|
+
access_token: req.body.access_token,
|
|
78707
|
+
token_type: "Bearer",
|
|
78708
|
+
expires_in: req.body.expires_in === void 0 ? void 0 : Number(req.body.expires_in),
|
|
78709
|
+
scope: req.body.scope,
|
|
78710
|
+
obtained_at: Date.now()
|
|
78711
|
+
};
|
|
78621
78712
|
await writeTokens(this.options.serverUrlHash, tokens);
|
|
78622
78713
|
this.events.emit("oauth-success", tokens);
|
|
78623
|
-
res.json({ success: true
|
|
78714
|
+
res.json({ success: true });
|
|
78624
78715
|
} catch (error51) {
|
|
78625
|
-
|
|
78626
|
-
|
|
78627
|
-
|
|
78628
|
-
res.status(400).json({ error: errorMessage });
|
|
78716
|
+
const failure = error51 instanceof OAuthError2 ? error51 : new OAuthError2("Invalid implicit response");
|
|
78717
|
+
if (failure.code !== "INVALID_STATE") this.events.emit("oauth-error", failure);
|
|
78718
|
+
res.status(400).json({ error: failure.message });
|
|
78629
78719
|
}
|
|
78630
78720
|
});
|
|
78631
78721
|
this.app.get("/oauth/health", (req, res) => {
|
|
@@ -78642,21 +78732,33 @@ var OAuthCallbackServer = class {
|
|
|
78642
78732
|
}
|
|
78643
78733
|
);
|
|
78644
78734
|
}
|
|
78735
|
+
validateResponse(state, issuer) {
|
|
78736
|
+
if (!this.options.state || state !== this.options.state)
|
|
78737
|
+
throw new OAuthError2("Invalid callback state", "INVALID_STATE");
|
|
78738
|
+
if ((issuer !== void 0 || this.options.requireIssuer) && issuer !== this.options.issuer)
|
|
78739
|
+
throw new OAuthError2("Invalid callback issuer", "INVALID_ISSUER");
|
|
78740
|
+
}
|
|
78645
78741
|
async start() {
|
|
78646
78742
|
return new Promise((resolve, reject) => {
|
|
78647
78743
|
try {
|
|
78648
|
-
this.server = this.app.listen(this.options.port, this.options.host, () => {
|
|
78744
|
+
this.server = this.app.listen(this.options.port, this.options.host, (error51) => {
|
|
78745
|
+
clearTimeout(this.startupTimer);
|
|
78746
|
+
if (error51) {
|
|
78747
|
+
reject(error51);
|
|
78748
|
+
return;
|
|
78749
|
+
}
|
|
78649
78750
|
logger.oauth(
|
|
78650
78751
|
`OAuth callback server listening on http://${this.options.host}:${this.options.port}`
|
|
78651
78752
|
);
|
|
78652
78753
|
resolve();
|
|
78653
78754
|
});
|
|
78654
78755
|
this.server.on("error", (error51) => {
|
|
78756
|
+
clearTimeout(this.startupTimer);
|
|
78655
78757
|
logger.error("OAuth callback server error", "OAUTH", error51);
|
|
78656
78758
|
reject(error51);
|
|
78657
78759
|
});
|
|
78658
78760
|
if (this.options.timeout) {
|
|
78659
|
-
setTimeout(() => {
|
|
78761
|
+
this.startupTimer = setTimeout(() => {
|
|
78660
78762
|
if (!this.server?.listening) {
|
|
78661
78763
|
reject(new OAuthError2("OAuth callback server startup timeout", "TIMEOUT"));
|
|
78662
78764
|
}
|
|
@@ -78668,6 +78770,7 @@ var OAuthCallbackServer = class {
|
|
|
78668
78770
|
});
|
|
78669
78771
|
}
|
|
78670
78772
|
async stop() {
|
|
78773
|
+
clearTimeout(this.startupTimer);
|
|
78671
78774
|
if (!this.server) return;
|
|
78672
78775
|
const server = this.server;
|
|
78673
78776
|
this.server = null;
|
|
@@ -78699,7 +78802,9 @@ var MCPOAuthProvider = class {
|
|
|
78699
78802
|
this.authServerMetadata = null;
|
|
78700
78803
|
this.resourceMetadata = null;
|
|
78701
78804
|
const serverUrl = options.serverUrl || CONFIG.WP_API_URL;
|
|
78702
|
-
const defaultScopes = getDefaultOAuthScopes();
|
|
78805
|
+
const defaultScopes = CONFIG.OAUTH_SCOPES ? getDefaultOAuthScopes() : [];
|
|
78806
|
+
this.explicitScopes = options.scopes ?? defaultScopes;
|
|
78807
|
+
this.configuredClientId = options.clientId || CONFIG.WP_OAUTH_CLIENT_ID || void 0;
|
|
78703
78808
|
this.config = {
|
|
78704
78809
|
serverUrl,
|
|
78705
78810
|
resource: generateCanonicalResourceURI(serverUrl),
|
|
@@ -78758,187 +78863,217 @@ var MCPOAuthProvider = class {
|
|
|
78758
78863
|
/**
|
|
78759
78864
|
* Discover OAuth 2.1 server endpoints using MCP-compliant discovery
|
|
78760
78865
|
*/
|
|
78761
|
-
async discoverOAuthEndpoints() {
|
|
78762
|
-
|
|
78763
|
-
|
|
78764
|
-
|
|
78765
|
-
|
|
78766
|
-
|
|
78767
|
-
|
|
78768
|
-
|
|
78769
|
-
|
|
78770
|
-
|
|
78771
|
-
|
|
78772
|
-
|
|
78773
|
-
|
|
78774
|
-
|
|
78775
|
-
|
|
78776
|
-
|
|
78777
|
-
|
|
78778
|
-
|
|
78779
|
-
|
|
78780
|
-
this.config.registrationEndpoint = this.authServerMetadata.registration_endpoint;
|
|
78781
|
-
} else {
|
|
78782
|
-
throw new OAuthError2("Could not determine authorization server URL", "DISCOVERY_FAILED");
|
|
78783
|
-
}
|
|
78784
|
-
} catch (error51) {
|
|
78785
|
-
logger.error("OAuth endpoint discovery failed", "OAUTH", error51);
|
|
78786
|
-
throw error51;
|
|
78787
|
-
}
|
|
78788
|
-
}
|
|
78789
|
-
/**
|
|
78790
|
-
* Discover endpoints via 401 Unauthorized response (RFC 9728 Section 5.1)
|
|
78791
|
-
*/
|
|
78792
|
-
async discoverVia401Response() {
|
|
78793
|
-
try {
|
|
78794
|
-
logger.oauth("Attempting discovery via 401 response method");
|
|
78795
|
-
const customHeaders = getCustomHeaders();
|
|
78796
|
-
const response = await proxyFetch(this.config.serverUrl, {
|
|
78797
|
-
headers: {
|
|
78798
|
-
Accept: "application/json",
|
|
78799
|
-
...customHeaders
|
|
78800
|
-
}
|
|
78801
|
-
});
|
|
78802
|
-
if (response.status === 401) {
|
|
78803
|
-
const wwwAuthHeader = response.headers.get("WWW-Authenticate");
|
|
78804
|
-
if (wwwAuthHeader) {
|
|
78805
|
-
const authInfo = parseWWWAuthenticateHeader(wwwAuthHeader);
|
|
78806
|
-
logger.oauth("WWW-Authenticate header parsed successfully");
|
|
78807
|
-
if (authInfo.resource_metadata_url) {
|
|
78808
|
-
const metadataResponse = await proxyFetch(authInfo.resource_metadata_url, {
|
|
78809
|
-
headers: {
|
|
78810
|
-
Accept: "application/json",
|
|
78811
|
-
...customHeaders
|
|
78812
|
-
}
|
|
78813
|
-
});
|
|
78814
|
-
if (metadataResponse.ok) {
|
|
78815
|
-
this.resourceMetadata = await metadataResponse.json();
|
|
78816
|
-
logger.oauth("Protected resource metadata obtained via 401 response");
|
|
78817
|
-
}
|
|
78818
|
-
}
|
|
78819
|
-
}
|
|
78820
|
-
}
|
|
78821
|
-
} catch (error51) {
|
|
78822
|
-
logger.warn("401 response discovery method failed", "OAUTH", error51);
|
|
78823
|
-
}
|
|
78866
|
+
async discoverOAuthEndpoints(challenge) {
|
|
78867
|
+
this.resourceMetadata = await discoverProtectedResourceMetadata(
|
|
78868
|
+
this.config.serverUrl,
|
|
78869
|
+
challenge?.resource_metadata
|
|
78870
|
+
);
|
|
78871
|
+
this.authServerMetadata = await discoverAuthorizationServerMetadata2(
|
|
78872
|
+
this.resourceMetadata.authorization_servers[0]
|
|
78873
|
+
);
|
|
78874
|
+
this.config.resource = this.resourceMetadata.resource;
|
|
78875
|
+
this.config.authorizationEndpoint = this.authServerMetadata.authorization_endpoint;
|
|
78876
|
+
this.config.tokenEndpoint = this.authServerMetadata.token_endpoint;
|
|
78877
|
+
this.config.registrationEndpoint = this.authServerMetadata.registration_endpoint;
|
|
78878
|
+
this.config.clientId = this.configuredClientId;
|
|
78879
|
+
const challenged = challenge?.scope?.split(/\s+/).filter(Boolean);
|
|
78880
|
+
this.config.scopes = [
|
|
78881
|
+
...new Set(
|
|
78882
|
+
challenged ?? (this.explicitScopes.length ? this.explicitScopes : this.resourceMetadata.scopes_supported ?? [])
|
|
78883
|
+
)
|
|
78884
|
+
];
|
|
78824
78885
|
}
|
|
78825
|
-
/**
|
|
78826
|
-
* Get authorization server URL from discovered metadata
|
|
78827
|
-
*/
|
|
78828
78886
|
getAuthorizationServerUrl() {
|
|
78829
|
-
|
|
78830
|
-
return this.resourceMetadata.authorization_servers[0];
|
|
78831
|
-
}
|
|
78832
|
-
try {
|
|
78833
|
-
const url2 = new URL(this.config.serverUrl);
|
|
78834
|
-
return url2.origin;
|
|
78835
|
-
} catch {
|
|
78836
|
-
return null;
|
|
78837
|
-
}
|
|
78887
|
+
return this.authServerMetadata?.issuer ?? this.resourceMetadata?.authorization_servers[0] ?? new URL(this.config.serverUrl).origin;
|
|
78838
78888
|
}
|
|
78839
78889
|
/**
|
|
78840
78890
|
* Perform dynamic client registration if needed and supported
|
|
78841
78891
|
*/
|
|
78842
78892
|
async ensureClientRegistration() {
|
|
78893
|
+
const issuer = this.getAuthorizationServerUrl();
|
|
78894
|
+
const stored = await readClientInfo(this.serverUrlHash);
|
|
78843
78895
|
if (this.config.clientId) {
|
|
78844
|
-
|
|
78896
|
+
if (stored?.issuer && stored.issuer !== issuer && stored.client_id === this.config.clientId) {
|
|
78897
|
+
throw new OAuthError2(
|
|
78898
|
+
"Configured client belongs to another authorization server; update its registration",
|
|
78899
|
+
"CLIENT_ISSUER_MISMATCH"
|
|
78900
|
+
);
|
|
78901
|
+
}
|
|
78902
|
+
await writeClientInfo(this.serverUrlHash, { client_id: this.config.clientId, issuer });
|
|
78845
78903
|
return;
|
|
78846
78904
|
}
|
|
78847
|
-
|
|
78848
|
-
|
|
78849
|
-
this.config.clientId = storedClientInfo.client_id;
|
|
78850
|
-
logger.oauth("Reusing persisted client registration, skipping dynamic registration");
|
|
78905
|
+
if (stored?.issuer === issuer && typeof stored.client_id === "string" && stored.client_id.length > 0) {
|
|
78906
|
+
this.config.clientId = stored.client_id;
|
|
78851
78907
|
return;
|
|
78852
78908
|
}
|
|
78853
|
-
if (!CONFIG.OAUTH_DYNAMIC_REGISTRATION)
|
|
78909
|
+
if (!CONFIG.OAUTH_DYNAMIC_REGISTRATION)
|
|
78854
78910
|
throw new OAuthError2(
|
|
78855
|
-
"No client
|
|
78911
|
+
"No issuer-bound client registration; configure a client ID or enable registration",
|
|
78856
78912
|
"NO_CLIENT_ID"
|
|
78857
78913
|
);
|
|
78858
|
-
|
|
78859
|
-
if (!this.authServerMetadata?.registration_endpoint) {
|
|
78914
|
+
if (!this.authServerMetadata?.registration_endpoint)
|
|
78860
78915
|
throw new OAuthError2(
|
|
78861
|
-
"
|
|
78916
|
+
"Authorization server does not support dynamic registration; configure its client ID",
|
|
78862
78917
|
"NO_DYNAMIC_REGISTRATION"
|
|
78863
78918
|
);
|
|
78864
|
-
|
|
78865
|
-
|
|
78866
|
-
|
|
78867
|
-
|
|
78868
|
-
|
|
78869
|
-
|
|
78870
|
-
|
|
78871
|
-
|
|
78872
|
-
|
|
78873
|
-
|
|
78874
|
-
|
|
78875
|
-
|
|
78876
|
-
|
|
78877
|
-
|
|
78878
|
-
|
|
78879
|
-
|
|
78880
|
-
|
|
78881
|
-
|
|
78882
|
-
|
|
78883
|
-
};
|
|
78884
|
-
await writeClientInfo(this.serverUrlHash, clientInfo);
|
|
78885
|
-
this.config.clientId = registrationResponse.client_id;
|
|
78886
|
-
logger.oauth("Dynamic client registration completed successfully");
|
|
78887
|
-
} catch (error51) {
|
|
78888
|
-
logger.error("Dynamic client registration failed", "OAUTH", error51);
|
|
78889
|
-
throw error51;
|
|
78890
|
-
}
|
|
78919
|
+
const request = {
|
|
78920
|
+
redirect_uris: [this.config.redirectUri],
|
|
78921
|
+
application_type: "native",
|
|
78922
|
+
token_endpoint_auth_method: "none",
|
|
78923
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
78924
|
+
response_types: ["code"],
|
|
78925
|
+
client_name: "WordPress MCP Remote",
|
|
78926
|
+
...this.config.scopes.length ? { scope: this.config.scopes.join(" ") } : {}
|
|
78927
|
+
};
|
|
78928
|
+
const registered = await registerDynamicClient(
|
|
78929
|
+
this.authServerMetadata.registration_endpoint,
|
|
78930
|
+
request
|
|
78931
|
+
);
|
|
78932
|
+
await writeClientInfo(this.serverUrlHash, {
|
|
78933
|
+
...request,
|
|
78934
|
+
client_id: registered.client_id,
|
|
78935
|
+
issuer
|
|
78936
|
+
});
|
|
78937
|
+
this.config.clientId = registered.client_id;
|
|
78891
78938
|
}
|
|
78892
78939
|
/**
|
|
78893
78940
|
* Initiate MCP-compliant OAuth 2.1 authorization flow
|
|
78894
78941
|
*/
|
|
78895
|
-
|
|
78896
|
-
|
|
78897
|
-
|
|
78898
|
-
|
|
78899
|
-
|
|
78900
|
-
|
|
78901
|
-
const
|
|
78902
|
-
|
|
78903
|
-
|
|
78904
|
-
|
|
78942
|
+
satisfies(tokens, request) {
|
|
78943
|
+
return !!tokens && tokens.access_token !== request.rejectedToken && (!request.scopes?.length || request.scopes.every((scope) => tokens.scope?.split(" ").includes(scope)));
|
|
78944
|
+
}
|
|
78945
|
+
async authorize(request = {}) {
|
|
78946
|
+
if (this.authPromise) await this.authPromise;
|
|
78947
|
+
if (!this.authPromise) this.authPromise = this.authorizeWithLock(request);
|
|
78948
|
+
const pending = this.authPromise;
|
|
78949
|
+
try {
|
|
78950
|
+
await pending;
|
|
78951
|
+
} finally {
|
|
78952
|
+
if (this.authPromise === pending) this.authPromise = null;
|
|
78905
78953
|
}
|
|
78906
|
-
|
|
78907
|
-
|
|
78954
|
+
}
|
|
78955
|
+
async authorizeWithLock(request) {
|
|
78956
|
+
const valid = await this.tokens();
|
|
78957
|
+
if (this.satisfies(valid, request)) return valid;
|
|
78958
|
+
await ensureConfigDir();
|
|
78959
|
+
const file2 = getConfigFilePath(this.serverUrlHash, "oauth");
|
|
78960
|
+
let release;
|
|
78908
78961
|
try {
|
|
78909
|
-
await
|
|
78910
|
-
logger.oauth("OAuth 2.1 authorization completed successfully");
|
|
78962
|
+
release = await lockfile.lock(file2, { realpath: false });
|
|
78911
78963
|
} catch (error51) {
|
|
78912
|
-
|
|
78913
|
-
|
|
78964
|
+
if (error51.code !== "ELOCKED") throw error51;
|
|
78965
|
+
const deadline = Date.now() + this.config.timeout;
|
|
78966
|
+
while (Date.now() < deadline) {
|
|
78967
|
+
const tokens = await this.tokens();
|
|
78968
|
+
if (this.satisfies(tokens, request)) return tokens;
|
|
78969
|
+
if (!await lockfile.check(file2, { realpath: false })) {
|
|
78970
|
+
const completed = await this.tokens();
|
|
78971
|
+
if (this.satisfies(completed, request)) return completed;
|
|
78972
|
+
throw new OAuthError2("Authentication in another process did not complete", "AUTH_FAILED");
|
|
78973
|
+
}
|
|
78974
|
+
await delay(Math.min(100, Math.max(0, deadline - Date.now())));
|
|
78975
|
+
}
|
|
78976
|
+
throw new OAuthError2("Timeout waiting for authentication in another process", "LOCK_TIMEOUT");
|
|
78977
|
+
}
|
|
78978
|
+
try {
|
|
78979
|
+
const completed = await this.tokens();
|
|
78980
|
+
if (this.satisfies(completed, request)) return completed;
|
|
78981
|
+
await this.discoverOAuthEndpoints(request.challenge);
|
|
78982
|
+
const issuer = this.getAuthorizationServerUrl();
|
|
78983
|
+
const stored = await readTokens(this.serverUrlHash);
|
|
78984
|
+
const client = await readClientInfo(this.serverUrlHash);
|
|
78985
|
+
if (this.configuredClientId && client?.issuer && client.issuer !== issuer && client.client_id === this.configuredClientId) {
|
|
78986
|
+
throw new OAuthError2(
|
|
78987
|
+
"Configured client belongs to another authorization server",
|
|
78988
|
+
"CLIENT_ISSUER_MISMATCH"
|
|
78989
|
+
);
|
|
78990
|
+
}
|
|
78991
|
+
this.config.scopes = [
|
|
78992
|
+
.../* @__PURE__ */ new Set([
|
|
78993
|
+
...stored?.issuer === issuer ? stored.scope?.split(" ").filter(Boolean) ?? [] : [],
|
|
78994
|
+
...this.config.scopes,
|
|
78995
|
+
...request.scopes ?? []
|
|
78996
|
+
])
|
|
78997
|
+
];
|
|
78998
|
+
const needsScope = !!request.scopes?.some(
|
|
78999
|
+
(scope) => !stored?.scope?.split(" ").includes(scope)
|
|
79000
|
+
);
|
|
79001
|
+
const clientId = this.configuredClientId || client?.client_id;
|
|
79002
|
+
if (stored?.issuer === issuer && client?.issuer === issuer && stored.refresh_token && clientId && (!this.configuredClientId || this.configuredClientId === client.client_id) && !needsScope) {
|
|
79003
|
+
try {
|
|
79004
|
+
const renewed = await refreshAuthorization(issuer, {
|
|
79005
|
+
metadata: { ...this.authServerMetadata },
|
|
79006
|
+
clientInformation: { client_id: clientId },
|
|
79007
|
+
refreshToken: stored.refresh_token,
|
|
79008
|
+
resource: this.resourceIndicator(),
|
|
79009
|
+
fetchFn: (url2, init) => oauthFetch(String(url2), init)
|
|
79010
|
+
});
|
|
79011
|
+
if (renewed.token_type.toLowerCase() !== "bearer")
|
|
79012
|
+
throw new OAuthError2("Unsupported token type", "INVALID_TOKEN_RESPONSE");
|
|
79013
|
+
const tokens = {
|
|
79014
|
+
...renewed,
|
|
79015
|
+
issuer,
|
|
79016
|
+
scope: renewed.scope ?? stored.scope,
|
|
79017
|
+
obtained_at: Date.now()
|
|
79018
|
+
};
|
|
79019
|
+
await writeTokens(this.serverUrlHash, tokens);
|
|
79020
|
+
return tokens;
|
|
79021
|
+
} catch (error51) {
|
|
79022
|
+
if (!(error51 instanceof InvalidGrantError)) throw error51;
|
|
79023
|
+
await deleteConfigFile(this.serverUrlHash, "tokens.json");
|
|
79024
|
+
}
|
|
79025
|
+
}
|
|
79026
|
+
return await this.performAuthorization();
|
|
78914
79027
|
} finally {
|
|
78915
|
-
|
|
79028
|
+
await release();
|
|
78916
79029
|
}
|
|
78917
79030
|
}
|
|
79031
|
+
resourceIndicator() {
|
|
79032
|
+
if (!CONFIG.OAUTH_RESOURCE_INDICATOR)
|
|
79033
|
+
throw new OAuthError2(
|
|
79034
|
+
"MCP OAuth requires resource indicators; remove OAUTH_RESOURCE_INDICATOR=false",
|
|
79035
|
+
"RESOURCE_REQUIRED"
|
|
79036
|
+
);
|
|
79037
|
+
return this.config.resource;
|
|
79038
|
+
}
|
|
78918
79039
|
/**
|
|
78919
79040
|
* Perform the complete OAuth 2.1 authorization flow
|
|
78920
79041
|
*/
|
|
78921
79042
|
async performAuthorization() {
|
|
78922
79043
|
try {
|
|
78923
|
-
await this.discoverOAuthEndpoints();
|
|
78924
|
-
|
|
79044
|
+
if (!this.authServerMetadata) await this.discoverOAuthEndpoints();
|
|
79045
|
+
if (!this.authServerMetadata?.code_challenge_methods_supported?.includes("S256"))
|
|
79046
|
+
throw new OAuthError2(
|
|
79047
|
+
"Authorization server must advertise PKCE S256 support",
|
|
79048
|
+
"PKCE_REQUIRED"
|
|
79049
|
+
);
|
|
79050
|
+
this.resourceIndicator();
|
|
79051
|
+
if (!["127.0.0.1", "localhost", "::1"].includes(this.config.host))
|
|
79052
|
+
throw new OAuthError2(
|
|
79053
|
+
"Native OAuth callback must bind to loopback",
|
|
79054
|
+
"INVALID_CALLBACK_HOST"
|
|
79055
|
+
);
|
|
79056
|
+
this.currentPKCE = generatePKCE();
|
|
79057
|
+
this.currentState = generateSecureState();
|
|
79058
|
+
const callbackPort = this.config.callbackPort === 0 ? await selectCallbackPort(this.config.serverUrl, void 0, false, this.config.host) : this.config.callbackPort;
|
|
78925
79059
|
const callbackServer = setupWPOAuthCallbackServer(
|
|
78926
79060
|
{
|
|
78927
79061
|
port: callbackPort,
|
|
78928
79062
|
host: this.config.host,
|
|
78929
79063
|
serverUrlHash: this.serverUrlHash,
|
|
78930
|
-
timeout: this.config.timeout
|
|
79064
|
+
timeout: this.config.timeout,
|
|
79065
|
+
state: this.currentState,
|
|
79066
|
+
issuer: this.authServerMetadata.issuer,
|
|
79067
|
+
requireIssuer: this.authServerMetadata.authorization_response_iss_parameter_supported
|
|
78931
79068
|
},
|
|
78932
79069
|
this.events
|
|
78933
79070
|
);
|
|
78934
79071
|
await callbackServer.start();
|
|
78935
79072
|
logger.oauth("OAuth callback server started");
|
|
78936
79073
|
try {
|
|
78937
|
-
const actualRedirectUri = `http://${this.config.host}:${callbackPort}/oauth/callback`;
|
|
79074
|
+
const actualRedirectUri = `http://${this.config.host === "::1" ? "[::1]" : this.config.host}:${callbackPort}/oauth/callback`;
|
|
78938
79075
|
this.config.redirectUri = actualRedirectUri;
|
|
78939
79076
|
await this.ensureClientRegistration();
|
|
78940
|
-
this.currentPKCE = generatePKCE();
|
|
78941
|
-
this.currentState = generateSecureState();
|
|
78942
79077
|
await writeTextFile(this.serverUrlHash, "pkce_verifier.txt", this.currentPKCE.codeVerifier);
|
|
78943
79078
|
await writeTextFile(this.serverUrlHash, "oauth_state.txt", this.currentState);
|
|
78944
79079
|
const authUrl = buildAuthorizationUrl(
|
|
@@ -78948,10 +79083,13 @@ var MCPOAuthProvider = class {
|
|
|
78948
79083
|
this.config.scopes,
|
|
78949
79084
|
this.currentState,
|
|
78950
79085
|
this.currentPKCE.codeChallenge,
|
|
78951
|
-
|
|
79086
|
+
this.resourceIndicator()
|
|
78952
79087
|
);
|
|
78953
79088
|
logger.oauth("Built OAuth 2.1 authorization URL");
|
|
78954
79089
|
logger.debug("Authorization URL", "OAUTH", { url: authUrl });
|
|
79090
|
+
const authorizationCode = this.waitForAuthorizationCode();
|
|
79091
|
+
void authorizationCode.catch(() => {
|
|
79092
|
+
});
|
|
78955
79093
|
try {
|
|
78956
79094
|
await open_default(authUrl);
|
|
78957
79095
|
logger.oauth("Browser opened successfully");
|
|
@@ -78962,13 +79100,20 @@ var MCPOAuthProvider = class {
|
|
|
78962
79100
|
logger.info(`${authUrl}`);
|
|
78963
79101
|
logger.info("===============================\n");
|
|
78964
79102
|
}
|
|
78965
|
-
const authCode = await
|
|
78966
|
-
const
|
|
79103
|
+
const authCode = await authorizationCode;
|
|
79104
|
+
const response = await this.exchangeCodeForTokens(authCode, actualRedirectUri);
|
|
79105
|
+
const tokens = {
|
|
79106
|
+
...response,
|
|
79107
|
+
issuer: this.getAuthorizationServerUrl(),
|
|
79108
|
+
scope: response.scope ?? this.config.scopes.join(" ")
|
|
79109
|
+
};
|
|
78967
79110
|
await writeTokens(this.serverUrlHash, tokens);
|
|
78968
79111
|
logger.oauth("OAuth 2.1 tokens stored successfully");
|
|
78969
79112
|
return tokens;
|
|
78970
79113
|
} finally {
|
|
78971
79114
|
await callbackServer.stop();
|
|
79115
|
+
await deleteConfigFile(this.serverUrlHash, "pkce_verifier.txt");
|
|
79116
|
+
await deleteConfigFile(this.serverUrlHash, "oauth_state.txt");
|
|
78972
79117
|
}
|
|
78973
79118
|
} catch (error51) {
|
|
78974
79119
|
logger.error("Error during OAuth 2.1 authorization flow", "OAUTH", error51);
|
|
@@ -78989,12 +79134,16 @@ var MCPOAuthProvider = class {
|
|
|
78989
79134
|
this.events.removeAllListeners("oauth-error");
|
|
78990
79135
|
clearTimeout(timeout);
|
|
78991
79136
|
};
|
|
78992
|
-
this.events.once("oauth-code-received", async ({ code, state }) => {
|
|
79137
|
+
this.events.once("oauth-code-received", async ({ code, state, iss }) => {
|
|
78993
79138
|
cleanup();
|
|
78994
79139
|
if (state !== this.currentState) {
|
|
78995
79140
|
reject(new OAuthError2("State parameter mismatch", "INVALID_STATE"));
|
|
78996
79141
|
return;
|
|
78997
79142
|
}
|
|
79143
|
+
if ((iss !== void 0 || this.authServerMetadata?.authorization_response_iss_parameter_supported) && iss !== this.authServerMetadata?.issuer) {
|
|
79144
|
+
reject(new OAuthError2("Authorization response issuer mismatch", "INVALID_ISSUER"));
|
|
79145
|
+
return;
|
|
79146
|
+
}
|
|
78998
79147
|
logger.oauth("Valid authorization code received");
|
|
78999
79148
|
resolve(code);
|
|
79000
79149
|
});
|
|
@@ -79020,7 +79169,7 @@ var MCPOAuthProvider = class {
|
|
|
79020
79169
|
redirectUri,
|
|
79021
79170
|
this.config.clientId,
|
|
79022
79171
|
codeVerifier,
|
|
79023
|
-
|
|
79172
|
+
this.resourceIndicator()
|
|
79024
79173
|
);
|
|
79025
79174
|
await deleteConfigFile(this.serverUrlHash, "pkce_verifier.txt");
|
|
79026
79175
|
await deleteConfigFile(this.serverUrlHash, "oauth_state.txt");
|
|
@@ -79086,6 +79235,7 @@ import * as path5 from "node:path";
|
|
|
79086
79235
|
import * as os3 from "node:os";
|
|
79087
79236
|
|
|
79088
79237
|
// src/lib/persistent-oauth-client-provider.ts
|
|
79238
|
+
import { randomBytes } from "node:crypto";
|
|
79089
79239
|
import { EventEmitter as EventEmitter2 } from "node:events";
|
|
79090
79240
|
var PersistentWPOAuthClientProvider = class {
|
|
79091
79241
|
constructor(options) {
|
|
@@ -79243,7 +79393,10 @@ var PersistentWPOAuthClientProvider = class {
|
|
|
79243
79393
|
*/
|
|
79244
79394
|
async performAuthorization() {
|
|
79245
79395
|
const callbackPort = this.options.callbackPort === 0 ? await getOAuthCallbackPort() : this.options.callbackPort;
|
|
79396
|
+
const state = this.generateState();
|
|
79246
79397
|
const callbackServerOptions = {
|
|
79398
|
+
flow: "implicit",
|
|
79399
|
+
state,
|
|
79247
79400
|
port: callbackPort,
|
|
79248
79401
|
host: this.options.host,
|
|
79249
79402
|
serverUrlHash: this.serverUrlHash,
|
|
@@ -79255,12 +79408,14 @@ var PersistentWPOAuthClientProvider = class {
|
|
|
79255
79408
|
logger.oauth("Starting callback server...");
|
|
79256
79409
|
await callbackServer.start();
|
|
79257
79410
|
logger.oauth("Callback server started successfully");
|
|
79258
|
-
const state = this.generateState();
|
|
79259
79411
|
logger.debug(`Generated state parameter: ${state}`, "OAUTH");
|
|
79260
79412
|
const authUrl = this.buildAuthorizationUrl(callbackServer.getCallbackUrl(), state);
|
|
79261
79413
|
logger.oauth(`Built authorization URL: ${authUrl}`);
|
|
79262
79414
|
logger.debug(`Callback URL: ${callbackServer.getCallbackUrl()}`, "OAUTH");
|
|
79263
79415
|
logger.oauth("Attempting to open browser...");
|
|
79416
|
+
const authorization = this.waitForAuthorizationResult();
|
|
79417
|
+
void authorization.catch(() => {
|
|
79418
|
+
});
|
|
79264
79419
|
try {
|
|
79265
79420
|
await open_default(authUrl);
|
|
79266
79421
|
logger.oauth("Browser opened successfully");
|
|
@@ -79272,7 +79427,7 @@ var PersistentWPOAuthClientProvider = class {
|
|
|
79272
79427
|
logger.info("===============================\n");
|
|
79273
79428
|
}
|
|
79274
79429
|
logger.oauth("Waiting for authorization result...");
|
|
79275
|
-
const tokens = await
|
|
79430
|
+
const tokens = await authorization;
|
|
79276
79431
|
logger.oauth("Authorization result received");
|
|
79277
79432
|
logger.oauth("Saving tokens to persistent storage...");
|
|
79278
79433
|
await this.saveTokens(tokens);
|
|
@@ -79325,7 +79480,7 @@ var PersistentWPOAuthClientProvider = class {
|
|
|
79325
79480
|
* Generate a secure state parameter
|
|
79326
79481
|
*/
|
|
79327
79482
|
generateState() {
|
|
79328
|
-
return
|
|
79483
|
+
return randomBytes(32).toString("base64url");
|
|
79329
79484
|
}
|
|
79330
79485
|
/**
|
|
79331
79486
|
* Wait for authorization result from callback server
|
|
@@ -79720,6 +79875,12 @@ function constructApiUrl(baseUrl, defaultEndpoint) {
|
|
|
79720
79875
|
return new URL(`/?rest_route=${defaultEndpoint}`, cleanUrl).toString();
|
|
79721
79876
|
}
|
|
79722
79877
|
}
|
|
79878
|
+
function getMCPOAuthProvider() {
|
|
79879
|
+
return mcpOAuthProvider ??= new MCPOAuthProvider({
|
|
79880
|
+
serverUrl: getRequestUrl(),
|
|
79881
|
+
clientId: CONFIG.WP_OAUTH_CLIENT_ID
|
|
79882
|
+
});
|
|
79883
|
+
}
|
|
79723
79884
|
async function getOAuthTokens() {
|
|
79724
79885
|
try {
|
|
79725
79886
|
if (!CONFIG.OAUTH_ENABLED) {
|
|
@@ -79727,7 +79888,7 @@ async function getOAuthTokens() {
|
|
|
79727
79888
|
return null;
|
|
79728
79889
|
}
|
|
79729
79890
|
logger.auth("Attempting to get OAuth tokens for WordPress API (MCP-compliant)...");
|
|
79730
|
-
const serverUrl =
|
|
79891
|
+
const serverUrl = getRequestUrl();
|
|
79731
79892
|
const serverUrlHash = generateServerUrlHash(serverUrl);
|
|
79732
79893
|
const existingTokens = await getValidTokens(serverUrlHash);
|
|
79733
79894
|
if (existingTokens) {
|
|
@@ -79738,16 +79899,10 @@ async function getOAuthTokens() {
|
|
|
79738
79899
|
logger.auth("Starting MCP-compliant OAuth 2.1 authentication flow");
|
|
79739
79900
|
logger.auth("Your browser should open automatically for authentication");
|
|
79740
79901
|
if (CONFIG.OAUTH_FLOW_TYPE === "authorization_code" && CONFIG.OAUTH_USE_PKCE) {
|
|
79741
|
-
if (!mcpOAuthProvider) {
|
|
79742
|
-
mcpOAuthProvider = new MCPOAuthProvider({
|
|
79743
|
-
serverUrl,
|
|
79744
|
-
clientId: CONFIG.WP_OAUTH_CLIENT_ID,
|
|
79745
|
-
scopes: getDefaultOAuthScopes()
|
|
79746
|
-
});
|
|
79747
|
-
}
|
|
79748
79902
|
logger.auth("Using MCP-compliant OAuth 2.1 authorization code flow with PKCE");
|
|
79749
|
-
|
|
79750
|
-
|
|
79903
|
+
const provider = getMCPOAuthProvider();
|
|
79904
|
+
await provider.authorize();
|
|
79905
|
+
const tokens = await provider.tokens();
|
|
79751
79906
|
if (tokens) {
|
|
79752
79907
|
logger.auth("MCP OAuth 2.1 tokens obtained for WordPress API access");
|
|
79753
79908
|
return tokens;
|
|
@@ -79788,6 +79943,22 @@ async function getOAuthTokens() {
|
|
|
79788
79943
|
return null;
|
|
79789
79944
|
}
|
|
79790
79945
|
}
|
|
79946
|
+
async function recoverOAuthAuthorization(authorization, challenge, status = 401) {
|
|
79947
|
+
if (!CONFIG.OAUTH_ENABLED || CONFIG.JWT_TOKEN || CONFIG.OAUTH_FLOW_TYPE !== "authorization_code" || !CONFIG.OAUTH_USE_PKCE)
|
|
79948
|
+
return false;
|
|
79949
|
+
if (authorization && !/^Bearer /i.test(authorization)) return false;
|
|
79950
|
+
const scopes = status === 401 || challenge?.error === "insufficient_scope" ? challenge?.scope?.split(/\s+/).filter(Boolean) : void 0;
|
|
79951
|
+
if (status === 403 && !scopes?.length) return false;
|
|
79952
|
+
const current = await getValidTokens(generateServerUrlHash(getRequestUrl()));
|
|
79953
|
+
if (status === 403 && scopes?.every((scope) => current?.scope?.split(" ").includes(scope)))
|
|
79954
|
+
return current?.access_token !== authorization?.slice(7);
|
|
79955
|
+
await getMCPOAuthProvider().authorize({
|
|
79956
|
+
rejectedToken: status === 401 ? authorization?.slice(7) : void 0,
|
|
79957
|
+
challenge,
|
|
79958
|
+
scopes
|
|
79959
|
+
});
|
|
79960
|
+
return true;
|
|
79961
|
+
}
|
|
79791
79962
|
function getCurrentApiUrl() {
|
|
79792
79963
|
return process.env.WP_API_URL || CONFIG.WP_API_URL;
|
|
79793
79964
|
}
|
|
@@ -79806,7 +79977,7 @@ function bindWordPressRequest(request) {
|
|
|
79806
79977
|
if (shared[LIVE_REQUEST_KEY] === request) delete shared[LIVE_REQUEST_KEY];
|
|
79807
79978
|
};
|
|
79808
79979
|
}
|
|
79809
|
-
async function getWordPressHeaders(requestData) {
|
|
79980
|
+
async function getWordPressHeaders(requestData, options = {}) {
|
|
79810
79981
|
validateEnvironment();
|
|
79811
79982
|
let authHeader = "";
|
|
79812
79983
|
if (CONFIG.JWT_TOKEN) {
|
|
@@ -79815,7 +79986,7 @@ async function getWordPressHeaders(requestData) {
|
|
|
79815
79986
|
logger.debug(`Token length: ${CONFIG.JWT_TOKEN.length}`, "AUTH");
|
|
79816
79987
|
} else if (CONFIG.OAUTH_ENABLED) {
|
|
79817
79988
|
logger.auth("OAuth is the primary authentication method - attempting to get tokens...");
|
|
79818
|
-
const oauthTokens = await getOAuthTokens();
|
|
79989
|
+
const oauthTokens = options.allowUnauthenticated && !CONFIG.WP_API_USERNAME ? await getValidTokens(generateServerUrlHash(getRequestUrl())) : await getOAuthTokens();
|
|
79819
79990
|
if (oauthTokens) {
|
|
79820
79991
|
authHeader = `Bearer ${oauthTokens.access_token}`;
|
|
79821
79992
|
logger.auth("Using OAuth token authentication for WordPress API");
|
|
@@ -79855,7 +80026,7 @@ async function getWordPressHeaders(requestData) {
|
|
|
79855
80026
|
if (name.toLowerCase() === "mcp-protocol-version") delete customHeaders[name];
|
|
79856
80027
|
}
|
|
79857
80028
|
const hasCustomHeaders = Object.keys(customHeaders).length > 0;
|
|
79858
|
-
if (!authHeader && !hasCustomHeaders) {
|
|
80029
|
+
if (!authHeader && !hasCustomHeaders && !(options.allowUnauthenticated && CONFIG.OAUTH_ENABLED)) {
|
|
79859
80030
|
throw new AuthError(
|
|
79860
80031
|
"No authentication method available. Please configure JWT_TOKEN, OAuth, Basic Auth (WP_API_USERNAME+WP_API_PASSWORD), or CUSTOM_HEADERS.",
|
|
79861
80032
|
"NO_AUTH_METHOD"
|
|
@@ -79887,6 +80058,9 @@ function collectHeaderParams(schema, path6 = []) {
|
|
|
79887
80058
|
return [...own, ...collectHeaderParams(child, [...path6, key])];
|
|
79888
80059
|
});
|
|
79889
80060
|
}
|
|
80061
|
+
function isBearerChallenge(challenge) {
|
|
80062
|
+
return challenge === null || parseWWWAuthenticateHeader(challenge).scheme === "Bearer";
|
|
80063
|
+
}
|
|
79890
80064
|
function valueAtPath(value, path6) {
|
|
79891
80065
|
return path6.reduce(
|
|
79892
80066
|
(node, key) => node && typeof node === "object" ? node[key] : void 0,
|
|
@@ -79896,25 +80070,26 @@ function valueAtPath(value, path6) {
|
|
|
79896
80070
|
function createWordPressTransport(onFailure) {
|
|
79897
80071
|
const inflight = /* @__PURE__ */ new Map();
|
|
79898
80072
|
const toolHeaders = /* @__PURE__ */ new Map();
|
|
79899
|
-
const
|
|
80073
|
+
const scopeAttempts = /* @__PURE__ */ new Set();
|
|
80074
|
+
const scopeCounts = /* @__PURE__ */ new Map();
|
|
80075
|
+
const send = async (url2, init, retried) => {
|
|
79900
80076
|
const message = typeof init?.body === "string" ? JSON.parse(init.body) : void 0;
|
|
79901
80077
|
const request = message && "method" in message && "id" in message ? message : void 0;
|
|
79902
80078
|
const controller = new AbortController();
|
|
79903
|
-
const abort = () => controller.abort();
|
|
79904
80079
|
let cancelled = false;
|
|
79905
80080
|
const cancel = () => {
|
|
79906
80081
|
cancelled = true;
|
|
79907
|
-
abort();
|
|
80082
|
+
controller.abort();
|
|
79908
80083
|
};
|
|
79909
80084
|
if (request) inflight.set(request.id, cancel);
|
|
79910
|
-
init?.signal?.addEventListener("abort",
|
|
79911
|
-
if (init?.signal?.aborted)
|
|
80085
|
+
init?.signal?.addEventListener("abort", cancel, { once: true });
|
|
80086
|
+
if (init?.signal?.aborted) cancel();
|
|
79912
80087
|
const timeoutMs = message && "method" in message && message.method === "initialize" ? CONFIG.WP_API_INIT_TIMEOUT : CONFIG.WP_API_TIMEOUT;
|
|
79913
80088
|
let timedOut = false;
|
|
79914
80089
|
let timer;
|
|
79915
80090
|
const cleanup = () => {
|
|
79916
80091
|
clearTimeout(timer);
|
|
79917
|
-
init?.signal?.removeEventListener("abort",
|
|
80092
|
+
init?.signal?.removeEventListener("abort", cancel);
|
|
79918
80093
|
if (request && inflight.get(request.id) === cancel) inflight.delete(request.id);
|
|
79919
80094
|
};
|
|
79920
80095
|
const failure = (error51) => {
|
|
@@ -79930,7 +80105,9 @@ function createWordPressTransport(onFailure) {
|
|
|
79930
80105
|
return apiError;
|
|
79931
80106
|
};
|
|
79932
80107
|
try {
|
|
79933
|
-
const headers = new Headers(
|
|
80108
|
+
const headers = new Headers(
|
|
80109
|
+
await getWordPressHeaders(message, { allowUnauthenticated: !retried })
|
|
80110
|
+
);
|
|
79934
80111
|
if (init?.method !== "GET" && request?.method !== "subscriptions/listen") {
|
|
79935
80112
|
timer = setTimeout(() => {
|
|
79936
80113
|
timedOut = true;
|
|
@@ -79963,17 +80140,55 @@ function createWordPressTransport(onFailure) {
|
|
|
79963
80140
|
headers,
|
|
79964
80141
|
signal: controller.signal
|
|
79965
80142
|
});
|
|
80143
|
+
const challenge = parseWWWAuthenticateHeader(response.headers.get("WWW-Authenticate") ?? "");
|
|
80144
|
+
const operationKey = JSON.stringify([
|
|
80145
|
+
request?.method,
|
|
80146
|
+
request?.params?.name ?? request?.params?.uri
|
|
80147
|
+
]);
|
|
80148
|
+
const scopeKey = JSON.stringify([
|
|
80149
|
+
request?.method,
|
|
80150
|
+
request?.params?.name,
|
|
80151
|
+
challenge.scope?.split(/\s+/).sort()
|
|
80152
|
+
]);
|
|
80153
|
+
const canRecover = !retried && (response.status === 401 && isBearerChallenge(response.headers.get("WWW-Authenticate")) || response.status === 403 && challenge.error === "insufficient_scope" && !!challenge.scope && !scopeAttempts.has(scopeKey) && (scopeCounts.get(operationKey) ?? 0) < 2);
|
|
80154
|
+
if (canRecover) {
|
|
80155
|
+
if (response.status === 403) {
|
|
80156
|
+
scopeAttempts.add(scopeKey);
|
|
80157
|
+
scopeCounts.set(operationKey, (scopeCounts.get(operationKey) ?? 0) + 1);
|
|
80158
|
+
}
|
|
80159
|
+
clearTimeout(timer);
|
|
80160
|
+
const recovered = await recoverOAuthAuthorization(
|
|
80161
|
+
headers.get("Authorization"),
|
|
80162
|
+
challenge,
|
|
80163
|
+
response.status
|
|
80164
|
+
);
|
|
80165
|
+
if (recovered) {
|
|
80166
|
+
const unread = response.body;
|
|
80167
|
+
if (typeof unread?.cancel === "function") await unread.cancel();
|
|
80168
|
+
else unread?.destroy?.();
|
|
80169
|
+
cleanup();
|
|
80170
|
+
if (cancelled) return new Response(null, { status: 202 });
|
|
80171
|
+
return send(url2, init, true);
|
|
80172
|
+
}
|
|
80173
|
+
timer = setTimeout(() => {
|
|
80174
|
+
timedOut = true;
|
|
80175
|
+
controller.abort();
|
|
80176
|
+
}, timeoutMs);
|
|
80177
|
+
}
|
|
79966
80178
|
const body = response.body && typeof response.body.getReader !== "function" ? Readable.toWeb(response.body) : response.body;
|
|
79967
80179
|
const reader = body?.getReader();
|
|
80180
|
+
let released = false;
|
|
79968
80181
|
const stream = reader ? new ReadableStream({
|
|
79969
80182
|
async pull(output) {
|
|
79970
80183
|
try {
|
|
79971
80184
|
const { value, done } = await reader.read();
|
|
80185
|
+
if (released) return;
|
|
79972
80186
|
if (done) {
|
|
79973
80187
|
cleanup();
|
|
79974
80188
|
output.close();
|
|
79975
80189
|
} else output.enqueue(value);
|
|
79976
80190
|
} catch (error51) {
|
|
80191
|
+
if (released) return;
|
|
79977
80192
|
if (cancelled) {
|
|
79978
80193
|
cleanup();
|
|
79979
80194
|
output.close();
|
|
@@ -79981,6 +80196,7 @@ function createWordPressTransport(onFailure) {
|
|
|
79981
80196
|
}
|
|
79982
80197
|
},
|
|
79983
80198
|
async cancel(reason) {
|
|
80199
|
+
released = true;
|
|
79984
80200
|
cleanup();
|
|
79985
80201
|
await reader.cancel(reason);
|
|
79986
80202
|
}
|
|
@@ -80019,6 +80235,7 @@ function createWordPressTransport(onFailure) {
|
|
|
80019
80235
|
throw failure(error51);
|
|
80020
80236
|
}
|
|
80021
80237
|
};
|
|
80238
|
+
const fetch3 = (url2, init) => send(url2, init, false);
|
|
80022
80239
|
return Object.assign(new StreamableHTTPClientTransport(new URL(getRequestUrl()), { fetch: fetch3 }), {
|
|
80023
80240
|
cancelRequest(id) {
|
|
80024
80241
|
inflight.get(id)?.();
|
|
@@ -80246,11 +80463,6 @@ async function startPassThrough(local, remote) {
|
|
|
80246
80463
|
validateNodeVersion(18);
|
|
80247
80464
|
async function WordPressProxy() {
|
|
80248
80465
|
await setupFetchPolyfill();
|
|
80249
|
-
try {
|
|
80250
|
-
await cleanupExpiredTokens();
|
|
80251
|
-
} catch (error51) {
|
|
80252
|
-
logger.warn("Error cleaning up expired tokens", "PROXY", error51);
|
|
80253
|
-
}
|
|
80254
80466
|
const local = new StdioServerTransport();
|
|
80255
80467
|
let bridge;
|
|
80256
80468
|
const remote = createWordPressTransport((message, error51) => bridge?.fail(message, error51));
|
|
@@ -80285,6 +80497,13 @@ formdata-polyfill/esm.min.js:
|
|
|
80285
80497
|
node-domexception/index.js:
|
|
80286
80498
|
(*! node-domexception. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> *)
|
|
80287
80499
|
|
|
80500
|
+
content-type/index.js:
|
|
80501
|
+
(*!
|
|
80502
|
+
* content-type
|
|
80503
|
+
* Copyright(c) 2015 Douglas Christopher Wilson
|
|
80504
|
+
* MIT Licensed
|
|
80505
|
+
*)
|
|
80506
|
+
|
|
80288
80507
|
depd/index.js:
|
|
80289
80508
|
(*!
|
|
80290
80509
|
* depd
|
|
@@ -80482,13 +80701,6 @@ express/lib/view.js:
|
|
|
80482
80701
|
* MIT Licensed
|
|
80483
80702
|
*)
|
|
80484
80703
|
|
|
80485
|
-
content-type/index.js:
|
|
80486
|
-
(*!
|
|
80487
|
-
* content-type
|
|
80488
|
-
* Copyright(c) 2015 Douglas Christopher Wilson
|
|
80489
|
-
* MIT Licensed
|
|
80490
|
-
*)
|
|
80491
|
-
|
|
80492
80704
|
etag/index.js:
|
|
80493
80705
|
(*!
|
|
80494
80706
|
* etag
|