bridge-agent 0.17.1 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bridge-mcp.cjs +2779 -133
- package/dist/index.js +151 -84
- package/package.json +2 -1
package/dist/bridge-mcp.cjs
CHANGED
|
@@ -1299,21 +1299,21 @@ var require_errors = __commonJS({
|
|
|
1299
1299
|
function extendErrors({ gen, keyword, schemaValue, data, errsCount, it }) {
|
|
1300
1300
|
if (errsCount === void 0)
|
|
1301
1301
|
throw new Error("ajv implementation error");
|
|
1302
|
-
const
|
|
1302
|
+
const err6 = gen.name("err");
|
|
1303
1303
|
gen.forRange("i", errsCount, names_1.default.errors, (i) => {
|
|
1304
|
-
gen.const(
|
|
1305
|
-
gen.if((0, codegen_1._)`${
|
|
1306
|
-
gen.assign((0, codegen_1._)`${
|
|
1304
|
+
gen.const(err6, (0, codegen_1._)`${names_1.default.vErrors}[${i}]`);
|
|
1305
|
+
gen.if((0, codegen_1._)`${err6}.instancePath === undefined`, () => gen.assign((0, codegen_1._)`${err6}.instancePath`, (0, codegen_1.strConcat)(names_1.default.instancePath, it.errorPath)));
|
|
1306
|
+
gen.assign((0, codegen_1._)`${err6}.schemaPath`, (0, codegen_1.str)`${it.errSchemaPath}/${keyword}`);
|
|
1307
1307
|
if (it.opts.verbose) {
|
|
1308
|
-
gen.assign((0, codegen_1._)`${
|
|
1309
|
-
gen.assign((0, codegen_1._)`${
|
|
1308
|
+
gen.assign((0, codegen_1._)`${err6}.schema`, schemaValue);
|
|
1309
|
+
gen.assign((0, codegen_1._)`${err6}.data`, data);
|
|
1310
1310
|
}
|
|
1311
1311
|
});
|
|
1312
1312
|
}
|
|
1313
1313
|
exports2.extendErrors = extendErrors;
|
|
1314
1314
|
function addError(gen, errObj) {
|
|
1315
|
-
const
|
|
1316
|
-
gen.if((0, codegen_1._)`${names_1.default.vErrors} === null`, () => gen.assign(names_1.default.vErrors, (0, codegen_1._)`[${
|
|
1315
|
+
const err6 = gen.const("err", errObj);
|
|
1316
|
+
gen.if((0, codegen_1._)`${names_1.default.vErrors} === null`, () => gen.assign(names_1.default.vErrors, (0, codegen_1._)`[${err6}]`), (0, codegen_1._)`${names_1.default.vErrors}.push(${err6})`);
|
|
1317
1317
|
gen.code((0, codegen_1._)`${names_1.default.errors}++`);
|
|
1318
1318
|
}
|
|
1319
1319
|
function returnErrors(it, errs) {
|
|
@@ -6493,7 +6493,7 @@ var require_formats = __commonJS({
|
|
|
6493
6493
|
}
|
|
6494
6494
|
exports2.fullFormats = {
|
|
6495
6495
|
// date: http://tools.ietf.org/html/rfc3339#section-5.6
|
|
6496
|
-
date: fmtDef(
|
|
6496
|
+
date: fmtDef(date4, compareDate),
|
|
6497
6497
|
// date-time: http://tools.ietf.org/html/rfc3339#section-5.6
|
|
6498
6498
|
time: fmtDef(getTime(true), compareTime),
|
|
6499
6499
|
"date-time": fmtDef(getDateTime(true), compareDateTime),
|
|
@@ -6559,7 +6559,7 @@ var require_formats = __commonJS({
|
|
|
6559
6559
|
}
|
|
6560
6560
|
var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
|
|
6561
6561
|
var DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
6562
|
-
function
|
|
6562
|
+
function date4(str) {
|
|
6563
6563
|
const matches = DATE.exec(str);
|
|
6564
6564
|
if (!matches)
|
|
6565
6565
|
return false;
|
|
@@ -6628,7 +6628,7 @@ var require_formats = __commonJS({
|
|
|
6628
6628
|
const time3 = getTime(strictTimeZone);
|
|
6629
6629
|
return function date_time(str) {
|
|
6630
6630
|
const dateTime = str.split(DATE_TIME_SEPARATOR);
|
|
6631
|
-
return dateTime.length === 2 &&
|
|
6631
|
+
return dateTime.length === 2 && date4(dateTime[0]) && time3(dateTime[1]);
|
|
6632
6632
|
};
|
|
6633
6633
|
}
|
|
6634
6634
|
function compareDateTime(dt1, dt2) {
|
|
@@ -7541,8 +7541,8 @@ var ZodType = class {
|
|
|
7541
7541
|
} : {
|
|
7542
7542
|
issues: ctx.common.issues
|
|
7543
7543
|
};
|
|
7544
|
-
} catch (
|
|
7545
|
-
if (
|
|
7544
|
+
} catch (err6) {
|
|
7545
|
+
if (err6?.message?.toLowerCase()?.includes("encountered")) {
|
|
7546
7546
|
this["~standard"].async = true;
|
|
7547
7547
|
}
|
|
7548
7548
|
ctx.common = {
|
|
@@ -11602,6 +11602,7 @@ var string = (params) => {
|
|
|
11602
11602
|
const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
|
|
11603
11603
|
return new RegExp(`^${regex}$`);
|
|
11604
11604
|
};
|
|
11605
|
+
var bigint = /^\d+n?$/;
|
|
11605
11606
|
var integer = /^\d+$/;
|
|
11606
11607
|
var number = /^-?\d+(?:\.\d+)?/i;
|
|
11607
11608
|
var boolean = /true|false/i;
|
|
@@ -12179,11 +12180,11 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
|
|
|
12179
12180
|
inst._zod.check = (payload) => {
|
|
12180
12181
|
try {
|
|
12181
12182
|
const orig = payload.value;
|
|
12182
|
-
const
|
|
12183
|
-
const href =
|
|
12183
|
+
const url2 = new URL(orig);
|
|
12184
|
+
const href = url2.href;
|
|
12184
12185
|
if (def.hostname) {
|
|
12185
12186
|
def.hostname.lastIndex = 0;
|
|
12186
|
-
if (!def.hostname.test(
|
|
12187
|
+
if (!def.hostname.test(url2.hostname)) {
|
|
12187
12188
|
payload.issues.push({
|
|
12188
12189
|
code: "invalid_format",
|
|
12189
12190
|
format: "url",
|
|
@@ -12197,7 +12198,7 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
|
|
|
12197
12198
|
}
|
|
12198
12199
|
if (def.protocol) {
|
|
12199
12200
|
def.protocol.lastIndex = 0;
|
|
12200
|
-
if (!def.protocol.test(
|
|
12201
|
+
if (!def.protocol.test(url2.protocol.endsWith(":") ? url2.protocol.slice(0, -1) : url2.protocol)) {
|
|
12201
12202
|
payload.issues.push({
|
|
12202
12203
|
code: "invalid_format",
|
|
12203
12204
|
format: "url",
|
|
@@ -12470,6 +12471,26 @@ var $ZodBoolean = /* @__PURE__ */ $constructor("$ZodBoolean", (inst, def) => {
|
|
|
12470
12471
|
return payload;
|
|
12471
12472
|
};
|
|
12472
12473
|
});
|
|
12474
|
+
var $ZodBigInt = /* @__PURE__ */ $constructor("$ZodBigInt", (inst, def) => {
|
|
12475
|
+
$ZodType.init(inst, def);
|
|
12476
|
+
inst._zod.pattern = bigint;
|
|
12477
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
12478
|
+
if (def.coerce)
|
|
12479
|
+
try {
|
|
12480
|
+
payload.value = BigInt(payload.value);
|
|
12481
|
+
} catch (_) {
|
|
12482
|
+
}
|
|
12483
|
+
if (typeof payload.value === "bigint")
|
|
12484
|
+
return payload;
|
|
12485
|
+
payload.issues.push({
|
|
12486
|
+
expected: "bigint",
|
|
12487
|
+
code: "invalid_type",
|
|
12488
|
+
input: payload.value,
|
|
12489
|
+
inst
|
|
12490
|
+
});
|
|
12491
|
+
return payload;
|
|
12492
|
+
};
|
|
12493
|
+
});
|
|
12473
12494
|
var $ZodNull = /* @__PURE__ */ $constructor("$ZodNull", (inst, def) => {
|
|
12474
12495
|
$ZodType.init(inst, def);
|
|
12475
12496
|
inst._zod.pattern = _null;
|
|
@@ -12487,6 +12508,10 @@ var $ZodNull = /* @__PURE__ */ $constructor("$ZodNull", (inst, def) => {
|
|
|
12487
12508
|
return payload;
|
|
12488
12509
|
};
|
|
12489
12510
|
});
|
|
12511
|
+
var $ZodAny = /* @__PURE__ */ $constructor("$ZodAny", (inst, def) => {
|
|
12512
|
+
$ZodType.init(inst, def);
|
|
12513
|
+
inst._zod.parse = (payload) => payload;
|
|
12514
|
+
});
|
|
12490
12515
|
var $ZodUnknown = /* @__PURE__ */ $constructor("$ZodUnknown", (inst, def) => {
|
|
12491
12516
|
$ZodType.init(inst, def);
|
|
12492
12517
|
inst._zod.parse = (payload) => payload;
|
|
@@ -12503,6 +12528,30 @@ var $ZodNever = /* @__PURE__ */ $constructor("$ZodNever", (inst, def) => {
|
|
|
12503
12528
|
return payload;
|
|
12504
12529
|
};
|
|
12505
12530
|
});
|
|
12531
|
+
var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
|
|
12532
|
+
$ZodType.init(inst, def);
|
|
12533
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
12534
|
+
if (def.coerce) {
|
|
12535
|
+
try {
|
|
12536
|
+
payload.value = new Date(payload.value);
|
|
12537
|
+
} catch (_err) {
|
|
12538
|
+
}
|
|
12539
|
+
}
|
|
12540
|
+
const input = payload.value;
|
|
12541
|
+
const isDate = input instanceof Date;
|
|
12542
|
+
const isValidDate = isDate && !Number.isNaN(input.getTime());
|
|
12543
|
+
if (isValidDate)
|
|
12544
|
+
return payload;
|
|
12545
|
+
payload.issues.push({
|
|
12546
|
+
expected: "date",
|
|
12547
|
+
code: "invalid_type",
|
|
12548
|
+
input,
|
|
12549
|
+
...isDate ? { received: "Invalid Date" } : {},
|
|
12550
|
+
inst
|
|
12551
|
+
});
|
|
12552
|
+
return payload;
|
|
12553
|
+
};
|
|
12554
|
+
});
|
|
12506
12555
|
function handleArrayResult(result, final, index) {
|
|
12507
12556
|
if (result.issues.length) {
|
|
12508
12557
|
final.issues.push(...prefixIssues(index, result.issues));
|
|
@@ -13448,6 +13497,13 @@ function _string(Class2, params) {
|
|
|
13448
13497
|
...normalizeParams(params)
|
|
13449
13498
|
});
|
|
13450
13499
|
}
|
|
13500
|
+
function _coercedString(Class2, params) {
|
|
13501
|
+
return new Class2({
|
|
13502
|
+
type: "string",
|
|
13503
|
+
coerce: true,
|
|
13504
|
+
...normalizeParams(params)
|
|
13505
|
+
});
|
|
13506
|
+
}
|
|
13451
13507
|
function _email(Class2, params) {
|
|
13452
13508
|
return new Class2({
|
|
13453
13509
|
type: "string",
|
|
@@ -13692,6 +13748,14 @@ function _number(Class2, params) {
|
|
|
13692
13748
|
...normalizeParams(params)
|
|
13693
13749
|
});
|
|
13694
13750
|
}
|
|
13751
|
+
function _coercedNumber(Class2, params) {
|
|
13752
|
+
return new Class2({
|
|
13753
|
+
type: "number",
|
|
13754
|
+
coerce: true,
|
|
13755
|
+
checks: [],
|
|
13756
|
+
...normalizeParams(params)
|
|
13757
|
+
});
|
|
13758
|
+
}
|
|
13695
13759
|
function _int(Class2, params) {
|
|
13696
13760
|
return new Class2({
|
|
13697
13761
|
type: "number",
|
|
@@ -13707,12 +13771,31 @@ function _boolean(Class2, params) {
|
|
|
13707
13771
|
...normalizeParams(params)
|
|
13708
13772
|
});
|
|
13709
13773
|
}
|
|
13774
|
+
function _coercedBoolean(Class2, params) {
|
|
13775
|
+
return new Class2({
|
|
13776
|
+
type: "boolean",
|
|
13777
|
+
coerce: true,
|
|
13778
|
+
...normalizeParams(params)
|
|
13779
|
+
});
|
|
13780
|
+
}
|
|
13781
|
+
function _coercedBigint(Class2, params) {
|
|
13782
|
+
return new Class2({
|
|
13783
|
+
type: "bigint",
|
|
13784
|
+
coerce: true,
|
|
13785
|
+
...normalizeParams(params)
|
|
13786
|
+
});
|
|
13787
|
+
}
|
|
13710
13788
|
function _null2(Class2, params) {
|
|
13711
13789
|
return new Class2({
|
|
13712
13790
|
type: "null",
|
|
13713
13791
|
...normalizeParams(params)
|
|
13714
13792
|
});
|
|
13715
13793
|
}
|
|
13794
|
+
function _any(Class2) {
|
|
13795
|
+
return new Class2({
|
|
13796
|
+
type: "any"
|
|
13797
|
+
});
|
|
13798
|
+
}
|
|
13716
13799
|
function _unknown(Class2) {
|
|
13717
13800
|
return new Class2({
|
|
13718
13801
|
type: "unknown"
|
|
@@ -13724,6 +13807,13 @@ function _never(Class2, params) {
|
|
|
13724
13807
|
...normalizeParams(params)
|
|
13725
13808
|
});
|
|
13726
13809
|
}
|
|
13810
|
+
function _coercedDate(Class2, params) {
|
|
13811
|
+
return new Class2({
|
|
13812
|
+
type: "date",
|
|
13813
|
+
coerce: true,
|
|
13814
|
+
...normalizeParams(params)
|
|
13815
|
+
});
|
|
13816
|
+
}
|
|
13727
13817
|
function _lt(value, params) {
|
|
13728
13818
|
return new $ZodCheckLessThan({
|
|
13729
13819
|
check: "less_than",
|
|
@@ -15061,6 +15151,9 @@ var ZodURL = /* @__PURE__ */ $constructor("ZodURL", (inst, def) => {
|
|
|
15061
15151
|
$ZodURL.init(inst, def);
|
|
15062
15152
|
ZodStringFormat.init(inst, def);
|
|
15063
15153
|
});
|
|
15154
|
+
function url(params) {
|
|
15155
|
+
return _url(ZodURL, params);
|
|
15156
|
+
}
|
|
15064
15157
|
var ZodEmoji = /* @__PURE__ */ $constructor("ZodEmoji", (inst, def) => {
|
|
15065
15158
|
$ZodEmoji.init(inst, def);
|
|
15066
15159
|
ZodStringFormat.init(inst, def);
|
|
@@ -15163,6 +15256,27 @@ var ZodBoolean2 = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
|
|
|
15163
15256
|
function boolean2(params) {
|
|
15164
15257
|
return _boolean(ZodBoolean2, params);
|
|
15165
15258
|
}
|
|
15259
|
+
var ZodBigInt2 = /* @__PURE__ */ $constructor("ZodBigInt", (inst, def) => {
|
|
15260
|
+
$ZodBigInt.init(inst, def);
|
|
15261
|
+
ZodType2.init(inst, def);
|
|
15262
|
+
inst.gte = (value, params) => inst.check(_gte(value, params));
|
|
15263
|
+
inst.min = (value, params) => inst.check(_gte(value, params));
|
|
15264
|
+
inst.gt = (value, params) => inst.check(_gt(value, params));
|
|
15265
|
+
inst.gte = (value, params) => inst.check(_gte(value, params));
|
|
15266
|
+
inst.min = (value, params) => inst.check(_gte(value, params));
|
|
15267
|
+
inst.lt = (value, params) => inst.check(_lt(value, params));
|
|
15268
|
+
inst.lte = (value, params) => inst.check(_lte(value, params));
|
|
15269
|
+
inst.max = (value, params) => inst.check(_lte(value, params));
|
|
15270
|
+
inst.positive = (params) => inst.check(_gt(BigInt(0), params));
|
|
15271
|
+
inst.negative = (params) => inst.check(_lt(BigInt(0), params));
|
|
15272
|
+
inst.nonpositive = (params) => inst.check(_lte(BigInt(0), params));
|
|
15273
|
+
inst.nonnegative = (params) => inst.check(_gte(BigInt(0), params));
|
|
15274
|
+
inst.multipleOf = (value, params) => inst.check(_multipleOf(value, params));
|
|
15275
|
+
const bag = inst._zod.bag;
|
|
15276
|
+
inst.minValue = bag.minimum ?? null;
|
|
15277
|
+
inst.maxValue = bag.maximum ?? null;
|
|
15278
|
+
inst.format = bag.format ?? null;
|
|
15279
|
+
});
|
|
15166
15280
|
var ZodNull2 = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
|
|
15167
15281
|
$ZodNull.init(inst, def);
|
|
15168
15282
|
ZodType2.init(inst, def);
|
|
@@ -15170,6 +15284,13 @@ var ZodNull2 = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
|
|
|
15170
15284
|
function _null3(params) {
|
|
15171
15285
|
return _null2(ZodNull2, params);
|
|
15172
15286
|
}
|
|
15287
|
+
var ZodAny2 = /* @__PURE__ */ $constructor("ZodAny", (inst, def) => {
|
|
15288
|
+
$ZodAny.init(inst, def);
|
|
15289
|
+
ZodType2.init(inst, def);
|
|
15290
|
+
});
|
|
15291
|
+
function any() {
|
|
15292
|
+
return _any(ZodAny2);
|
|
15293
|
+
}
|
|
15173
15294
|
var ZodUnknown2 = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
|
|
15174
15295
|
$ZodUnknown.init(inst, def);
|
|
15175
15296
|
ZodType2.init(inst, def);
|
|
@@ -15184,6 +15305,15 @@ var ZodNever2 = /* @__PURE__ */ $constructor("ZodNever", (inst, def) => {
|
|
|
15184
15305
|
function never(params) {
|
|
15185
15306
|
return _never(ZodNever2, params);
|
|
15186
15307
|
}
|
|
15308
|
+
var ZodDate2 = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
|
|
15309
|
+
$ZodDate.init(inst, def);
|
|
15310
|
+
ZodType2.init(inst, def);
|
|
15311
|
+
inst.min = (value, params) => inst.check(_gte(value, params));
|
|
15312
|
+
inst.max = (value, params) => inst.check(_lte(value, params));
|
|
15313
|
+
const c = inst._zod.bag;
|
|
15314
|
+
inst.minDate = c.minimum ? new Date(c.minimum) : null;
|
|
15315
|
+
inst.maxDate = c.maximum ? new Date(c.maximum) : null;
|
|
15316
|
+
});
|
|
15187
15317
|
var ZodArray2 = /* @__PURE__ */ $constructor("ZodArray", (inst, def) => {
|
|
15188
15318
|
$ZodArray.init(inst, def);
|
|
15189
15319
|
ZodType2.init(inst, def);
|
|
@@ -15529,6 +15659,46 @@ function preprocess(fn, schema) {
|
|
|
15529
15659
|
return pipe(transform(fn), schema);
|
|
15530
15660
|
}
|
|
15531
15661
|
|
|
15662
|
+
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/compat.js
|
|
15663
|
+
var ZodIssueCode2 = {
|
|
15664
|
+
invalid_type: "invalid_type",
|
|
15665
|
+
too_big: "too_big",
|
|
15666
|
+
too_small: "too_small",
|
|
15667
|
+
invalid_format: "invalid_format",
|
|
15668
|
+
not_multiple_of: "not_multiple_of",
|
|
15669
|
+
unrecognized_keys: "unrecognized_keys",
|
|
15670
|
+
invalid_union: "invalid_union",
|
|
15671
|
+
invalid_key: "invalid_key",
|
|
15672
|
+
invalid_element: "invalid_element",
|
|
15673
|
+
invalid_value: "invalid_value",
|
|
15674
|
+
custom: "custom"
|
|
15675
|
+
};
|
|
15676
|
+
|
|
15677
|
+
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/coerce.js
|
|
15678
|
+
var coerce_exports2 = {};
|
|
15679
|
+
__export(coerce_exports2, {
|
|
15680
|
+
bigint: () => bigint2,
|
|
15681
|
+
boolean: () => boolean3,
|
|
15682
|
+
date: () => date3,
|
|
15683
|
+
number: () => number3,
|
|
15684
|
+
string: () => string3
|
|
15685
|
+
});
|
|
15686
|
+
function string3(params) {
|
|
15687
|
+
return _coercedString(ZodString2, params);
|
|
15688
|
+
}
|
|
15689
|
+
function number3(params) {
|
|
15690
|
+
return _coercedNumber(ZodNumber2, params);
|
|
15691
|
+
}
|
|
15692
|
+
function boolean3(params) {
|
|
15693
|
+
return _coercedBoolean(ZodBoolean2, params);
|
|
15694
|
+
}
|
|
15695
|
+
function bigint2(params) {
|
|
15696
|
+
return _coercedBigint(ZodBigInt2, params);
|
|
15697
|
+
}
|
|
15698
|
+
function date3(params) {
|
|
15699
|
+
return _coercedDate(ZodDate2, params);
|
|
15700
|
+
}
|
|
15701
|
+
|
|
15532
15702
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/external.js
|
|
15533
15703
|
config(en_default2());
|
|
15534
15704
|
|
|
@@ -15928,6 +16098,7 @@ var InitializedNotificationSchema = NotificationSchema.extend({
|
|
|
15928
16098
|
method: literal("notifications/initialized"),
|
|
15929
16099
|
params: NotificationsParamsSchema.optional()
|
|
15930
16100
|
});
|
|
16101
|
+
var isInitializedNotification = (value) => InitializedNotificationSchema.safeParse(value).success;
|
|
15931
16102
|
var PingRequestSchema = RequestSchema.extend({
|
|
15932
16103
|
method: literal("ping"),
|
|
15933
16104
|
params: BaseRequestParamsSchema.optional()
|
|
@@ -20955,7 +21126,7 @@ var newHeadersFromIncoming = (incoming) => {
|
|
|
20955
21126
|
return new Headers(headerRecord);
|
|
20956
21127
|
};
|
|
20957
21128
|
var wrapBodyStream = /* @__PURE__ */ Symbol("wrapBodyStream");
|
|
20958
|
-
var newRequestFromIncoming = (method,
|
|
21129
|
+
var newRequestFromIncoming = (method, url2, headers, incoming, abortController) => {
|
|
20959
21130
|
const init = {
|
|
20960
21131
|
method,
|
|
20961
21132
|
headers,
|
|
@@ -20963,7 +21134,7 @@ var newRequestFromIncoming = (method, url, headers, incoming, abortController) =
|
|
|
20963
21134
|
};
|
|
20964
21135
|
if (method === "TRACE") {
|
|
20965
21136
|
init.method = "GET";
|
|
20966
|
-
const req = new Request(
|
|
21137
|
+
const req = new Request(url2, init);
|
|
20967
21138
|
Object.defineProperty(req, "method", {
|
|
20968
21139
|
get() {
|
|
20969
21140
|
return "TRACE";
|
|
@@ -21000,7 +21171,7 @@ var newRequestFromIncoming = (method, url, headers, incoming, abortController) =
|
|
|
21000
21171
|
init.body = import_stream.Readable.toWeb(incoming);
|
|
21001
21172
|
}
|
|
21002
21173
|
}
|
|
21003
|
-
return new Request(
|
|
21174
|
+
return new Request(url2, init);
|
|
21004
21175
|
};
|
|
21005
21176
|
var getRequestCache = /* @__PURE__ */ Symbol("getRequestCache");
|
|
21006
21177
|
var requestCache = /* @__PURE__ */ Symbol("requestCache");
|
|
@@ -21072,8 +21243,8 @@ var newRequest = (incoming, defaultHostname) => {
|
|
|
21072
21243
|
throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
|
|
21073
21244
|
}
|
|
21074
21245
|
try {
|
|
21075
|
-
const
|
|
21076
|
-
req[urlKey] =
|
|
21246
|
+
const url22 = new URL(incomingUrl);
|
|
21247
|
+
req[urlKey] = url22.href;
|
|
21077
21248
|
} catch (e) {
|
|
21078
21249
|
throw new RequestError("Invalid absolute URL", { cause: e });
|
|
21079
21250
|
}
|
|
@@ -21092,11 +21263,11 @@ var newRequest = (incoming, defaultHostname) => {
|
|
|
21092
21263
|
} else {
|
|
21093
21264
|
scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
|
|
21094
21265
|
}
|
|
21095
|
-
const
|
|
21096
|
-
if (
|
|
21266
|
+
const url2 = new URL(`${scheme}://${host}${incomingUrl}`);
|
|
21267
|
+
if (url2.hostname.length !== host.length && url2.hostname !== host.replace(/:\d+$/, "")) {
|
|
21097
21268
|
throw new RequestError("Invalid host header");
|
|
21098
21269
|
}
|
|
21099
|
-
req[urlKey] =
|
|
21270
|
+
req[urlKey] = url2.href;
|
|
21100
21271
|
return req;
|
|
21101
21272
|
};
|
|
21102
21273
|
var responseCache = /* @__PURE__ */ Symbol("responseCache");
|
|
@@ -21132,14 +21303,14 @@ var Response2 = class _Response {
|
|
|
21132
21303
|
}
|
|
21133
21304
|
}
|
|
21134
21305
|
get headers() {
|
|
21135
|
-
const
|
|
21136
|
-
if (
|
|
21137
|
-
if (!(
|
|
21138
|
-
|
|
21139
|
-
|
|
21306
|
+
const cache2 = this[cacheKey];
|
|
21307
|
+
if (cache2) {
|
|
21308
|
+
if (!(cache2[2] instanceof Headers)) {
|
|
21309
|
+
cache2[2] = new Headers(
|
|
21310
|
+
cache2[2] || { "content-type": "text/plain; charset=UTF-8" }
|
|
21140
21311
|
);
|
|
21141
21312
|
}
|
|
21142
|
-
return
|
|
21313
|
+
return cache2[2];
|
|
21143
21314
|
}
|
|
21144
21315
|
return this[getResponseCache]().headers;
|
|
21145
21316
|
}
|
|
@@ -21243,16 +21414,16 @@ var handleFetchError = (e) => new Response(null, {
|
|
|
21243
21414
|
status: e instanceof Error && (e.name === "TimeoutError" || e.constructor.name === "TimeoutError") ? 504 : 500
|
|
21244
21415
|
});
|
|
21245
21416
|
var handleResponseError = (e, outgoing) => {
|
|
21246
|
-
const
|
|
21247
|
-
if (
|
|
21417
|
+
const err6 = e instanceof Error ? e : new Error("unknown error", { cause: e });
|
|
21418
|
+
if (err6.code === "ERR_STREAM_PREMATURE_CLOSE") {
|
|
21248
21419
|
console.info("The user aborted a request.");
|
|
21249
21420
|
} else {
|
|
21250
21421
|
console.error(e);
|
|
21251
21422
|
if (!outgoing.headersSent) {
|
|
21252
21423
|
outgoing.writeHead(500, { "Content-Type": "text/plain" });
|
|
21253
21424
|
}
|
|
21254
|
-
outgoing.end(`Error: ${
|
|
21255
|
-
outgoing.destroy(
|
|
21425
|
+
outgoing.end(`Error: ${err6.message}`);
|
|
21426
|
+
outgoing.destroy(err6);
|
|
21256
21427
|
}
|
|
21257
21428
|
};
|
|
21258
21429
|
var flushHeaders = (outgoing) => {
|
|
@@ -21309,8 +21480,8 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
|
21309
21480
|
if (options.errorHandler) {
|
|
21310
21481
|
try {
|
|
21311
21482
|
res = await res;
|
|
21312
|
-
} catch (
|
|
21313
|
-
const errRes = await options.errorHandler(
|
|
21483
|
+
} catch (err6) {
|
|
21484
|
+
const errRes = await options.errorHandler(err6);
|
|
21314
21485
|
if (!errRes) {
|
|
21315
21486
|
return;
|
|
21316
21487
|
}
|
|
@@ -22271,12 +22442,12 @@ function workspacePath(ctx, suffix = "") {
|
|
|
22271
22442
|
return `${base}/api/workspaces/${ctx.workspaceId}${suffix}`;
|
|
22272
22443
|
}
|
|
22273
22444
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
22274
|
-
async function request(ctx, method,
|
|
22445
|
+
async function request(ctx, method, url2, body, opts) {
|
|
22275
22446
|
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
22276
22447
|
const controller = new AbortController();
|
|
22277
22448
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
22278
22449
|
try {
|
|
22279
|
-
const res = await fetch(
|
|
22450
|
+
const res = await fetch(url2, {
|
|
22280
22451
|
method,
|
|
22281
22452
|
headers: {
|
|
22282
22453
|
"Authorization": `Bearer ${ctx.token}`,
|
|
@@ -22300,19 +22471,23 @@ async function request(ctx, method, url, body, opts) {
|
|
|
22300
22471
|
throw new Error(message || `HTTP ${res.status}`);
|
|
22301
22472
|
}
|
|
22302
22473
|
return res.json();
|
|
22303
|
-
} catch (
|
|
22474
|
+
} catch (err6) {
|
|
22304
22475
|
clearTimeout(timer);
|
|
22305
|
-
if (
|
|
22306
|
-
throw new Error(`Request timed out after ${timeoutMs}ms: ${method} ${
|
|
22476
|
+
if (err6 instanceof Error && err6.name === "AbortError") {
|
|
22477
|
+
throw new Error(`Request timed out after ${timeoutMs}ms: ${method} ${url2}`);
|
|
22307
22478
|
}
|
|
22308
|
-
throw
|
|
22479
|
+
throw err6;
|
|
22309
22480
|
}
|
|
22310
22481
|
}
|
|
22311
22482
|
async function getProject(ctx) {
|
|
22312
22483
|
return request(ctx, "GET", projectPath(ctx));
|
|
22313
22484
|
}
|
|
22485
|
+
async function getProjectDigest(ctx) {
|
|
22486
|
+
return request(ctx, "GET", projectPath(ctx, "/digest"));
|
|
22487
|
+
}
|
|
22314
22488
|
async function updateProject(ctx, description) {
|
|
22315
|
-
|
|
22489
|
+
const res = await request(ctx, "PATCH", projectPath(ctx), { description });
|
|
22490
|
+
return res.project;
|
|
22316
22491
|
}
|
|
22317
22492
|
async function getTodos(ctx, scope) {
|
|
22318
22493
|
const qs = scope === "active" ? "?scope=active" : "";
|
|
@@ -22341,8 +22516,8 @@ async function getProjectHistory(ctx, limit) {
|
|
|
22341
22516
|
}
|
|
22342
22517
|
async function getMyAssignment(ctx) {
|
|
22343
22518
|
if (!ctx.agentId) throw new Error("agentId not set in BridgeContext");
|
|
22344
|
-
const
|
|
22345
|
-
return request(ctx, "GET",
|
|
22519
|
+
const url2 = `${projectPath(ctx, "/assignment")}?agentId=${encodeURIComponent(ctx.agentId)}`;
|
|
22520
|
+
return request(ctx, "GET", url2);
|
|
22346
22521
|
}
|
|
22347
22522
|
async function completeMyTask(ctx, todoId) {
|
|
22348
22523
|
return request(ctx, "POST", projectPath(ctx, `/todos/${todoId}/done`));
|
|
@@ -22386,15 +22561,18 @@ async function spawnAgent(ctx, agentKey, daemonId, role, cmd, model) {
|
|
|
22386
22561
|
}
|
|
22387
22562
|
async function killAgent(ctx, agentId) {
|
|
22388
22563
|
const base = ctx.serverUrl.replace(/\/$/, "");
|
|
22389
|
-
const
|
|
22390
|
-
return request(ctx, "DELETE",
|
|
22564
|
+
const url2 = ctx.projectId && ctx.projectId !== "workspace" ? `${base}/api/workspaces/${ctx.workspaceId}/projects/${ctx.projectId}/agents/${agentId}` : `${base}/api/workspaces/${ctx.workspaceId}/agents/${agentId}`;
|
|
22565
|
+
return request(ctx, "DELETE", url2);
|
|
22391
22566
|
}
|
|
22392
22567
|
async function assignTask(ctx, todoId, agentId) {
|
|
22393
22568
|
return request(ctx, "POST", projectPath(ctx, `/todos/${todoId}/assign`), { agentId });
|
|
22394
22569
|
}
|
|
22395
|
-
async function getAgentOutput(ctx, agentId, lines) {
|
|
22396
|
-
const
|
|
22397
|
-
|
|
22570
|
+
async function getAgentOutput(ctx, agentId, lines, cursor) {
|
|
22571
|
+
const params = new URLSearchParams();
|
|
22572
|
+
if (lines !== void 0) params.set("lines", String(lines));
|
|
22573
|
+
if (cursor) params.set("cursor", cursor);
|
|
22574
|
+
const qs = params.toString();
|
|
22575
|
+
return request(ctx, "GET", projectPath(ctx, `/panels/${agentId}/output${qs ? `?${qs}` : ""}`));
|
|
22398
22576
|
}
|
|
22399
22577
|
async function sendAgentInput(ctx, agentId, text) {
|
|
22400
22578
|
return request(ctx, "POST", workspacePath(ctx, `/agents/${agentId}/input`), { text });
|
|
@@ -22406,11 +22584,11 @@ async function recordProjectEvent(ctx, params) {
|
|
|
22406
22584
|
const { projectId, ...body } = params;
|
|
22407
22585
|
const explicitProjectId = projectId?.trim();
|
|
22408
22586
|
const isWorkspaceScope = ctx.projectId === "workspace" && !explicitProjectId;
|
|
22409
|
-
const
|
|
22587
|
+
const url2 = isWorkspaceScope ? workspacePath(ctx, "/events") : projectPath(ctx, "/events", explicitProjectId);
|
|
22410
22588
|
return request(
|
|
22411
22589
|
ctx,
|
|
22412
22590
|
"POST",
|
|
22413
|
-
|
|
22591
|
+
url2,
|
|
22414
22592
|
{ ...body, agentId: ctx.agentId }
|
|
22415
22593
|
);
|
|
22416
22594
|
}
|
|
@@ -22484,14 +22662,16 @@ async function applyPersona(ctx, params) {
|
|
|
22484
22662
|
});
|
|
22485
22663
|
}
|
|
22486
22664
|
async function listRolePrompts(ctx) {
|
|
22487
|
-
|
|
22665
|
+
const qs = ctx.projectId ? `?projectId=${encodeURIComponent(ctx.projectId)}` : "";
|
|
22666
|
+
return request(ctx, "GET", workspacePath(ctx, `/prompts${qs}`));
|
|
22488
22667
|
}
|
|
22489
22668
|
async function getRolePrompt(ctx, role) {
|
|
22490
22669
|
const start = Date.now();
|
|
22670
|
+
const qs = ctx.projectId ? `?projectId=${encodeURIComponent(ctx.projectId)}` : "";
|
|
22491
22671
|
const res = await request(
|
|
22492
22672
|
ctx,
|
|
22493
22673
|
"GET",
|
|
22494
|
-
workspacePath(ctx, `/prompts/${encodeURIComponent(role)}`)
|
|
22674
|
+
workspacePath(ctx, `/prompts/${encodeURIComponent(role)}${qs}`)
|
|
22495
22675
|
);
|
|
22496
22676
|
const latencyMs = Date.now() - start;
|
|
22497
22677
|
const bytes = res.content.length;
|
|
@@ -22533,9 +22713,37 @@ function registerPlanTools(server, ctx) {
|
|
|
22533
22713
|
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
22534
22714
|
}
|
|
22535
22715
|
);
|
|
22716
|
+
server.tool(
|
|
22717
|
+
"bridge_get_blueprint",
|
|
22718
|
+
"Get the project blueprint \u2014 the architecture/conventions/features/decisions markdown doc for this project. Returns { blueprint, updatedAt }; updatedAt is null when the blueprint was never seeded.",
|
|
22719
|
+
{},
|
|
22720
|
+
async () => {
|
|
22721
|
+
const project = await getProject(ctx);
|
|
22722
|
+
return {
|
|
22723
|
+
content: [{
|
|
22724
|
+
type: "text",
|
|
22725
|
+
text: JSON.stringify({ blueprint: project.description ?? "", updatedAt: project.blueprintUpdatedAt ?? null })
|
|
22726
|
+
}]
|
|
22727
|
+
};
|
|
22728
|
+
}
|
|
22729
|
+
);
|
|
22730
|
+
server.tool(
|
|
22731
|
+
"bridge_update_blueprint",
|
|
22732
|
+
"Update the project blueprint markdown doc. Stored as the project description and immediately reflected in the Bridge UI. Returns { ok, blueprint, updatedAt }.",
|
|
22733
|
+
{ content: external_exports.string().describe("New blueprint content in Markdown") },
|
|
22734
|
+
async ({ content }) => {
|
|
22735
|
+
const project = await updateProject(ctx, content);
|
|
22736
|
+
return {
|
|
22737
|
+
content: [{
|
|
22738
|
+
type: "text",
|
|
22739
|
+
text: JSON.stringify({ ok: true, blueprint: project.description ?? "", updatedAt: project.blueprintUpdatedAt ?? null })
|
|
22740
|
+
}]
|
|
22741
|
+
};
|
|
22742
|
+
}
|
|
22743
|
+
);
|
|
22536
22744
|
server.tool(
|
|
22537
22745
|
"bridge_get_plan",
|
|
22538
|
-
"Get the current plan / spec for this Bridge project
|
|
22746
|
+
"DEPRECATED \u2014 use bridge_get_blueprint. Get the current plan / spec for this Bridge project (legacy { plan } response shape).",
|
|
22539
22747
|
{},
|
|
22540
22748
|
async () => {
|
|
22541
22749
|
const project = await getProject(ctx);
|
|
@@ -22549,14 +22757,14 @@ function registerPlanTools(server, ctx) {
|
|
|
22549
22757
|
);
|
|
22550
22758
|
server.tool(
|
|
22551
22759
|
"bridge_update_plan",
|
|
22552
|
-
"Update the plan / spec for this Bridge project
|
|
22760
|
+
"DEPRECATED \u2014 use bridge_update_blueprint. Update the plan / spec for this Bridge project (legacy response shape).",
|
|
22553
22761
|
{ content: external_exports.string().describe("New plan content in Markdown") },
|
|
22554
22762
|
async ({ content }) => {
|
|
22555
|
-
|
|
22763
|
+
await updateProject(ctx, content);
|
|
22556
22764
|
return {
|
|
22557
22765
|
content: [{
|
|
22558
22766
|
type: "text",
|
|
22559
|
-
text: JSON.stringify(
|
|
22767
|
+
text: JSON.stringify({ ok: true })
|
|
22560
22768
|
}]
|
|
22561
22769
|
};
|
|
22562
22770
|
}
|
|
@@ -22672,65 +22880,89 @@ var EVENT_ROLES = [...AGENT_ROLES, "system"];
|
|
|
22672
22880
|
// ../shared/dist/tool-registry.js
|
|
22673
22881
|
var BRIDGE_TOOL_DOCS = {
|
|
22674
22882
|
// Project / plan
|
|
22675
|
-
bridge_get_project: "Project metadata
|
|
22676
|
-
|
|
22677
|
-
|
|
22678
|
-
|
|
22679
|
-
|
|
22883
|
+
bridge_get_project: "Project metadata (name, cwd, machineId)",
|
|
22884
|
+
bridge_get_project_digest: "Repo file-tree digest (capped), on demand",
|
|
22885
|
+
bridge_get_blueprint: "Read project blueprint doc ({blueprint, updatedAt})",
|
|
22886
|
+
bridge_update_blueprint: "Update project blueprint doc",
|
|
22887
|
+
bridge_get_project_history: "Past runs + failure patterns",
|
|
22888
|
+
bridge_get_execution_status: "Run history + todo completion counts",
|
|
22680
22889
|
// Todos
|
|
22681
|
-
bridge_get_todos: "List todos + session state
|
|
22682
|
-
bridge_add_todo: "Create
|
|
22683
|
-
bridge_update_todo: "Update
|
|
22684
|
-
bridge_cancel_run: "Cancel active run (
|
|
22890
|
+
bridge_get_todos: "List todos + session state",
|
|
22891
|
+
bridge_add_todo: "Create todo (title, todoType, dependsOn)",
|
|
22892
|
+
bridge_update_todo: "Update todo title/status",
|
|
22893
|
+
bridge_cancel_run: "Cancel active run (before restarting a stale plan)",
|
|
22685
22894
|
// Panel management
|
|
22686
|
-
bridge_list_agents: "All agents: role, status, inRun
|
|
22687
|
-
bridge_get_agent_status: "Single agent status
|
|
22688
|
-
bridge_spawn_worker: "Spawn
|
|
22689
|
-
bridge_kill_agent: "Terminate
|
|
22690
|
-
bridge_get_agent_output: "Read terminal output
|
|
22691
|
-
bridge_send_input: "Send text input to
|
|
22895
|
+
bridge_list_agents: "All agents: role, status, inRun",
|
|
22896
|
+
bridge_get_agent_status: "Single agent status",
|
|
22897
|
+
bridge_spawn_worker: "Spawn worker (agentKey, role)",
|
|
22898
|
+
bridge_kill_agent: "Terminate stuck/dead agent",
|
|
22899
|
+
bridge_get_agent_output: "Read agent terminal output (round-trip cursor = delta read)",
|
|
22900
|
+
bridge_send_input: "Send text input to agent PTY",
|
|
22692
22901
|
// Worker task lifecycle
|
|
22693
|
-
bridge_get_my_task: "
|
|
22902
|
+
bridge_get_my_task: "This agent's assigned task",
|
|
22694
22903
|
bridge_complete_task: "Signal task completion",
|
|
22695
|
-
bridge_fail_task: "Signal
|
|
22696
|
-
bridge_get_todo_context: "Read todo output/error
|
|
22697
|
-
bridge_assign_task: "Assign
|
|
22904
|
+
bridge_fail_task: "Signal failure with reason",
|
|
22905
|
+
bridge_get_todo_context: "Read a todo's output/error",
|
|
22906
|
+
bridge_assign_task: "Assign pending todo to an agent",
|
|
22698
22907
|
// Workspace scope (Phase 6)
|
|
22699
|
-
bridge_list_groups: "
|
|
22700
|
-
bridge_get_group_status: "
|
|
22701
|
-
bridge_dispatch_to_group: "Send
|
|
22702
|
-
|
|
22703
|
-
|
|
22704
|
-
|
|
22705
|
-
|
|
22706
|
-
|
|
22908
|
+
bridge_list_groups: "Groups + member agentIds",
|
|
22909
|
+
bridge_get_group_status: "Group agents: status + last output line",
|
|
22910
|
+
bridge_dispatch_to_group: "Send message to every agent in a group",
|
|
22911
|
+
bridge_create_group: "Create group (name, optional color)",
|
|
22912
|
+
bridge_update_group: "Rename/recolor a group",
|
|
22913
|
+
bridge_delete_group: "Delete a group",
|
|
22914
|
+
bridge_assign_agent_to_group: "Move agent into a group, or remove (groupId: null); orchestrators cannot join",
|
|
22915
|
+
bridge_list_workspace_projects: "Workspace projects: name, cwd, active run count",
|
|
22916
|
+
bridge_query_workspace: "Natural-language query of orchestration state",
|
|
22917
|
+
bridge_list_active_runs: "Active runs across workspace projects",
|
|
22918
|
+
bridge_peek_panel: "Read any panel output workspace-wide (cursor = delta read)",
|
|
22919
|
+
bridge_status_panel: "Status of any panel workspace-wide",
|
|
22707
22920
|
// Personas
|
|
22708
|
-
bridge_get_persona: "
|
|
22709
|
-
bridge_list_personas: "
|
|
22710
|
-
bridge_create_persona: "Create
|
|
22711
|
-
bridge_update_persona: "Update persona
|
|
22712
|
-
bridge_archive_persona: "Archive
|
|
22713
|
-
bridge_launch_persona: "Spawn
|
|
22714
|
-
bridge_apply_persona: "Apply persona
|
|
22921
|
+
bridge_get_persona: "Persona by id (name, systemPrompt, role, agentKey)",
|
|
22922
|
+
bridge_list_personas: "Visible personas (workspace + personal)",
|
|
22923
|
+
bridge_create_persona: "Create persona",
|
|
22924
|
+
bridge_update_persona: "Update persona fields",
|
|
22925
|
+
bridge_archive_persona: "Archive a persona",
|
|
22926
|
+
bridge_launch_persona: "Spawn worker with a persona",
|
|
22927
|
+
bridge_apply_persona: "Apply persona to a running worker",
|
|
22928
|
+
// Group Schemas (reusable team templates)
|
|
22929
|
+
bridge_list_group_schemas: "Reusable team/group schema templates",
|
|
22930
|
+
bridge_create_group_schema: "Create group schema from current groups",
|
|
22931
|
+
bridge_update_group_schema: "Update a group schema (name/slug/desc/color/groups/shared)",
|
|
22932
|
+
bridge_apply_group_schema: "Spawn a schema's groups and agents",
|
|
22933
|
+
// Agent Model Info
|
|
22934
|
+
bridge_list_agent_models: "Available models for an agent key on a daemon",
|
|
22715
22935
|
// Messaging
|
|
22716
|
-
bridge_send_message: "
|
|
22717
|
-
bridge_poll_messages: "Poll unread messages
|
|
22936
|
+
bridge_send_message: "Direct message to a peer agent",
|
|
22937
|
+
bridge_poll_messages: "Poll unread messages for this agent",
|
|
22718
22938
|
// Role Prompts
|
|
22719
|
-
bridge_list_role_prompts: "
|
|
22720
|
-
bridge_get_role_prompt: "Fetch resolved
|
|
22721
|
-
bridge_update_role_prompt: "Update custom role prompt
|
|
22722
|
-
bridge_delete_role_prompt: "Delete custom role prompt
|
|
22723
|
-
|
|
22724
|
-
|
|
22725
|
-
|
|
22726
|
-
|
|
22727
|
-
|
|
22728
|
-
|
|
22939
|
+
bridge_list_role_prompts: "Role prompt templates",
|
|
22940
|
+
bridge_get_role_prompt: "Fetch resolved role prompt",
|
|
22941
|
+
bridge_update_role_prompt: "Update custom role prompt",
|
|
22942
|
+
bridge_delete_role_prompt: "Delete custom role prompt",
|
|
22943
|
+
bridge_update_todo_status: "Update todo status only",
|
|
22944
|
+
// Codegraph (structural code intelligence — PREFER over Read/Grep for structure)
|
|
22945
|
+
bridge_codegraph_status: "Codegraph index status + resolution coverage",
|
|
22946
|
+
bridge_codegraph_index: "Index/refresh a project for codegraph",
|
|
22947
|
+
bridge_codegraph_find_symbol: "Find a symbol by name (where is X)",
|
|
22948
|
+
bridge_codegraph_file_outline: "Structural outline of a single file",
|
|
22949
|
+
bridge_codegraph_find_references: "All call/reference sites of a symbol (who calls X)",
|
|
22950
|
+
bridge_codegraph_call_graph: "Call graph (in/out/both) around a symbol",
|
|
22951
|
+
bridge_codegraph_get_symbol_source: "Source snippet of a qualified symbol",
|
|
22952
|
+
bridge_codegraph_diff_impact: "Blast-radius of a git diff (changed exported symbols + transitive callers)"
|
|
22729
22953
|
};
|
|
22730
22954
|
if (Object.keys(BRIDGE_TOOL_DOCS).length === 0) {
|
|
22731
22955
|
throw new Error("BRIDGE_TOOL_DOCS registry is empty at module load \u2014 fail fast");
|
|
22732
22956
|
}
|
|
22733
22957
|
|
|
22958
|
+
// ../shared/dist/blueprint.js
|
|
22959
|
+
var BLUEPRINT_H1_AREAS = ["Frontend", "Backend", "Other"];
|
|
22960
|
+
var BLUEPRINT_H2_ASPECTS = ["Architecture", "Conventions", "Features", "Decisions"];
|
|
22961
|
+
var BLUEPRINT_DOC_TEMPLATE = BLUEPRINT_H1_AREAS.map((area) => `# ${area}
|
|
22962
|
+
|
|
22963
|
+
` + BLUEPRINT_H2_ASPECTS.map((aspect) => `## ${aspect}
|
|
22964
|
+
`).join("\n")).join("\n");
|
|
22965
|
+
|
|
22734
22966
|
// ../mcp-server/src/tools/orchestration.ts
|
|
22735
22967
|
function ok(data) {
|
|
22736
22968
|
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
@@ -22815,12 +23047,13 @@ function registerOrchestrationTools(server, ctx) {
|
|
|
22815
23047
|
);
|
|
22816
23048
|
server.tool(
|
|
22817
23049
|
"bridge_get_agent_output",
|
|
22818
|
-
"Read the last N lines of a panel's terminal output (ANSI codes stripped). Use this to check a dev server for errors, verify a build succeeded, or read a shell panel's result. Works on any agent type \u2014 dev servers, shells, AI agents.",
|
|
23050
|
+
"Read the last N lines of a panel's terminal output (ANSI codes stripped). Returns { output, cursor, cursor_reset }. Round-trip the returned cursor on the next call to get only new output (delta) \u2014 omit it for a full tail. cursor_reset: true means the cursor went stale (buffer evicted or panel respawned) and a full tail was returned. Use this to check a dev server for errors, verify a build succeeded, or read a shell panel's result. Works on any agent type \u2014 dev servers, shells, AI agents.",
|
|
22819
23051
|
{
|
|
22820
23052
|
agentId: external_exports.string().describe("The agent ID to read"),
|
|
22821
|
-
lines: external_exports.number().int().min(1).max(300).optional().describe("Trailing lines
|
|
23053
|
+
lines: external_exports.number().int().min(1).max(300).optional().describe("Trailing lines for full-tail reads (default 50, max 300); delta reads return all new lines"),
|
|
23054
|
+
cursor: external_exports.string().optional().describe("Opaque cursor from a previous response \u2014 pass it back to receive only new output since that read")
|
|
22822
23055
|
},
|
|
22823
|
-
({ agentId, lines }) => safe(() => getAgentOutput(ctx, agentId, lines))
|
|
23056
|
+
({ agentId, lines, cursor }) => safe(() => getAgentOutput(ctx, agentId, lines, cursor))
|
|
22824
23057
|
);
|
|
22825
23058
|
server.tool(
|
|
22826
23059
|
"bridge_send_input",
|
|
@@ -22986,6 +23219,12 @@ function registerWorkspaceTools(server, ctx) {
|
|
|
22986
23219
|
{},
|
|
22987
23220
|
() => safe2(() => getProject(ctx))
|
|
22988
23221
|
);
|
|
23222
|
+
server.tool(
|
|
23223
|
+
"bridge_get_project_digest",
|
|
23224
|
+
"Get the repository file-tree digest for the current project (capped to preserve context budget). Use on demand for codebase orientation instead of expecting it at startup.",
|
|
23225
|
+
{},
|
|
23226
|
+
() => safe2(() => getProjectDigest(ctx))
|
|
23227
|
+
);
|
|
22989
23228
|
server.tool(
|
|
22990
23229
|
"bridge_query_workspace",
|
|
22991
23230
|
"Natural-language query about orchestration state (runs, todos, failures). No LLM involved \u2014 deterministic answer.",
|
|
@@ -23000,12 +23239,19 @@ function registerWorkspaceTools(server, ctx) {
|
|
|
23000
23239
|
);
|
|
23001
23240
|
server.tool(
|
|
23002
23241
|
"bridge_peek_panel",
|
|
23003
|
-
"Read the last N lines of a panel's terminal output. Project-scoped contexts may only peek at their own project's panels (403 cross_project_block otherwise); workspace scope has no project boundary. Use this to check what a specific agent is doing.",
|
|
23242
|
+
"Read the last N lines of a panel's terminal output. Project-scoped contexts may only peek at their own project's panels (403 cross_project_block otherwise); workspace scope has no project boundary. Use this to check what a specific agent is doing. Returns { output, cursor, cursor_reset } \u2014 round-trip the cursor on the next call to get only new output (delta); omit it for a full tail.",
|
|
23004
23243
|
{
|
|
23005
23244
|
agentId: external_exports.string().describe("The panel/agent ID to peek at"),
|
|
23006
|
-
lines: external_exports.number().int().min(1).max(300).optional().describe("Trailing lines
|
|
23245
|
+
lines: external_exports.number().int().min(1).max(300).optional().describe("Trailing lines for full-tail reads (default 50, max 300); delta reads return all new lines"),
|
|
23246
|
+
cursor: external_exports.string().optional().describe("Opaque cursor from a previous response \u2014 pass it back to receive only new output since that read")
|
|
23007
23247
|
},
|
|
23008
|
-
({ agentId, lines }) => safe2(() =>
|
|
23248
|
+
({ agentId, lines, cursor }) => safe2(() => {
|
|
23249
|
+
const params = new URLSearchParams();
|
|
23250
|
+
if (lines !== void 0) params.set("lines", String(lines));
|
|
23251
|
+
if (cursor) params.set("cursor", cursor);
|
|
23252
|
+
const qs = params.toString();
|
|
23253
|
+
return request(ctx, "GET", workspacePath(ctx, `/agents/${agentId}/output${qs ? `?${qs}` : ""}`));
|
|
23254
|
+
})
|
|
23009
23255
|
);
|
|
23010
23256
|
server.tool(
|
|
23011
23257
|
"bridge_status_panel",
|
|
@@ -23013,6 +23259,49 @@ function registerWorkspaceTools(server, ctx) {
|
|
|
23013
23259
|
{ agentId: external_exports.string().describe("The panel/agent ID to inspect") },
|
|
23014
23260
|
({ agentId }) => safe2(() => request(ctx, "GET", workspacePath(ctx, `/agents/${agentId}`)))
|
|
23015
23261
|
);
|
|
23262
|
+
server.tool(
|
|
23263
|
+
"bridge_create_group",
|
|
23264
|
+
"Create a new agent group in the current project with an optional color.",
|
|
23265
|
+
{
|
|
23266
|
+
name: external_exports.string().min(1).max(64).describe("Human-readable group name"),
|
|
23267
|
+
color: external_exports.string().regex(/^#[0-9a-fA-F]{6}$/).optional().describe("Hex color e.g. #6366f1")
|
|
23268
|
+
},
|
|
23269
|
+
({ name, color }) => safe2(() => {
|
|
23270
|
+
if (!ctx.projectId) throw new Error("Project-scoped context required");
|
|
23271
|
+
return request(ctx, "POST", workspacePath(ctx, `/projects/${ctx.projectId}/groups`), { name, color });
|
|
23272
|
+
})
|
|
23273
|
+
);
|
|
23274
|
+
server.tool(
|
|
23275
|
+
"bridge_update_group",
|
|
23276
|
+
"Rename or recolor an existing agent group.",
|
|
23277
|
+
{
|
|
23278
|
+
groupId: external_exports.string().describe("The group ID to update"),
|
|
23279
|
+
name: external_exports.string().min(1).max(64).optional().describe("New group name"),
|
|
23280
|
+
color: external_exports.string().regex(/^#[0-9a-fA-F]{6}$/).optional().describe("New hex color e.g. #6366f1")
|
|
23281
|
+
},
|
|
23282
|
+
({ groupId, name, color }) => safe2(() => {
|
|
23283
|
+
if (!ctx.projectId) throw new Error("Project-scoped context required");
|
|
23284
|
+
return request(ctx, "PATCH", workspacePath(ctx, `/projects/${ctx.projectId}/groups/${groupId}`), { name, color });
|
|
23285
|
+
})
|
|
23286
|
+
);
|
|
23287
|
+
server.tool(
|
|
23288
|
+
"bridge_assign_agent_to_group",
|
|
23289
|
+
"Assign a running agent to a group (team), or remove it with groupId:null. Orchestrator panels cannot join groups. Project-scoped context required; the group must already exist (use bridge_create_group first).",
|
|
23290
|
+
{ agentId: external_exports.string().min(1), groupId: external_exports.string().nullable() },
|
|
23291
|
+
({ agentId, groupId }) => safe2(() => {
|
|
23292
|
+
if (!ctx.projectId) throw new Error("Project-scoped context required");
|
|
23293
|
+
return request(ctx, "PATCH", workspacePath(ctx, `/projects/${ctx.projectId}/agents/${agentId}/group`), { groupId });
|
|
23294
|
+
})
|
|
23295
|
+
);
|
|
23296
|
+
server.tool(
|
|
23297
|
+
"bridge_delete_group",
|
|
23298
|
+
"Delete an agent group. Members are detached but keep running.",
|
|
23299
|
+
{ groupId: external_exports.string().describe("The group ID to delete") },
|
|
23300
|
+
({ groupId }) => safe2(() => {
|
|
23301
|
+
if (!ctx.projectId) throw new Error("Project-scoped context required");
|
|
23302
|
+
return request(ctx, "DELETE", workspacePath(ctx, `/projects/${ctx.projectId}/groups/${groupId}`));
|
|
23303
|
+
})
|
|
23304
|
+
);
|
|
23016
23305
|
}
|
|
23017
23306
|
|
|
23018
23307
|
// ../mcp-server/src/tools/personas.ts
|
|
@@ -23188,17 +23477,2374 @@ function registerRolePromptTools(server, ctx) {
|
|
|
23188
23477
|
);
|
|
23189
23478
|
}
|
|
23190
23479
|
|
|
23191
|
-
// ../mcp-server/src/
|
|
23192
|
-
|
|
23193
|
-
|
|
23194
|
-
|
|
23195
|
-
|
|
23196
|
-
|
|
23197
|
-
|
|
23198
|
-
|
|
23199
|
-
|
|
23200
|
-
|
|
23201
|
-
|
|
23480
|
+
// ../mcp-server/src/tools/group-schemas.ts
|
|
23481
|
+
function ok5(data) {
|
|
23482
|
+
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
23483
|
+
}
|
|
23484
|
+
function err5(message) {
|
|
23485
|
+
return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: message }) }] };
|
|
23486
|
+
}
|
|
23487
|
+
async function safe5(fn) {
|
|
23488
|
+
try {
|
|
23489
|
+
return ok5(await fn());
|
|
23490
|
+
} catch (e) {
|
|
23491
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
23492
|
+
if (e instanceof Error && (e.name === "TypeError" || e.name === "ReferenceError")) {
|
|
23493
|
+
console.error("[mcp-bridge] unexpected error in group-schema tool handler", { name: e.name, message, stack: e.stack });
|
|
23494
|
+
}
|
|
23495
|
+
return err5(message);
|
|
23496
|
+
}
|
|
23497
|
+
}
|
|
23498
|
+
function registerGroupSchemaTools(server, ctx) {
|
|
23499
|
+
server.tool(
|
|
23500
|
+
"bridge_list_group_schemas",
|
|
23501
|
+
"List reusable team/group schema templates saved in this workspace. Returns name, slug, color, groupsJson payload, and metadata for each schema.",
|
|
23502
|
+
{
|
|
23503
|
+
scope: external_exports.enum(["personal", "workspace", "project"]).optional().describe("Scope filter"),
|
|
23504
|
+
projectId: external_exports.string().optional().describe("Filter to a specific project"),
|
|
23505
|
+
q: external_exports.string().optional().describe("Substring search on name")
|
|
23506
|
+
},
|
|
23507
|
+
({ scope, projectId, q }) => safe5(() => {
|
|
23508
|
+
let path = "/group-schemas";
|
|
23509
|
+
const params = new URLSearchParams();
|
|
23510
|
+
if (scope) params.set("scope", scope);
|
|
23511
|
+
if (projectId) params.set("projectId", projectId);
|
|
23512
|
+
if (q) params.set("q", q);
|
|
23513
|
+
const qs = params.toString();
|
|
23514
|
+
if (qs) path += "?" + qs;
|
|
23515
|
+
return request(ctx, "GET", workspacePath(ctx, path));
|
|
23516
|
+
})
|
|
23517
|
+
);
|
|
23518
|
+
server.tool(
|
|
23519
|
+
"bridge_apply_group_schema",
|
|
23520
|
+
"Apply a group schema template to spawn all its groups and agents in one call. Validates model availability against the target daemon. Returns created groups + agent IDs and any partial failures.",
|
|
23521
|
+
{
|
|
23522
|
+
schemaId: external_exports.string().describe("The group schema ID to apply"),
|
|
23523
|
+
projectId: external_exports.string().describe("Target project ID"),
|
|
23524
|
+
daemonId: external_exports.string().optional().describe("Target daemon ID (auto-resolves if omitted)"),
|
|
23525
|
+
mode: external_exports.enum(["auto-suffix", "replace"]).optional().describe("Name collision mode: auto-suffix (default) appends -2, -3, etc; replace reaps existing teams first")
|
|
23526
|
+
},
|
|
23527
|
+
({ schemaId, projectId, daemonId, mode }) => safe5(
|
|
23528
|
+
() => request(
|
|
23529
|
+
ctx,
|
|
23530
|
+
"POST",
|
|
23531
|
+
workspacePath(ctx, `/group-schemas/${schemaId}/apply`),
|
|
23532
|
+
{ projectId, daemonId, mode }
|
|
23533
|
+
)
|
|
23534
|
+
)
|
|
23535
|
+
);
|
|
23536
|
+
server.tool(
|
|
23537
|
+
"bridge_create_group_schema",
|
|
23538
|
+
"Create a reusable group schema template from the current project group setup. Serializes groups and agent slots into a template that can be applied later with bridge_apply_group_schema.",
|
|
23539
|
+
{
|
|
23540
|
+
name: external_exports.string().min(1).max(80).describe("Display name for the schema"),
|
|
23541
|
+
slug: external_exports.string().regex(/^[a-z][a-z0-9_]{1,62}$/).describe("Unique slug (lowercase, starts with letter, a-z0-9_ only, 2-63 chars)"),
|
|
23542
|
+
description: external_exports.string().max(200).optional().describe("Optional description"),
|
|
23543
|
+
color: external_exports.string().regex(/^#[0-9a-fA-F]{6}$/).optional().describe("Hex colour for the schema card"),
|
|
23544
|
+
groupsJson: external_exports.any().optional().describe("GroupSchemaPayload: { version:1, groups:[{name, color?, slots:[{agentKey, model?, role?, count, cmd?}]}] }"),
|
|
23545
|
+
scope: external_exports.enum(["personal", "workspace", "project"]).optional().describe("Visibility scope (default: workspace)"),
|
|
23546
|
+
projectId: external_exports.string().optional().describe("Project ID (required if scope=project)")
|
|
23547
|
+
},
|
|
23548
|
+
({ name, slug, description, color, groupsJson, scope, projectId }) => safe5(
|
|
23549
|
+
() => request(
|
|
23550
|
+
ctx,
|
|
23551
|
+
"POST",
|
|
23552
|
+
workspacePath(ctx, "/group-schemas"),
|
|
23553
|
+
{ name, slug, description, color, groupsJson, scope, projectId }
|
|
23554
|
+
)
|
|
23555
|
+
)
|
|
23556
|
+
);
|
|
23557
|
+
server.tool(
|
|
23558
|
+
"bridge_update_group_schema",
|
|
23559
|
+
"Update an existing (non-archived) group schema template. Pass schemaId plus only the fields to change (name, slug, description, color, groupsJson, shared). Returns the updated schema.",
|
|
23560
|
+
{
|
|
23561
|
+
schemaId: external_exports.string().describe("The group schema ID to update"),
|
|
23562
|
+
name: external_exports.string().min(1).max(80).optional().describe("New display name"),
|
|
23563
|
+
slug: external_exports.string().regex(/^[a-z][a-z0-9_]{1,62}$/).optional().describe("New unique slug (lowercase, starts with letter, a-z0-9_, 2-63 chars)"),
|
|
23564
|
+
description: external_exports.string().max(200).optional().describe("New description"),
|
|
23565
|
+
color: external_exports.string().regex(/^#[0-9a-fA-F]{6}$/).optional().describe("New hex colour e.g. #6366f1"),
|
|
23566
|
+
groupsJson: external_exports.any().optional().describe("Replacement GroupSchemaPayload: { version:1, groups:[{name, color?, slots:[{agentKey, model?, role?, count, cmd?}]}] }"),
|
|
23567
|
+
shared: external_exports.boolean().optional().describe("Workspace-scope only: mark the schema shared across the workspace")
|
|
23568
|
+
},
|
|
23569
|
+
({ schemaId, name, slug, description, color, groupsJson, shared }) => safe5(
|
|
23570
|
+
() => request(
|
|
23571
|
+
ctx,
|
|
23572
|
+
"PATCH",
|
|
23573
|
+
workspacePath(ctx, `/group-schemas/${schemaId}`),
|
|
23574
|
+
{ name, slug, description, color, groupsJson, shared }
|
|
23575
|
+
)
|
|
23576
|
+
)
|
|
23577
|
+
);
|
|
23578
|
+
server.tool(
|
|
23579
|
+
"bridge_list_agent_models",
|
|
23580
|
+
"List available models for an agent key on a target daemon. Validates model portability across machines; use before applying a group schema to verify required models exist.",
|
|
23581
|
+
{
|
|
23582
|
+
agentKey: external_exports.string().optional().describe("Filter by agent key (e.g. claude, kimi, qwen)"),
|
|
23583
|
+
daemonId: external_exports.string().optional().describe("Filter by daemon ID")
|
|
23584
|
+
},
|
|
23585
|
+
({ agentKey, daemonId }) => safe5(() => {
|
|
23586
|
+
let path = "/agent-models";
|
|
23587
|
+
const params = new URLSearchParams();
|
|
23588
|
+
if (agentKey) params.set("agentKey", agentKey);
|
|
23589
|
+
if (daemonId) params.set("daemonId", daemonId);
|
|
23590
|
+
const qs = params.toString();
|
|
23591
|
+
if (qs) path += "?" + qs;
|
|
23592
|
+
return request(ctx, "GET", workspacePath(ctx, path));
|
|
23593
|
+
})
|
|
23594
|
+
);
|
|
23595
|
+
}
|
|
23596
|
+
|
|
23597
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.28.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/client.js
|
|
23598
|
+
var ExperimentalClientTasks = class {
|
|
23599
|
+
constructor(_client) {
|
|
23600
|
+
this._client = _client;
|
|
23601
|
+
}
|
|
23602
|
+
/**
|
|
23603
|
+
* Calls a tool and returns an AsyncGenerator that yields response messages.
|
|
23604
|
+
* The generator is guaranteed to end with either a 'result' or 'error' message.
|
|
23605
|
+
*
|
|
23606
|
+
* This method provides streaming access to tool execution, allowing you to
|
|
23607
|
+
* observe intermediate task status updates for long-running tool calls.
|
|
23608
|
+
* Automatically validates structured output if the tool has an outputSchema.
|
|
23609
|
+
*
|
|
23610
|
+
* @example
|
|
23611
|
+
* ```typescript
|
|
23612
|
+
* const stream = client.experimental.tasks.callToolStream({ name: 'myTool', arguments: {} });
|
|
23613
|
+
* for await (const message of stream) {
|
|
23614
|
+
* switch (message.type) {
|
|
23615
|
+
* case 'taskCreated':
|
|
23616
|
+
* console.log('Tool execution started:', message.task.taskId);
|
|
23617
|
+
* break;
|
|
23618
|
+
* case 'taskStatus':
|
|
23619
|
+
* console.log('Tool status:', message.task.status);
|
|
23620
|
+
* break;
|
|
23621
|
+
* case 'result':
|
|
23622
|
+
* console.log('Tool result:', message.result);
|
|
23623
|
+
* break;
|
|
23624
|
+
* case 'error':
|
|
23625
|
+
* console.error('Tool error:', message.error);
|
|
23626
|
+
* break;
|
|
23627
|
+
* }
|
|
23628
|
+
* }
|
|
23629
|
+
* ```
|
|
23630
|
+
*
|
|
23631
|
+
* @param params - Tool call parameters (name and arguments)
|
|
23632
|
+
* @param resultSchema - Zod schema for validating the result (defaults to CallToolResultSchema)
|
|
23633
|
+
* @param options - Optional request options (timeout, signal, task creation params, etc.)
|
|
23634
|
+
* @returns AsyncGenerator that yields ResponseMessage objects
|
|
23635
|
+
*
|
|
23636
|
+
* @experimental
|
|
23637
|
+
*/
|
|
23638
|
+
async *callToolStream(params, resultSchema = CallToolResultSchema, options) {
|
|
23639
|
+
const clientInternal = this._client;
|
|
23640
|
+
const optionsWithTask = {
|
|
23641
|
+
...options,
|
|
23642
|
+
// We check if the tool is known to be a task during auto-configuration, but assume
|
|
23643
|
+
// the caller knows what they're doing if they pass this explicitly
|
|
23644
|
+
task: options?.task ?? (clientInternal.isToolTask(params.name) ? {} : void 0)
|
|
23645
|
+
};
|
|
23646
|
+
const stream = clientInternal.requestStream({ method: "tools/call", params }, resultSchema, optionsWithTask);
|
|
23647
|
+
const validator = clientInternal.getToolOutputValidator(params.name);
|
|
23648
|
+
for await (const message of stream) {
|
|
23649
|
+
if (message.type === "result" && validator) {
|
|
23650
|
+
const result = message.result;
|
|
23651
|
+
if (!result.structuredContent && !result.isError) {
|
|
23652
|
+
yield {
|
|
23653
|
+
type: "error",
|
|
23654
|
+
error: new McpError(ErrorCode.InvalidRequest, `Tool ${params.name} has an output schema but did not return structured content`)
|
|
23655
|
+
};
|
|
23656
|
+
return;
|
|
23657
|
+
}
|
|
23658
|
+
if (result.structuredContent) {
|
|
23659
|
+
try {
|
|
23660
|
+
const validationResult = validator(result.structuredContent);
|
|
23661
|
+
if (!validationResult.valid) {
|
|
23662
|
+
yield {
|
|
23663
|
+
type: "error",
|
|
23664
|
+
error: new McpError(ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${validationResult.errorMessage}`)
|
|
23665
|
+
};
|
|
23666
|
+
return;
|
|
23667
|
+
}
|
|
23668
|
+
} catch (error2) {
|
|
23669
|
+
if (error2 instanceof McpError) {
|
|
23670
|
+
yield { type: "error", error: error2 };
|
|
23671
|
+
return;
|
|
23672
|
+
}
|
|
23673
|
+
yield {
|
|
23674
|
+
type: "error",
|
|
23675
|
+
error: new McpError(ErrorCode.InvalidParams, `Failed to validate structured content: ${error2 instanceof Error ? error2.message : String(error2)}`)
|
|
23676
|
+
};
|
|
23677
|
+
return;
|
|
23678
|
+
}
|
|
23679
|
+
}
|
|
23680
|
+
}
|
|
23681
|
+
yield message;
|
|
23682
|
+
}
|
|
23683
|
+
}
|
|
23684
|
+
/**
|
|
23685
|
+
* Gets the current status of a task.
|
|
23686
|
+
*
|
|
23687
|
+
* @param taskId - The task identifier
|
|
23688
|
+
* @param options - Optional request options
|
|
23689
|
+
* @returns The task status
|
|
23690
|
+
*
|
|
23691
|
+
* @experimental
|
|
23692
|
+
*/
|
|
23693
|
+
async getTask(taskId, options) {
|
|
23694
|
+
return this._client.getTask({ taskId }, options);
|
|
23695
|
+
}
|
|
23696
|
+
/**
|
|
23697
|
+
* Retrieves the result of a completed task.
|
|
23698
|
+
*
|
|
23699
|
+
* @param taskId - The task identifier
|
|
23700
|
+
* @param resultSchema - Zod schema for validating the result
|
|
23701
|
+
* @param options - Optional request options
|
|
23702
|
+
* @returns The task result
|
|
23703
|
+
*
|
|
23704
|
+
* @experimental
|
|
23705
|
+
*/
|
|
23706
|
+
async getTaskResult(taskId, resultSchema, options) {
|
|
23707
|
+
return this._client.getTaskResult({ taskId }, resultSchema, options);
|
|
23708
|
+
}
|
|
23709
|
+
/**
|
|
23710
|
+
* Lists tasks with optional pagination.
|
|
23711
|
+
*
|
|
23712
|
+
* @param cursor - Optional pagination cursor
|
|
23713
|
+
* @param options - Optional request options
|
|
23714
|
+
* @returns List of tasks with optional next cursor
|
|
23715
|
+
*
|
|
23716
|
+
* @experimental
|
|
23717
|
+
*/
|
|
23718
|
+
async listTasks(cursor, options) {
|
|
23719
|
+
return this._client.listTasks(cursor ? { cursor } : void 0, options);
|
|
23720
|
+
}
|
|
23721
|
+
/**
|
|
23722
|
+
* Cancels a running task.
|
|
23723
|
+
*
|
|
23724
|
+
* @param taskId - The task identifier
|
|
23725
|
+
* @param options - Optional request options
|
|
23726
|
+
*
|
|
23727
|
+
* @experimental
|
|
23728
|
+
*/
|
|
23729
|
+
async cancelTask(taskId, options) {
|
|
23730
|
+
return this._client.cancelTask({ taskId }, options);
|
|
23731
|
+
}
|
|
23732
|
+
/**
|
|
23733
|
+
* Sends a request and returns an AsyncGenerator that yields response messages.
|
|
23734
|
+
* The generator is guaranteed to end with either a 'result' or 'error' message.
|
|
23735
|
+
*
|
|
23736
|
+
* This method provides streaming access to request processing, allowing you to
|
|
23737
|
+
* observe intermediate task status updates for task-augmented requests.
|
|
23738
|
+
*
|
|
23739
|
+
* @param request - The request to send
|
|
23740
|
+
* @param resultSchema - Zod schema for validating the result
|
|
23741
|
+
* @param options - Optional request options (timeout, signal, task creation params, etc.)
|
|
23742
|
+
* @returns AsyncGenerator that yields ResponseMessage objects
|
|
23743
|
+
*
|
|
23744
|
+
* @experimental
|
|
23745
|
+
*/
|
|
23746
|
+
requestStream(request2, resultSchema, options) {
|
|
23747
|
+
return this._client.requestStream(request2, resultSchema, options);
|
|
23748
|
+
}
|
|
23749
|
+
};
|
|
23750
|
+
|
|
23751
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.28.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js
|
|
23752
|
+
function applyElicitationDefaults(schema, data) {
|
|
23753
|
+
if (!schema || data === null || typeof data !== "object")
|
|
23754
|
+
return;
|
|
23755
|
+
if (schema.type === "object" && schema.properties && typeof schema.properties === "object") {
|
|
23756
|
+
const obj = data;
|
|
23757
|
+
const props = schema.properties;
|
|
23758
|
+
for (const key of Object.keys(props)) {
|
|
23759
|
+
const propSchema = props[key];
|
|
23760
|
+
if (obj[key] === void 0 && Object.prototype.hasOwnProperty.call(propSchema, "default")) {
|
|
23761
|
+
obj[key] = propSchema.default;
|
|
23762
|
+
}
|
|
23763
|
+
if (obj[key] !== void 0) {
|
|
23764
|
+
applyElicitationDefaults(propSchema, obj[key]);
|
|
23765
|
+
}
|
|
23766
|
+
}
|
|
23767
|
+
}
|
|
23768
|
+
if (Array.isArray(schema.anyOf)) {
|
|
23769
|
+
for (const sub of schema.anyOf) {
|
|
23770
|
+
if (typeof sub !== "boolean") {
|
|
23771
|
+
applyElicitationDefaults(sub, data);
|
|
23772
|
+
}
|
|
23773
|
+
}
|
|
23774
|
+
}
|
|
23775
|
+
if (Array.isArray(schema.oneOf)) {
|
|
23776
|
+
for (const sub of schema.oneOf) {
|
|
23777
|
+
if (typeof sub !== "boolean") {
|
|
23778
|
+
applyElicitationDefaults(sub, data);
|
|
23779
|
+
}
|
|
23780
|
+
}
|
|
23781
|
+
}
|
|
23782
|
+
}
|
|
23783
|
+
function getSupportedElicitationModes(capabilities) {
|
|
23784
|
+
if (!capabilities) {
|
|
23785
|
+
return { supportsFormMode: false, supportsUrlMode: false };
|
|
23786
|
+
}
|
|
23787
|
+
const hasFormCapability = capabilities.form !== void 0;
|
|
23788
|
+
const hasUrlCapability = capabilities.url !== void 0;
|
|
23789
|
+
const supportsFormMode = hasFormCapability || !hasFormCapability && !hasUrlCapability;
|
|
23790
|
+
const supportsUrlMode = hasUrlCapability;
|
|
23791
|
+
return { supportsFormMode, supportsUrlMode };
|
|
23792
|
+
}
|
|
23793
|
+
var Client = class extends Protocol {
|
|
23794
|
+
/**
|
|
23795
|
+
* Initializes this client with the given name and version information.
|
|
23796
|
+
*/
|
|
23797
|
+
constructor(_clientInfo, options) {
|
|
23798
|
+
super(options);
|
|
23799
|
+
this._clientInfo = _clientInfo;
|
|
23800
|
+
this._cachedToolOutputValidators = /* @__PURE__ */ new Map();
|
|
23801
|
+
this._cachedKnownTaskTools = /* @__PURE__ */ new Set();
|
|
23802
|
+
this._cachedRequiredTaskTools = /* @__PURE__ */ new Set();
|
|
23803
|
+
this._listChangedDebounceTimers = /* @__PURE__ */ new Map();
|
|
23804
|
+
this._capabilities = options?.capabilities ?? {};
|
|
23805
|
+
this._jsonSchemaValidator = options?.jsonSchemaValidator ?? new AjvJsonSchemaValidator();
|
|
23806
|
+
if (options?.listChanged) {
|
|
23807
|
+
this._pendingListChangedConfig = options.listChanged;
|
|
23808
|
+
}
|
|
23809
|
+
}
|
|
23810
|
+
/**
|
|
23811
|
+
* Set up handlers for list changed notifications based on config and server capabilities.
|
|
23812
|
+
* This should only be called after initialization when server capabilities are known.
|
|
23813
|
+
* Handlers are silently skipped if the server doesn't advertise the corresponding listChanged capability.
|
|
23814
|
+
* @internal
|
|
23815
|
+
*/
|
|
23816
|
+
_setupListChangedHandlers(config2) {
|
|
23817
|
+
if (config2.tools && this._serverCapabilities?.tools?.listChanged) {
|
|
23818
|
+
this._setupListChangedHandler("tools", ToolListChangedNotificationSchema, config2.tools, async () => {
|
|
23819
|
+
const result = await this.listTools();
|
|
23820
|
+
return result.tools;
|
|
23821
|
+
});
|
|
23822
|
+
}
|
|
23823
|
+
if (config2.prompts && this._serverCapabilities?.prompts?.listChanged) {
|
|
23824
|
+
this._setupListChangedHandler("prompts", PromptListChangedNotificationSchema, config2.prompts, async () => {
|
|
23825
|
+
const result = await this.listPrompts();
|
|
23826
|
+
return result.prompts;
|
|
23827
|
+
});
|
|
23828
|
+
}
|
|
23829
|
+
if (config2.resources && this._serverCapabilities?.resources?.listChanged) {
|
|
23830
|
+
this._setupListChangedHandler("resources", ResourceListChangedNotificationSchema, config2.resources, async () => {
|
|
23831
|
+
const result = await this.listResources();
|
|
23832
|
+
return result.resources;
|
|
23833
|
+
});
|
|
23834
|
+
}
|
|
23835
|
+
}
|
|
23836
|
+
/**
|
|
23837
|
+
* Access experimental features.
|
|
23838
|
+
*
|
|
23839
|
+
* WARNING: These APIs are experimental and may change without notice.
|
|
23840
|
+
*
|
|
23841
|
+
* @experimental
|
|
23842
|
+
*/
|
|
23843
|
+
get experimental() {
|
|
23844
|
+
if (!this._experimental) {
|
|
23845
|
+
this._experimental = {
|
|
23846
|
+
tasks: new ExperimentalClientTasks(this)
|
|
23847
|
+
};
|
|
23848
|
+
}
|
|
23849
|
+
return this._experimental;
|
|
23850
|
+
}
|
|
23851
|
+
/**
|
|
23852
|
+
* Registers new capabilities. This can only be called before connecting to a transport.
|
|
23853
|
+
*
|
|
23854
|
+
* The new capabilities will be merged with any existing capabilities previously given (e.g., at initialization).
|
|
23855
|
+
*/
|
|
23856
|
+
registerCapabilities(capabilities) {
|
|
23857
|
+
if (this.transport) {
|
|
23858
|
+
throw new Error("Cannot register capabilities after connecting to transport");
|
|
23859
|
+
}
|
|
23860
|
+
this._capabilities = mergeCapabilities(this._capabilities, capabilities);
|
|
23861
|
+
}
|
|
23862
|
+
/**
|
|
23863
|
+
* Override request handler registration to enforce client-side validation for elicitation.
|
|
23864
|
+
*/
|
|
23865
|
+
setRequestHandler(requestSchema, handler) {
|
|
23866
|
+
const shape = getObjectShape(requestSchema);
|
|
23867
|
+
const methodSchema = shape?.method;
|
|
23868
|
+
if (!methodSchema) {
|
|
23869
|
+
throw new Error("Schema is missing a method literal");
|
|
23870
|
+
}
|
|
23871
|
+
let methodValue;
|
|
23872
|
+
if (isZ4Schema(methodSchema)) {
|
|
23873
|
+
const v4Schema = methodSchema;
|
|
23874
|
+
const v4Def = v4Schema._zod?.def;
|
|
23875
|
+
methodValue = v4Def?.value ?? v4Schema.value;
|
|
23876
|
+
} else {
|
|
23877
|
+
const v3Schema = methodSchema;
|
|
23878
|
+
const legacyDef = v3Schema._def;
|
|
23879
|
+
methodValue = legacyDef?.value ?? v3Schema.value;
|
|
23880
|
+
}
|
|
23881
|
+
if (typeof methodValue !== "string") {
|
|
23882
|
+
throw new Error("Schema method literal must be a string");
|
|
23883
|
+
}
|
|
23884
|
+
const method = methodValue;
|
|
23885
|
+
if (method === "elicitation/create") {
|
|
23886
|
+
const wrappedHandler = async (request2, extra) => {
|
|
23887
|
+
const validatedRequest = safeParse2(ElicitRequestSchema, request2);
|
|
23888
|
+
if (!validatedRequest.success) {
|
|
23889
|
+
const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
|
|
23890
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation request: ${errorMessage}`);
|
|
23891
|
+
}
|
|
23892
|
+
const { params } = validatedRequest.data;
|
|
23893
|
+
params.mode = params.mode ?? "form";
|
|
23894
|
+
const { supportsFormMode, supportsUrlMode } = getSupportedElicitationModes(this._capabilities.elicitation);
|
|
23895
|
+
if (params.mode === "form" && !supportsFormMode) {
|
|
23896
|
+
throw new McpError(ErrorCode.InvalidParams, "Client does not support form-mode elicitation requests");
|
|
23897
|
+
}
|
|
23898
|
+
if (params.mode === "url" && !supportsUrlMode) {
|
|
23899
|
+
throw new McpError(ErrorCode.InvalidParams, "Client does not support URL-mode elicitation requests");
|
|
23900
|
+
}
|
|
23901
|
+
const result = await Promise.resolve(handler(request2, extra));
|
|
23902
|
+
if (params.task) {
|
|
23903
|
+
const taskValidationResult = safeParse2(CreateTaskResultSchema, result);
|
|
23904
|
+
if (!taskValidationResult.success) {
|
|
23905
|
+
const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
|
|
23906
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
|
|
23907
|
+
}
|
|
23908
|
+
return taskValidationResult.data;
|
|
23909
|
+
}
|
|
23910
|
+
const validationResult = safeParse2(ElicitResultSchema, result);
|
|
23911
|
+
if (!validationResult.success) {
|
|
23912
|
+
const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
|
|
23913
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation result: ${errorMessage}`);
|
|
23914
|
+
}
|
|
23915
|
+
const validatedResult = validationResult.data;
|
|
23916
|
+
const requestedSchema = params.mode === "form" ? params.requestedSchema : void 0;
|
|
23917
|
+
if (params.mode === "form" && validatedResult.action === "accept" && validatedResult.content && requestedSchema) {
|
|
23918
|
+
if (this._capabilities.elicitation?.form?.applyDefaults) {
|
|
23919
|
+
try {
|
|
23920
|
+
applyElicitationDefaults(requestedSchema, validatedResult.content);
|
|
23921
|
+
} catch {
|
|
23922
|
+
}
|
|
23923
|
+
}
|
|
23924
|
+
}
|
|
23925
|
+
return validatedResult;
|
|
23926
|
+
};
|
|
23927
|
+
return super.setRequestHandler(requestSchema, wrappedHandler);
|
|
23928
|
+
}
|
|
23929
|
+
if (method === "sampling/createMessage") {
|
|
23930
|
+
const wrappedHandler = async (request2, extra) => {
|
|
23931
|
+
const validatedRequest = safeParse2(CreateMessageRequestSchema, request2);
|
|
23932
|
+
if (!validatedRequest.success) {
|
|
23933
|
+
const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
|
|
23934
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid sampling request: ${errorMessage}`);
|
|
23935
|
+
}
|
|
23936
|
+
const { params } = validatedRequest.data;
|
|
23937
|
+
const result = await Promise.resolve(handler(request2, extra));
|
|
23938
|
+
if (params.task) {
|
|
23939
|
+
const taskValidationResult = safeParse2(CreateTaskResultSchema, result);
|
|
23940
|
+
if (!taskValidationResult.success) {
|
|
23941
|
+
const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
|
|
23942
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
|
|
23943
|
+
}
|
|
23944
|
+
return taskValidationResult.data;
|
|
23945
|
+
}
|
|
23946
|
+
const hasTools = params.tools || params.toolChoice;
|
|
23947
|
+
const resultSchema = hasTools ? CreateMessageResultWithToolsSchema : CreateMessageResultSchema;
|
|
23948
|
+
const validationResult = safeParse2(resultSchema, result);
|
|
23949
|
+
if (!validationResult.success) {
|
|
23950
|
+
const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
|
|
23951
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid sampling result: ${errorMessage}`);
|
|
23952
|
+
}
|
|
23953
|
+
return validationResult.data;
|
|
23954
|
+
};
|
|
23955
|
+
return super.setRequestHandler(requestSchema, wrappedHandler);
|
|
23956
|
+
}
|
|
23957
|
+
return super.setRequestHandler(requestSchema, handler);
|
|
23958
|
+
}
|
|
23959
|
+
assertCapability(capability, method) {
|
|
23960
|
+
if (!this._serverCapabilities?.[capability]) {
|
|
23961
|
+
throw new Error(`Server does not support ${capability} (required for ${method})`);
|
|
23962
|
+
}
|
|
23963
|
+
}
|
|
23964
|
+
async connect(transport, options) {
|
|
23965
|
+
await super.connect(transport);
|
|
23966
|
+
if (transport.sessionId !== void 0) {
|
|
23967
|
+
return;
|
|
23968
|
+
}
|
|
23969
|
+
try {
|
|
23970
|
+
const result = await this.request({
|
|
23971
|
+
method: "initialize",
|
|
23972
|
+
params: {
|
|
23973
|
+
protocolVersion: LATEST_PROTOCOL_VERSION,
|
|
23974
|
+
capabilities: this._capabilities,
|
|
23975
|
+
clientInfo: this._clientInfo
|
|
23976
|
+
}
|
|
23977
|
+
}, InitializeResultSchema, options);
|
|
23978
|
+
if (result === void 0) {
|
|
23979
|
+
throw new Error(`Server sent invalid initialize result: ${result}`);
|
|
23980
|
+
}
|
|
23981
|
+
if (!SUPPORTED_PROTOCOL_VERSIONS.includes(result.protocolVersion)) {
|
|
23982
|
+
throw new Error(`Server's protocol version is not supported: ${result.protocolVersion}`);
|
|
23983
|
+
}
|
|
23984
|
+
this._serverCapabilities = result.capabilities;
|
|
23985
|
+
this._serverVersion = result.serverInfo;
|
|
23986
|
+
if (transport.setProtocolVersion) {
|
|
23987
|
+
transport.setProtocolVersion(result.protocolVersion);
|
|
23988
|
+
}
|
|
23989
|
+
this._instructions = result.instructions;
|
|
23990
|
+
await this.notification({
|
|
23991
|
+
method: "notifications/initialized"
|
|
23992
|
+
});
|
|
23993
|
+
if (this._pendingListChangedConfig) {
|
|
23994
|
+
this._setupListChangedHandlers(this._pendingListChangedConfig);
|
|
23995
|
+
this._pendingListChangedConfig = void 0;
|
|
23996
|
+
}
|
|
23997
|
+
} catch (error2) {
|
|
23998
|
+
void this.close();
|
|
23999
|
+
throw error2;
|
|
24000
|
+
}
|
|
24001
|
+
}
|
|
24002
|
+
/**
|
|
24003
|
+
* After initialization has completed, this will be populated with the server's reported capabilities.
|
|
24004
|
+
*/
|
|
24005
|
+
getServerCapabilities() {
|
|
24006
|
+
return this._serverCapabilities;
|
|
24007
|
+
}
|
|
24008
|
+
/**
|
|
24009
|
+
* After initialization has completed, this will be populated with information about the server's name and version.
|
|
24010
|
+
*/
|
|
24011
|
+
getServerVersion() {
|
|
24012
|
+
return this._serverVersion;
|
|
24013
|
+
}
|
|
24014
|
+
/**
|
|
24015
|
+
* After initialization has completed, this may be populated with information about the server's instructions.
|
|
24016
|
+
*/
|
|
24017
|
+
getInstructions() {
|
|
24018
|
+
return this._instructions;
|
|
24019
|
+
}
|
|
24020
|
+
assertCapabilityForMethod(method) {
|
|
24021
|
+
switch (method) {
|
|
24022
|
+
case "logging/setLevel":
|
|
24023
|
+
if (!this._serverCapabilities?.logging) {
|
|
24024
|
+
throw new Error(`Server does not support logging (required for ${method})`);
|
|
24025
|
+
}
|
|
24026
|
+
break;
|
|
24027
|
+
case "prompts/get":
|
|
24028
|
+
case "prompts/list":
|
|
24029
|
+
if (!this._serverCapabilities?.prompts) {
|
|
24030
|
+
throw new Error(`Server does not support prompts (required for ${method})`);
|
|
24031
|
+
}
|
|
24032
|
+
break;
|
|
24033
|
+
case "resources/list":
|
|
24034
|
+
case "resources/templates/list":
|
|
24035
|
+
case "resources/read":
|
|
24036
|
+
case "resources/subscribe":
|
|
24037
|
+
case "resources/unsubscribe":
|
|
24038
|
+
if (!this._serverCapabilities?.resources) {
|
|
24039
|
+
throw new Error(`Server does not support resources (required for ${method})`);
|
|
24040
|
+
}
|
|
24041
|
+
if (method === "resources/subscribe" && !this._serverCapabilities.resources.subscribe) {
|
|
24042
|
+
throw new Error(`Server does not support resource subscriptions (required for ${method})`);
|
|
24043
|
+
}
|
|
24044
|
+
break;
|
|
24045
|
+
case "tools/call":
|
|
24046
|
+
case "tools/list":
|
|
24047
|
+
if (!this._serverCapabilities?.tools) {
|
|
24048
|
+
throw new Error(`Server does not support tools (required for ${method})`);
|
|
24049
|
+
}
|
|
24050
|
+
break;
|
|
24051
|
+
case "completion/complete":
|
|
24052
|
+
if (!this._serverCapabilities?.completions) {
|
|
24053
|
+
throw new Error(`Server does not support completions (required for ${method})`);
|
|
24054
|
+
}
|
|
24055
|
+
break;
|
|
24056
|
+
case "initialize":
|
|
24057
|
+
break;
|
|
24058
|
+
case "ping":
|
|
24059
|
+
break;
|
|
24060
|
+
}
|
|
24061
|
+
}
|
|
24062
|
+
assertNotificationCapability(method) {
|
|
24063
|
+
switch (method) {
|
|
24064
|
+
case "notifications/roots/list_changed":
|
|
24065
|
+
if (!this._capabilities.roots?.listChanged) {
|
|
24066
|
+
throw new Error(`Client does not support roots list changed notifications (required for ${method})`);
|
|
24067
|
+
}
|
|
24068
|
+
break;
|
|
24069
|
+
case "notifications/initialized":
|
|
24070
|
+
break;
|
|
24071
|
+
case "notifications/cancelled":
|
|
24072
|
+
break;
|
|
24073
|
+
case "notifications/progress":
|
|
24074
|
+
break;
|
|
24075
|
+
}
|
|
24076
|
+
}
|
|
24077
|
+
assertRequestHandlerCapability(method) {
|
|
24078
|
+
if (!this._capabilities) {
|
|
24079
|
+
return;
|
|
24080
|
+
}
|
|
24081
|
+
switch (method) {
|
|
24082
|
+
case "sampling/createMessage":
|
|
24083
|
+
if (!this._capabilities.sampling) {
|
|
24084
|
+
throw new Error(`Client does not support sampling capability (required for ${method})`);
|
|
24085
|
+
}
|
|
24086
|
+
break;
|
|
24087
|
+
case "elicitation/create":
|
|
24088
|
+
if (!this._capabilities.elicitation) {
|
|
24089
|
+
throw new Error(`Client does not support elicitation capability (required for ${method})`);
|
|
24090
|
+
}
|
|
24091
|
+
break;
|
|
24092
|
+
case "roots/list":
|
|
24093
|
+
if (!this._capabilities.roots) {
|
|
24094
|
+
throw new Error(`Client does not support roots capability (required for ${method})`);
|
|
24095
|
+
}
|
|
24096
|
+
break;
|
|
24097
|
+
case "tasks/get":
|
|
24098
|
+
case "tasks/list":
|
|
24099
|
+
case "tasks/result":
|
|
24100
|
+
case "tasks/cancel":
|
|
24101
|
+
if (!this._capabilities.tasks) {
|
|
24102
|
+
throw new Error(`Client does not support tasks capability (required for ${method})`);
|
|
24103
|
+
}
|
|
24104
|
+
break;
|
|
24105
|
+
case "ping":
|
|
24106
|
+
break;
|
|
24107
|
+
}
|
|
24108
|
+
}
|
|
24109
|
+
assertTaskCapability(method) {
|
|
24110
|
+
assertToolsCallTaskCapability(this._serverCapabilities?.tasks?.requests, method, "Server");
|
|
24111
|
+
}
|
|
24112
|
+
assertTaskHandlerCapability(method) {
|
|
24113
|
+
if (!this._capabilities) {
|
|
24114
|
+
return;
|
|
24115
|
+
}
|
|
24116
|
+
assertClientRequestTaskCapability(this._capabilities.tasks?.requests, method, "Client");
|
|
24117
|
+
}
|
|
24118
|
+
async ping(options) {
|
|
24119
|
+
return this.request({ method: "ping" }, EmptyResultSchema, options);
|
|
24120
|
+
}
|
|
24121
|
+
async complete(params, options) {
|
|
24122
|
+
return this.request({ method: "completion/complete", params }, CompleteResultSchema, options);
|
|
24123
|
+
}
|
|
24124
|
+
async setLoggingLevel(level, options) {
|
|
24125
|
+
return this.request({ method: "logging/setLevel", params: { level } }, EmptyResultSchema, options);
|
|
24126
|
+
}
|
|
24127
|
+
async getPrompt(params, options) {
|
|
24128
|
+
return this.request({ method: "prompts/get", params }, GetPromptResultSchema, options);
|
|
24129
|
+
}
|
|
24130
|
+
async listPrompts(params, options) {
|
|
24131
|
+
return this.request({ method: "prompts/list", params }, ListPromptsResultSchema, options);
|
|
24132
|
+
}
|
|
24133
|
+
async listResources(params, options) {
|
|
24134
|
+
return this.request({ method: "resources/list", params }, ListResourcesResultSchema, options);
|
|
24135
|
+
}
|
|
24136
|
+
async listResourceTemplates(params, options) {
|
|
24137
|
+
return this.request({ method: "resources/templates/list", params }, ListResourceTemplatesResultSchema, options);
|
|
24138
|
+
}
|
|
24139
|
+
async readResource(params, options) {
|
|
24140
|
+
return this.request({ method: "resources/read", params }, ReadResourceResultSchema, options);
|
|
24141
|
+
}
|
|
24142
|
+
async subscribeResource(params, options) {
|
|
24143
|
+
return this.request({ method: "resources/subscribe", params }, EmptyResultSchema, options);
|
|
24144
|
+
}
|
|
24145
|
+
async unsubscribeResource(params, options) {
|
|
24146
|
+
return this.request({ method: "resources/unsubscribe", params }, EmptyResultSchema, options);
|
|
24147
|
+
}
|
|
24148
|
+
/**
|
|
24149
|
+
* Calls a tool and waits for the result. Automatically validates structured output if the tool has an outputSchema.
|
|
24150
|
+
*
|
|
24151
|
+
* For task-based execution with streaming behavior, use client.experimental.tasks.callToolStream() instead.
|
|
24152
|
+
*/
|
|
24153
|
+
async callTool(params, resultSchema = CallToolResultSchema, options) {
|
|
24154
|
+
if (this.isToolTaskRequired(params.name)) {
|
|
24155
|
+
throw new McpError(ErrorCode.InvalidRequest, `Tool "${params.name}" requires task-based execution. Use client.experimental.tasks.callToolStream() instead.`);
|
|
24156
|
+
}
|
|
24157
|
+
const result = await this.request({ method: "tools/call", params }, resultSchema, options);
|
|
24158
|
+
const validator = this.getToolOutputValidator(params.name);
|
|
24159
|
+
if (validator) {
|
|
24160
|
+
if (!result.structuredContent && !result.isError) {
|
|
24161
|
+
throw new McpError(ErrorCode.InvalidRequest, `Tool ${params.name} has an output schema but did not return structured content`);
|
|
24162
|
+
}
|
|
24163
|
+
if (result.structuredContent) {
|
|
24164
|
+
try {
|
|
24165
|
+
const validationResult = validator(result.structuredContent);
|
|
24166
|
+
if (!validationResult.valid) {
|
|
24167
|
+
throw new McpError(ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${validationResult.errorMessage}`);
|
|
24168
|
+
}
|
|
24169
|
+
} catch (error2) {
|
|
24170
|
+
if (error2 instanceof McpError) {
|
|
24171
|
+
throw error2;
|
|
24172
|
+
}
|
|
24173
|
+
throw new McpError(ErrorCode.InvalidParams, `Failed to validate structured content: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
24174
|
+
}
|
|
24175
|
+
}
|
|
24176
|
+
}
|
|
24177
|
+
return result;
|
|
24178
|
+
}
|
|
24179
|
+
isToolTask(toolName) {
|
|
24180
|
+
if (!this._serverCapabilities?.tasks?.requests?.tools?.call) {
|
|
24181
|
+
return false;
|
|
24182
|
+
}
|
|
24183
|
+
return this._cachedKnownTaskTools.has(toolName);
|
|
24184
|
+
}
|
|
24185
|
+
/**
|
|
24186
|
+
* Check if a tool requires task-based execution.
|
|
24187
|
+
* Unlike isToolTask which includes 'optional' tools, this only checks for 'required'.
|
|
24188
|
+
*/
|
|
24189
|
+
isToolTaskRequired(toolName) {
|
|
24190
|
+
return this._cachedRequiredTaskTools.has(toolName);
|
|
24191
|
+
}
|
|
24192
|
+
/**
|
|
24193
|
+
* Cache validators for tool output schemas.
|
|
24194
|
+
* Called after listTools() to pre-compile validators for better performance.
|
|
24195
|
+
*/
|
|
24196
|
+
cacheToolMetadata(tools) {
|
|
24197
|
+
this._cachedToolOutputValidators.clear();
|
|
24198
|
+
this._cachedKnownTaskTools.clear();
|
|
24199
|
+
this._cachedRequiredTaskTools.clear();
|
|
24200
|
+
for (const tool of tools) {
|
|
24201
|
+
if (tool.outputSchema) {
|
|
24202
|
+
const toolValidator = this._jsonSchemaValidator.getValidator(tool.outputSchema);
|
|
24203
|
+
this._cachedToolOutputValidators.set(tool.name, toolValidator);
|
|
24204
|
+
}
|
|
24205
|
+
const taskSupport = tool.execution?.taskSupport;
|
|
24206
|
+
if (taskSupport === "required" || taskSupport === "optional") {
|
|
24207
|
+
this._cachedKnownTaskTools.add(tool.name);
|
|
24208
|
+
}
|
|
24209
|
+
if (taskSupport === "required") {
|
|
24210
|
+
this._cachedRequiredTaskTools.add(tool.name);
|
|
24211
|
+
}
|
|
24212
|
+
}
|
|
24213
|
+
}
|
|
24214
|
+
/**
|
|
24215
|
+
* Get cached validator for a tool
|
|
24216
|
+
*/
|
|
24217
|
+
getToolOutputValidator(toolName) {
|
|
24218
|
+
return this._cachedToolOutputValidators.get(toolName);
|
|
24219
|
+
}
|
|
24220
|
+
async listTools(params, options) {
|
|
24221
|
+
const result = await this.request({ method: "tools/list", params }, ListToolsResultSchema, options);
|
|
24222
|
+
this.cacheToolMetadata(result.tools);
|
|
24223
|
+
return result;
|
|
24224
|
+
}
|
|
24225
|
+
/**
|
|
24226
|
+
* Set up a single list changed handler.
|
|
24227
|
+
* @internal
|
|
24228
|
+
*/
|
|
24229
|
+
_setupListChangedHandler(listType, notificationSchema, options, fetcher) {
|
|
24230
|
+
const parseResult = ListChangedOptionsBaseSchema.safeParse(options);
|
|
24231
|
+
if (!parseResult.success) {
|
|
24232
|
+
throw new Error(`Invalid ${listType} listChanged options: ${parseResult.error.message}`);
|
|
24233
|
+
}
|
|
24234
|
+
if (typeof options.onChanged !== "function") {
|
|
24235
|
+
throw new Error(`Invalid ${listType} listChanged options: onChanged must be a function`);
|
|
24236
|
+
}
|
|
24237
|
+
const { autoRefresh, debounceMs } = parseResult.data;
|
|
24238
|
+
const { onChanged } = options;
|
|
24239
|
+
const refresh = async () => {
|
|
24240
|
+
if (!autoRefresh) {
|
|
24241
|
+
onChanged(null, null);
|
|
24242
|
+
return;
|
|
24243
|
+
}
|
|
24244
|
+
try {
|
|
24245
|
+
const items = await fetcher();
|
|
24246
|
+
onChanged(null, items);
|
|
24247
|
+
} catch (e) {
|
|
24248
|
+
const error2 = e instanceof Error ? e : new Error(String(e));
|
|
24249
|
+
onChanged(error2, null);
|
|
24250
|
+
}
|
|
24251
|
+
};
|
|
24252
|
+
const handler = () => {
|
|
24253
|
+
if (debounceMs) {
|
|
24254
|
+
const existingTimer = this._listChangedDebounceTimers.get(listType);
|
|
24255
|
+
if (existingTimer) {
|
|
24256
|
+
clearTimeout(existingTimer);
|
|
24257
|
+
}
|
|
24258
|
+
const timer = setTimeout(refresh, debounceMs);
|
|
24259
|
+
this._listChangedDebounceTimers.set(listType, timer);
|
|
24260
|
+
} else {
|
|
24261
|
+
refresh();
|
|
24262
|
+
}
|
|
24263
|
+
};
|
|
24264
|
+
this.setNotificationHandler(notificationSchema, handler);
|
|
24265
|
+
}
|
|
24266
|
+
async sendRootsListChanged() {
|
|
24267
|
+
return this.notification({ method: "notifications/roots/list_changed" });
|
|
24268
|
+
}
|
|
24269
|
+
};
|
|
24270
|
+
|
|
24271
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.28.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/transport.js
|
|
24272
|
+
function normalizeHeaders(headers) {
|
|
24273
|
+
if (!headers)
|
|
24274
|
+
return {};
|
|
24275
|
+
if (headers instanceof Headers) {
|
|
24276
|
+
return Object.fromEntries(headers.entries());
|
|
24277
|
+
}
|
|
24278
|
+
if (Array.isArray(headers)) {
|
|
24279
|
+
return Object.fromEntries(headers);
|
|
24280
|
+
}
|
|
24281
|
+
return { ...headers };
|
|
24282
|
+
}
|
|
24283
|
+
function createFetchWithInit(baseFetch = fetch, baseInit) {
|
|
24284
|
+
if (!baseInit) {
|
|
24285
|
+
return baseFetch;
|
|
24286
|
+
}
|
|
24287
|
+
return async (url2, init) => {
|
|
24288
|
+
const mergedInit = {
|
|
24289
|
+
...baseInit,
|
|
24290
|
+
...init,
|
|
24291
|
+
// Headers need special handling - merge instead of replace
|
|
24292
|
+
headers: init?.headers ? { ...normalizeHeaders(baseInit.headers), ...normalizeHeaders(init.headers) } : baseInit.headers
|
|
24293
|
+
};
|
|
24294
|
+
return baseFetch(url2, mergedInit);
|
|
24295
|
+
};
|
|
24296
|
+
}
|
|
24297
|
+
|
|
24298
|
+
// ../../node_modules/.pnpm/pkce-challenge@5.0.1/node_modules/pkce-challenge/dist/index.node.js
|
|
24299
|
+
var crypto3;
|
|
24300
|
+
crypto3 = globalThis.crypto?.webcrypto ?? // Node.js [18-16] REPL
|
|
24301
|
+
globalThis.crypto ?? // Node.js >18
|
|
24302
|
+
import("node:crypto").then((m) => m.webcrypto);
|
|
24303
|
+
async function getRandomValues(size) {
|
|
24304
|
+
return (await crypto3).getRandomValues(new Uint8Array(size));
|
|
24305
|
+
}
|
|
24306
|
+
async function random(size) {
|
|
24307
|
+
const mask = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~";
|
|
24308
|
+
const evenDistCutoff = Math.pow(2, 8) - Math.pow(2, 8) % mask.length;
|
|
24309
|
+
let result = "";
|
|
24310
|
+
while (result.length < size) {
|
|
24311
|
+
const randomBytes = await getRandomValues(size - result.length);
|
|
24312
|
+
for (const randomByte of randomBytes) {
|
|
24313
|
+
if (randomByte < evenDistCutoff) {
|
|
24314
|
+
result += mask[randomByte % mask.length];
|
|
24315
|
+
}
|
|
24316
|
+
}
|
|
24317
|
+
}
|
|
24318
|
+
return result;
|
|
24319
|
+
}
|
|
24320
|
+
async function generateVerifier(length) {
|
|
24321
|
+
return await random(length);
|
|
24322
|
+
}
|
|
24323
|
+
async function generateChallenge(code_verifier) {
|
|
24324
|
+
const buffer = await (await crypto3).subtle.digest("SHA-256", new TextEncoder().encode(code_verifier));
|
|
24325
|
+
return btoa(String.fromCharCode(...new Uint8Array(buffer))).replace(/\//g, "_").replace(/\+/g, "-").replace(/=/g, "");
|
|
24326
|
+
}
|
|
24327
|
+
async function pkceChallenge(length) {
|
|
24328
|
+
if (!length)
|
|
24329
|
+
length = 43;
|
|
24330
|
+
if (length < 43 || length > 128) {
|
|
24331
|
+
throw `Expected a length between 43 and 128. Received ${length}.`;
|
|
24332
|
+
}
|
|
24333
|
+
const verifier = await generateVerifier(length);
|
|
24334
|
+
const challenge = await generateChallenge(verifier);
|
|
24335
|
+
return {
|
|
24336
|
+
code_verifier: verifier,
|
|
24337
|
+
code_challenge: challenge
|
|
24338
|
+
};
|
|
24339
|
+
}
|
|
24340
|
+
|
|
24341
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.28.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.js
|
|
24342
|
+
var SafeUrlSchema = url().superRefine((val, ctx) => {
|
|
24343
|
+
if (!URL.canParse(val)) {
|
|
24344
|
+
ctx.addIssue({
|
|
24345
|
+
code: ZodIssueCode2.custom,
|
|
24346
|
+
message: "URL must be parseable",
|
|
24347
|
+
fatal: true
|
|
24348
|
+
});
|
|
24349
|
+
return NEVER2;
|
|
24350
|
+
}
|
|
24351
|
+
}).refine((url2) => {
|
|
24352
|
+
const u = new URL(url2);
|
|
24353
|
+
return u.protocol !== "javascript:" && u.protocol !== "data:" && u.protocol !== "vbscript:";
|
|
24354
|
+
}, { message: "URL cannot use javascript:, data:, or vbscript: scheme" });
|
|
24355
|
+
var OAuthProtectedResourceMetadataSchema = looseObject({
|
|
24356
|
+
resource: string2().url(),
|
|
24357
|
+
authorization_servers: array(SafeUrlSchema).optional(),
|
|
24358
|
+
jwks_uri: string2().url().optional(),
|
|
24359
|
+
scopes_supported: array(string2()).optional(),
|
|
24360
|
+
bearer_methods_supported: array(string2()).optional(),
|
|
24361
|
+
resource_signing_alg_values_supported: array(string2()).optional(),
|
|
24362
|
+
resource_name: string2().optional(),
|
|
24363
|
+
resource_documentation: string2().optional(),
|
|
24364
|
+
resource_policy_uri: string2().url().optional(),
|
|
24365
|
+
resource_tos_uri: string2().url().optional(),
|
|
24366
|
+
tls_client_certificate_bound_access_tokens: boolean2().optional(),
|
|
24367
|
+
authorization_details_types_supported: array(string2()).optional(),
|
|
24368
|
+
dpop_signing_alg_values_supported: array(string2()).optional(),
|
|
24369
|
+
dpop_bound_access_tokens_required: boolean2().optional()
|
|
24370
|
+
});
|
|
24371
|
+
var OAuthMetadataSchema = looseObject({
|
|
24372
|
+
issuer: string2(),
|
|
24373
|
+
authorization_endpoint: SafeUrlSchema,
|
|
24374
|
+
token_endpoint: SafeUrlSchema,
|
|
24375
|
+
registration_endpoint: SafeUrlSchema.optional(),
|
|
24376
|
+
scopes_supported: array(string2()).optional(),
|
|
24377
|
+
response_types_supported: array(string2()),
|
|
24378
|
+
response_modes_supported: array(string2()).optional(),
|
|
24379
|
+
grant_types_supported: array(string2()).optional(),
|
|
24380
|
+
token_endpoint_auth_methods_supported: array(string2()).optional(),
|
|
24381
|
+
token_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
|
|
24382
|
+
service_documentation: SafeUrlSchema.optional(),
|
|
24383
|
+
revocation_endpoint: SafeUrlSchema.optional(),
|
|
24384
|
+
revocation_endpoint_auth_methods_supported: array(string2()).optional(),
|
|
24385
|
+
revocation_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
|
|
24386
|
+
introspection_endpoint: string2().optional(),
|
|
24387
|
+
introspection_endpoint_auth_methods_supported: array(string2()).optional(),
|
|
24388
|
+
introspection_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
|
|
24389
|
+
code_challenge_methods_supported: array(string2()).optional(),
|
|
24390
|
+
client_id_metadata_document_supported: boolean2().optional()
|
|
24391
|
+
});
|
|
24392
|
+
var OpenIdProviderMetadataSchema = looseObject({
|
|
24393
|
+
issuer: string2(),
|
|
24394
|
+
authorization_endpoint: SafeUrlSchema,
|
|
24395
|
+
token_endpoint: SafeUrlSchema,
|
|
24396
|
+
userinfo_endpoint: SafeUrlSchema.optional(),
|
|
24397
|
+
jwks_uri: SafeUrlSchema,
|
|
24398
|
+
registration_endpoint: SafeUrlSchema.optional(),
|
|
24399
|
+
scopes_supported: array(string2()).optional(),
|
|
24400
|
+
response_types_supported: array(string2()),
|
|
24401
|
+
response_modes_supported: array(string2()).optional(),
|
|
24402
|
+
grant_types_supported: array(string2()).optional(),
|
|
24403
|
+
acr_values_supported: array(string2()).optional(),
|
|
24404
|
+
subject_types_supported: array(string2()),
|
|
24405
|
+
id_token_signing_alg_values_supported: array(string2()),
|
|
24406
|
+
id_token_encryption_alg_values_supported: array(string2()).optional(),
|
|
24407
|
+
id_token_encryption_enc_values_supported: array(string2()).optional(),
|
|
24408
|
+
userinfo_signing_alg_values_supported: array(string2()).optional(),
|
|
24409
|
+
userinfo_encryption_alg_values_supported: array(string2()).optional(),
|
|
24410
|
+
userinfo_encryption_enc_values_supported: array(string2()).optional(),
|
|
24411
|
+
request_object_signing_alg_values_supported: array(string2()).optional(),
|
|
24412
|
+
request_object_encryption_alg_values_supported: array(string2()).optional(),
|
|
24413
|
+
request_object_encryption_enc_values_supported: array(string2()).optional(),
|
|
24414
|
+
token_endpoint_auth_methods_supported: array(string2()).optional(),
|
|
24415
|
+
token_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
|
|
24416
|
+
display_values_supported: array(string2()).optional(),
|
|
24417
|
+
claim_types_supported: array(string2()).optional(),
|
|
24418
|
+
claims_supported: array(string2()).optional(),
|
|
24419
|
+
service_documentation: string2().optional(),
|
|
24420
|
+
claims_locales_supported: array(string2()).optional(),
|
|
24421
|
+
ui_locales_supported: array(string2()).optional(),
|
|
24422
|
+
claims_parameter_supported: boolean2().optional(),
|
|
24423
|
+
request_parameter_supported: boolean2().optional(),
|
|
24424
|
+
request_uri_parameter_supported: boolean2().optional(),
|
|
24425
|
+
require_request_uri_registration: boolean2().optional(),
|
|
24426
|
+
op_policy_uri: SafeUrlSchema.optional(),
|
|
24427
|
+
op_tos_uri: SafeUrlSchema.optional(),
|
|
24428
|
+
client_id_metadata_document_supported: boolean2().optional()
|
|
24429
|
+
});
|
|
24430
|
+
var OpenIdProviderDiscoveryMetadataSchema = object2({
|
|
24431
|
+
...OpenIdProviderMetadataSchema.shape,
|
|
24432
|
+
...OAuthMetadataSchema.pick({
|
|
24433
|
+
code_challenge_methods_supported: true
|
|
24434
|
+
}).shape
|
|
24435
|
+
});
|
|
24436
|
+
var OAuthTokensSchema = object2({
|
|
24437
|
+
access_token: string2(),
|
|
24438
|
+
id_token: string2().optional(),
|
|
24439
|
+
// Optional for OAuth 2.1, but necessary in OpenID Connect
|
|
24440
|
+
token_type: string2(),
|
|
24441
|
+
expires_in: coerce_exports2.number().optional(),
|
|
24442
|
+
scope: string2().optional(),
|
|
24443
|
+
refresh_token: string2().optional()
|
|
24444
|
+
}).strip();
|
|
24445
|
+
var OAuthErrorResponseSchema = object2({
|
|
24446
|
+
error: string2(),
|
|
24447
|
+
error_description: string2().optional(),
|
|
24448
|
+
error_uri: string2().optional()
|
|
24449
|
+
});
|
|
24450
|
+
var OptionalSafeUrlSchema = SafeUrlSchema.optional().or(literal("").transform(() => void 0));
|
|
24451
|
+
var OAuthClientMetadataSchema = object2({
|
|
24452
|
+
redirect_uris: array(SafeUrlSchema),
|
|
24453
|
+
token_endpoint_auth_method: string2().optional(),
|
|
24454
|
+
grant_types: array(string2()).optional(),
|
|
24455
|
+
response_types: array(string2()).optional(),
|
|
24456
|
+
client_name: string2().optional(),
|
|
24457
|
+
client_uri: SafeUrlSchema.optional(),
|
|
24458
|
+
logo_uri: OptionalSafeUrlSchema,
|
|
24459
|
+
scope: string2().optional(),
|
|
24460
|
+
contacts: array(string2()).optional(),
|
|
24461
|
+
tos_uri: OptionalSafeUrlSchema,
|
|
24462
|
+
policy_uri: string2().optional(),
|
|
24463
|
+
jwks_uri: SafeUrlSchema.optional(),
|
|
24464
|
+
jwks: any().optional(),
|
|
24465
|
+
software_id: string2().optional(),
|
|
24466
|
+
software_version: string2().optional(),
|
|
24467
|
+
software_statement: string2().optional()
|
|
24468
|
+
}).strip();
|
|
24469
|
+
var OAuthClientInformationSchema = object2({
|
|
24470
|
+
client_id: string2(),
|
|
24471
|
+
client_secret: string2().optional(),
|
|
24472
|
+
client_id_issued_at: number2().optional(),
|
|
24473
|
+
client_secret_expires_at: number2().optional()
|
|
24474
|
+
}).strip();
|
|
24475
|
+
var OAuthClientInformationFullSchema = OAuthClientMetadataSchema.merge(OAuthClientInformationSchema);
|
|
24476
|
+
var OAuthClientRegistrationErrorSchema = object2({
|
|
24477
|
+
error: string2(),
|
|
24478
|
+
error_description: string2().optional()
|
|
24479
|
+
}).strip();
|
|
24480
|
+
var OAuthTokenRevocationRequestSchema = object2({
|
|
24481
|
+
token: string2(),
|
|
24482
|
+
token_type_hint: string2().optional()
|
|
24483
|
+
}).strip();
|
|
24484
|
+
|
|
24485
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.28.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth-utils.js
|
|
24486
|
+
function resourceUrlFromServerUrl(url2) {
|
|
24487
|
+
const resourceURL = typeof url2 === "string" ? new URL(url2) : new URL(url2.href);
|
|
24488
|
+
resourceURL.hash = "";
|
|
24489
|
+
return resourceURL;
|
|
24490
|
+
}
|
|
24491
|
+
function checkResourceAllowed({ requestedResource, configuredResource }) {
|
|
24492
|
+
const requested = typeof requestedResource === "string" ? new URL(requestedResource) : new URL(requestedResource.href);
|
|
24493
|
+
const configured = typeof configuredResource === "string" ? new URL(configuredResource) : new URL(configuredResource.href);
|
|
24494
|
+
if (requested.origin !== configured.origin) {
|
|
24495
|
+
return false;
|
|
24496
|
+
}
|
|
24497
|
+
if (requested.pathname.length < configured.pathname.length) {
|
|
24498
|
+
return false;
|
|
24499
|
+
}
|
|
24500
|
+
const requestedPath = requested.pathname.endsWith("/") ? requested.pathname : requested.pathname + "/";
|
|
24501
|
+
const configuredPath = configured.pathname.endsWith("/") ? configured.pathname : configured.pathname + "/";
|
|
24502
|
+
return requestedPath.startsWith(configuredPath);
|
|
24503
|
+
}
|
|
24504
|
+
|
|
24505
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.28.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/errors.js
|
|
24506
|
+
var OAuthError = class extends Error {
|
|
24507
|
+
constructor(message, errorUri) {
|
|
24508
|
+
super(message);
|
|
24509
|
+
this.errorUri = errorUri;
|
|
24510
|
+
this.name = this.constructor.name;
|
|
24511
|
+
}
|
|
24512
|
+
/**
|
|
24513
|
+
* Converts the error to a standard OAuth error response object
|
|
24514
|
+
*/
|
|
24515
|
+
toResponseObject() {
|
|
24516
|
+
const response = {
|
|
24517
|
+
error: this.errorCode,
|
|
24518
|
+
error_description: this.message
|
|
24519
|
+
};
|
|
24520
|
+
if (this.errorUri) {
|
|
24521
|
+
response.error_uri = this.errorUri;
|
|
24522
|
+
}
|
|
24523
|
+
return response;
|
|
24524
|
+
}
|
|
24525
|
+
get errorCode() {
|
|
24526
|
+
return this.constructor.errorCode;
|
|
24527
|
+
}
|
|
24528
|
+
};
|
|
24529
|
+
var InvalidRequestError = class extends OAuthError {
|
|
24530
|
+
};
|
|
24531
|
+
InvalidRequestError.errorCode = "invalid_request";
|
|
24532
|
+
var InvalidClientError = class extends OAuthError {
|
|
24533
|
+
};
|
|
24534
|
+
InvalidClientError.errorCode = "invalid_client";
|
|
24535
|
+
var InvalidGrantError = class extends OAuthError {
|
|
24536
|
+
};
|
|
24537
|
+
InvalidGrantError.errorCode = "invalid_grant";
|
|
24538
|
+
var UnauthorizedClientError = class extends OAuthError {
|
|
24539
|
+
};
|
|
24540
|
+
UnauthorizedClientError.errorCode = "unauthorized_client";
|
|
24541
|
+
var UnsupportedGrantTypeError = class extends OAuthError {
|
|
24542
|
+
};
|
|
24543
|
+
UnsupportedGrantTypeError.errorCode = "unsupported_grant_type";
|
|
24544
|
+
var InvalidScopeError = class extends OAuthError {
|
|
24545
|
+
};
|
|
24546
|
+
InvalidScopeError.errorCode = "invalid_scope";
|
|
24547
|
+
var AccessDeniedError = class extends OAuthError {
|
|
24548
|
+
};
|
|
24549
|
+
AccessDeniedError.errorCode = "access_denied";
|
|
24550
|
+
var ServerError = class extends OAuthError {
|
|
24551
|
+
};
|
|
24552
|
+
ServerError.errorCode = "server_error";
|
|
24553
|
+
var TemporarilyUnavailableError = class extends OAuthError {
|
|
24554
|
+
};
|
|
24555
|
+
TemporarilyUnavailableError.errorCode = "temporarily_unavailable";
|
|
24556
|
+
var UnsupportedResponseTypeError = class extends OAuthError {
|
|
24557
|
+
};
|
|
24558
|
+
UnsupportedResponseTypeError.errorCode = "unsupported_response_type";
|
|
24559
|
+
var UnsupportedTokenTypeError = class extends OAuthError {
|
|
24560
|
+
};
|
|
24561
|
+
UnsupportedTokenTypeError.errorCode = "unsupported_token_type";
|
|
24562
|
+
var InvalidTokenError = class extends OAuthError {
|
|
24563
|
+
};
|
|
24564
|
+
InvalidTokenError.errorCode = "invalid_token";
|
|
24565
|
+
var MethodNotAllowedError = class extends OAuthError {
|
|
24566
|
+
};
|
|
24567
|
+
MethodNotAllowedError.errorCode = "method_not_allowed";
|
|
24568
|
+
var TooManyRequestsError = class extends OAuthError {
|
|
24569
|
+
};
|
|
24570
|
+
TooManyRequestsError.errorCode = "too_many_requests";
|
|
24571
|
+
var InvalidClientMetadataError = class extends OAuthError {
|
|
24572
|
+
};
|
|
24573
|
+
InvalidClientMetadataError.errorCode = "invalid_client_metadata";
|
|
24574
|
+
var InsufficientScopeError = class extends OAuthError {
|
|
24575
|
+
};
|
|
24576
|
+
InsufficientScopeError.errorCode = "insufficient_scope";
|
|
24577
|
+
var InvalidTargetError = class extends OAuthError {
|
|
24578
|
+
};
|
|
24579
|
+
InvalidTargetError.errorCode = "invalid_target";
|
|
24580
|
+
var OAUTH_ERRORS = {
|
|
24581
|
+
[InvalidRequestError.errorCode]: InvalidRequestError,
|
|
24582
|
+
[InvalidClientError.errorCode]: InvalidClientError,
|
|
24583
|
+
[InvalidGrantError.errorCode]: InvalidGrantError,
|
|
24584
|
+
[UnauthorizedClientError.errorCode]: UnauthorizedClientError,
|
|
24585
|
+
[UnsupportedGrantTypeError.errorCode]: UnsupportedGrantTypeError,
|
|
24586
|
+
[InvalidScopeError.errorCode]: InvalidScopeError,
|
|
24587
|
+
[AccessDeniedError.errorCode]: AccessDeniedError,
|
|
24588
|
+
[ServerError.errorCode]: ServerError,
|
|
24589
|
+
[TemporarilyUnavailableError.errorCode]: TemporarilyUnavailableError,
|
|
24590
|
+
[UnsupportedResponseTypeError.errorCode]: UnsupportedResponseTypeError,
|
|
24591
|
+
[UnsupportedTokenTypeError.errorCode]: UnsupportedTokenTypeError,
|
|
24592
|
+
[InvalidTokenError.errorCode]: InvalidTokenError,
|
|
24593
|
+
[MethodNotAllowedError.errorCode]: MethodNotAllowedError,
|
|
24594
|
+
[TooManyRequestsError.errorCode]: TooManyRequestsError,
|
|
24595
|
+
[InvalidClientMetadataError.errorCode]: InvalidClientMetadataError,
|
|
24596
|
+
[InsufficientScopeError.errorCode]: InsufficientScopeError,
|
|
24597
|
+
[InvalidTargetError.errorCode]: InvalidTargetError
|
|
24598
|
+
};
|
|
24599
|
+
|
|
24600
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.28.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.js
|
|
24601
|
+
var UnauthorizedError = class extends Error {
|
|
24602
|
+
constructor(message) {
|
|
24603
|
+
super(message ?? "Unauthorized");
|
|
24604
|
+
}
|
|
24605
|
+
};
|
|
24606
|
+
function isClientAuthMethod(method) {
|
|
24607
|
+
return ["client_secret_basic", "client_secret_post", "none"].includes(method);
|
|
24608
|
+
}
|
|
24609
|
+
var AUTHORIZATION_CODE_RESPONSE_TYPE = "code";
|
|
24610
|
+
var AUTHORIZATION_CODE_CHALLENGE_METHOD = "S256";
|
|
24611
|
+
function selectClientAuthMethod(clientInformation, supportedMethods) {
|
|
24612
|
+
const hasClientSecret = clientInformation.client_secret !== void 0;
|
|
24613
|
+
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))) {
|
|
24614
|
+
return clientInformation.token_endpoint_auth_method;
|
|
24615
|
+
}
|
|
24616
|
+
if (supportedMethods.length === 0) {
|
|
24617
|
+
return hasClientSecret ? "client_secret_basic" : "none";
|
|
24618
|
+
}
|
|
24619
|
+
if (hasClientSecret && supportedMethods.includes("client_secret_basic")) {
|
|
24620
|
+
return "client_secret_basic";
|
|
24621
|
+
}
|
|
24622
|
+
if (hasClientSecret && supportedMethods.includes("client_secret_post")) {
|
|
24623
|
+
return "client_secret_post";
|
|
24624
|
+
}
|
|
24625
|
+
if (supportedMethods.includes("none")) {
|
|
24626
|
+
return "none";
|
|
24627
|
+
}
|
|
24628
|
+
return hasClientSecret ? "client_secret_post" : "none";
|
|
24629
|
+
}
|
|
24630
|
+
function applyClientAuthentication(method, clientInformation, headers, params) {
|
|
24631
|
+
const { client_id, client_secret } = clientInformation;
|
|
24632
|
+
switch (method) {
|
|
24633
|
+
case "client_secret_basic":
|
|
24634
|
+
applyBasicAuth(client_id, client_secret, headers);
|
|
24635
|
+
return;
|
|
24636
|
+
case "client_secret_post":
|
|
24637
|
+
applyPostAuth(client_id, client_secret, params);
|
|
24638
|
+
return;
|
|
24639
|
+
case "none":
|
|
24640
|
+
applyPublicAuth(client_id, params);
|
|
24641
|
+
return;
|
|
24642
|
+
default:
|
|
24643
|
+
throw new Error(`Unsupported client authentication method: ${method}`);
|
|
24644
|
+
}
|
|
24645
|
+
}
|
|
24646
|
+
function applyBasicAuth(clientId, clientSecret, headers) {
|
|
24647
|
+
if (!clientSecret) {
|
|
24648
|
+
throw new Error("client_secret_basic authentication requires a client_secret");
|
|
24649
|
+
}
|
|
24650
|
+
const credentials = btoa(`${clientId}:${clientSecret}`);
|
|
24651
|
+
headers.set("Authorization", `Basic ${credentials}`);
|
|
24652
|
+
}
|
|
24653
|
+
function applyPostAuth(clientId, clientSecret, params) {
|
|
24654
|
+
params.set("client_id", clientId);
|
|
24655
|
+
if (clientSecret) {
|
|
24656
|
+
params.set("client_secret", clientSecret);
|
|
24657
|
+
}
|
|
24658
|
+
}
|
|
24659
|
+
function applyPublicAuth(clientId, params) {
|
|
24660
|
+
params.set("client_id", clientId);
|
|
24661
|
+
}
|
|
24662
|
+
async function parseErrorResponse(input) {
|
|
24663
|
+
const statusCode = input instanceof Response ? input.status : void 0;
|
|
24664
|
+
const body = input instanceof Response ? await input.text() : input;
|
|
24665
|
+
try {
|
|
24666
|
+
const result = OAuthErrorResponseSchema.parse(JSON.parse(body));
|
|
24667
|
+
const { error: error2, error_description, error_uri } = result;
|
|
24668
|
+
const errorClass = OAUTH_ERRORS[error2] || ServerError;
|
|
24669
|
+
return new errorClass(error_description || "", error_uri);
|
|
24670
|
+
} catch (error2) {
|
|
24671
|
+
const errorMessage = `${statusCode ? `HTTP ${statusCode}: ` : ""}Invalid OAuth error response: ${error2}. Raw body: ${body}`;
|
|
24672
|
+
return new ServerError(errorMessage);
|
|
24673
|
+
}
|
|
24674
|
+
}
|
|
24675
|
+
async function auth(provider, options) {
|
|
24676
|
+
try {
|
|
24677
|
+
return await authInternal(provider, options);
|
|
24678
|
+
} catch (error2) {
|
|
24679
|
+
if (error2 instanceof InvalidClientError || error2 instanceof UnauthorizedClientError) {
|
|
24680
|
+
await provider.invalidateCredentials?.("all");
|
|
24681
|
+
return await authInternal(provider, options);
|
|
24682
|
+
} else if (error2 instanceof InvalidGrantError) {
|
|
24683
|
+
await provider.invalidateCredentials?.("tokens");
|
|
24684
|
+
return await authInternal(provider, options);
|
|
24685
|
+
}
|
|
24686
|
+
throw error2;
|
|
24687
|
+
}
|
|
24688
|
+
}
|
|
24689
|
+
async function authInternal(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl, fetchFn }) {
|
|
24690
|
+
const cachedState = await provider.discoveryState?.();
|
|
24691
|
+
let resourceMetadata;
|
|
24692
|
+
let authorizationServerUrl;
|
|
24693
|
+
let metadata;
|
|
24694
|
+
let effectiveResourceMetadataUrl = resourceMetadataUrl;
|
|
24695
|
+
if (!effectiveResourceMetadataUrl && cachedState?.resourceMetadataUrl) {
|
|
24696
|
+
effectiveResourceMetadataUrl = new URL(cachedState.resourceMetadataUrl);
|
|
24697
|
+
}
|
|
24698
|
+
if (cachedState?.authorizationServerUrl) {
|
|
24699
|
+
authorizationServerUrl = cachedState.authorizationServerUrl;
|
|
24700
|
+
resourceMetadata = cachedState.resourceMetadata;
|
|
24701
|
+
metadata = cachedState.authorizationServerMetadata ?? await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn });
|
|
24702
|
+
if (!resourceMetadata) {
|
|
24703
|
+
try {
|
|
24704
|
+
resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl: effectiveResourceMetadataUrl }, fetchFn);
|
|
24705
|
+
} catch {
|
|
24706
|
+
}
|
|
24707
|
+
}
|
|
24708
|
+
if (metadata !== cachedState.authorizationServerMetadata || resourceMetadata !== cachedState.resourceMetadata) {
|
|
24709
|
+
await provider.saveDiscoveryState?.({
|
|
24710
|
+
authorizationServerUrl: String(authorizationServerUrl),
|
|
24711
|
+
resourceMetadataUrl: effectiveResourceMetadataUrl?.toString(),
|
|
24712
|
+
resourceMetadata,
|
|
24713
|
+
authorizationServerMetadata: metadata
|
|
24714
|
+
});
|
|
24715
|
+
}
|
|
24716
|
+
} else {
|
|
24717
|
+
const serverInfo = await discoverOAuthServerInfo(serverUrl, { resourceMetadataUrl: effectiveResourceMetadataUrl, fetchFn });
|
|
24718
|
+
authorizationServerUrl = serverInfo.authorizationServerUrl;
|
|
24719
|
+
metadata = serverInfo.authorizationServerMetadata;
|
|
24720
|
+
resourceMetadata = serverInfo.resourceMetadata;
|
|
24721
|
+
await provider.saveDiscoveryState?.({
|
|
24722
|
+
authorizationServerUrl: String(authorizationServerUrl),
|
|
24723
|
+
resourceMetadataUrl: effectiveResourceMetadataUrl?.toString(),
|
|
24724
|
+
resourceMetadata,
|
|
24725
|
+
authorizationServerMetadata: metadata
|
|
24726
|
+
});
|
|
24727
|
+
}
|
|
24728
|
+
const resource = await selectResourceURL(serverUrl, provider, resourceMetadata);
|
|
24729
|
+
const resolvedScope = scope || resourceMetadata?.scopes_supported?.join(" ") || provider.clientMetadata.scope;
|
|
24730
|
+
let clientInformation = await Promise.resolve(provider.clientInformation());
|
|
24731
|
+
if (!clientInformation) {
|
|
24732
|
+
if (authorizationCode !== void 0) {
|
|
24733
|
+
throw new Error("Existing OAuth client information is required when exchanging an authorization code");
|
|
24734
|
+
}
|
|
24735
|
+
const supportsUrlBasedClientId = metadata?.client_id_metadata_document_supported === true;
|
|
24736
|
+
const clientMetadataUrl = provider.clientMetadataUrl;
|
|
24737
|
+
if (clientMetadataUrl && !isHttpsUrl(clientMetadataUrl)) {
|
|
24738
|
+
throw new InvalidClientMetadataError(`clientMetadataUrl must be a valid HTTPS URL with a non-root pathname, got: ${clientMetadataUrl}`);
|
|
24739
|
+
}
|
|
24740
|
+
const shouldUseUrlBasedClientId = supportsUrlBasedClientId && clientMetadataUrl;
|
|
24741
|
+
if (shouldUseUrlBasedClientId) {
|
|
24742
|
+
clientInformation = {
|
|
24743
|
+
client_id: clientMetadataUrl
|
|
24744
|
+
};
|
|
24745
|
+
await provider.saveClientInformation?.(clientInformation);
|
|
24746
|
+
} else {
|
|
24747
|
+
if (!provider.saveClientInformation) {
|
|
24748
|
+
throw new Error("OAuth client information must be saveable for dynamic registration");
|
|
24749
|
+
}
|
|
24750
|
+
const fullInformation = await registerClient(authorizationServerUrl, {
|
|
24751
|
+
metadata,
|
|
24752
|
+
clientMetadata: provider.clientMetadata,
|
|
24753
|
+
scope: resolvedScope,
|
|
24754
|
+
fetchFn
|
|
24755
|
+
});
|
|
24756
|
+
await provider.saveClientInformation(fullInformation);
|
|
24757
|
+
clientInformation = fullInformation;
|
|
24758
|
+
}
|
|
24759
|
+
}
|
|
24760
|
+
const nonInteractiveFlow = !provider.redirectUrl;
|
|
24761
|
+
if (authorizationCode !== void 0 || nonInteractiveFlow) {
|
|
24762
|
+
const tokens2 = await fetchToken(provider, authorizationServerUrl, {
|
|
24763
|
+
metadata,
|
|
24764
|
+
resource,
|
|
24765
|
+
authorizationCode,
|
|
24766
|
+
fetchFn
|
|
24767
|
+
});
|
|
24768
|
+
await provider.saveTokens(tokens2);
|
|
24769
|
+
return "AUTHORIZED";
|
|
24770
|
+
}
|
|
24771
|
+
const tokens = await provider.tokens();
|
|
24772
|
+
if (tokens?.refresh_token) {
|
|
24773
|
+
try {
|
|
24774
|
+
const newTokens = await refreshAuthorization(authorizationServerUrl, {
|
|
24775
|
+
metadata,
|
|
24776
|
+
clientInformation,
|
|
24777
|
+
refreshToken: tokens.refresh_token,
|
|
24778
|
+
resource,
|
|
24779
|
+
addClientAuthentication: provider.addClientAuthentication,
|
|
24780
|
+
fetchFn
|
|
24781
|
+
});
|
|
24782
|
+
await provider.saveTokens(newTokens);
|
|
24783
|
+
return "AUTHORIZED";
|
|
24784
|
+
} catch (error2) {
|
|
24785
|
+
if (!(error2 instanceof OAuthError) || error2 instanceof ServerError) {
|
|
24786
|
+
} else {
|
|
24787
|
+
throw error2;
|
|
24788
|
+
}
|
|
24789
|
+
}
|
|
24790
|
+
}
|
|
24791
|
+
const state = provider.state ? await provider.state() : void 0;
|
|
24792
|
+
const { authorizationUrl, codeVerifier } = await startAuthorization(authorizationServerUrl, {
|
|
24793
|
+
metadata,
|
|
24794
|
+
clientInformation,
|
|
24795
|
+
state,
|
|
24796
|
+
redirectUrl: provider.redirectUrl,
|
|
24797
|
+
scope: resolvedScope,
|
|
24798
|
+
resource
|
|
24799
|
+
});
|
|
24800
|
+
await provider.saveCodeVerifier(codeVerifier);
|
|
24801
|
+
await provider.redirectToAuthorization(authorizationUrl);
|
|
24802
|
+
return "REDIRECT";
|
|
24803
|
+
}
|
|
24804
|
+
function isHttpsUrl(value) {
|
|
24805
|
+
if (!value)
|
|
24806
|
+
return false;
|
|
24807
|
+
try {
|
|
24808
|
+
const url2 = new URL(value);
|
|
24809
|
+
return url2.protocol === "https:" && url2.pathname !== "/";
|
|
24810
|
+
} catch {
|
|
24811
|
+
return false;
|
|
24812
|
+
}
|
|
24813
|
+
}
|
|
24814
|
+
async function selectResourceURL(serverUrl, provider, resourceMetadata) {
|
|
24815
|
+
const defaultResource = resourceUrlFromServerUrl(serverUrl);
|
|
24816
|
+
if (provider.validateResourceURL) {
|
|
24817
|
+
return await provider.validateResourceURL(defaultResource, resourceMetadata?.resource);
|
|
24818
|
+
}
|
|
24819
|
+
if (!resourceMetadata) {
|
|
24820
|
+
return void 0;
|
|
24821
|
+
}
|
|
24822
|
+
if (!checkResourceAllowed({ requestedResource: defaultResource, configuredResource: resourceMetadata.resource })) {
|
|
24823
|
+
throw new Error(`Protected resource ${resourceMetadata.resource} does not match expected ${defaultResource} (or origin)`);
|
|
24824
|
+
}
|
|
24825
|
+
return new URL(resourceMetadata.resource);
|
|
24826
|
+
}
|
|
24827
|
+
function extractWWWAuthenticateParams(res) {
|
|
24828
|
+
const authenticateHeader = res.headers.get("WWW-Authenticate");
|
|
24829
|
+
if (!authenticateHeader) {
|
|
24830
|
+
return {};
|
|
24831
|
+
}
|
|
24832
|
+
const [type, scheme] = authenticateHeader.split(" ");
|
|
24833
|
+
if (type.toLowerCase() !== "bearer" || !scheme) {
|
|
24834
|
+
return {};
|
|
24835
|
+
}
|
|
24836
|
+
const resourceMetadataMatch = extractFieldFromWwwAuth(res, "resource_metadata") || void 0;
|
|
24837
|
+
let resourceMetadataUrl;
|
|
24838
|
+
if (resourceMetadataMatch) {
|
|
24839
|
+
try {
|
|
24840
|
+
resourceMetadataUrl = new URL(resourceMetadataMatch);
|
|
24841
|
+
} catch {
|
|
24842
|
+
}
|
|
24843
|
+
}
|
|
24844
|
+
const scope = extractFieldFromWwwAuth(res, "scope") || void 0;
|
|
24845
|
+
const error2 = extractFieldFromWwwAuth(res, "error") || void 0;
|
|
24846
|
+
return {
|
|
24847
|
+
resourceMetadataUrl,
|
|
24848
|
+
scope,
|
|
24849
|
+
error: error2
|
|
24850
|
+
};
|
|
24851
|
+
}
|
|
24852
|
+
function extractFieldFromWwwAuth(response, fieldName) {
|
|
24853
|
+
const wwwAuthHeader = response.headers.get("WWW-Authenticate");
|
|
24854
|
+
if (!wwwAuthHeader) {
|
|
24855
|
+
return null;
|
|
24856
|
+
}
|
|
24857
|
+
const pattern = new RegExp(`${fieldName}=(?:"([^"]+)"|([^\\s,]+))`);
|
|
24858
|
+
const match = wwwAuthHeader.match(pattern);
|
|
24859
|
+
if (match) {
|
|
24860
|
+
return match[1] || match[2];
|
|
24861
|
+
}
|
|
24862
|
+
return null;
|
|
24863
|
+
}
|
|
24864
|
+
async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn = fetch) {
|
|
24865
|
+
const response = await discoverMetadataWithFallback(serverUrl, "oauth-protected-resource", fetchFn, {
|
|
24866
|
+
protocolVersion: opts?.protocolVersion,
|
|
24867
|
+
metadataUrl: opts?.resourceMetadataUrl
|
|
24868
|
+
});
|
|
24869
|
+
if (!response || response.status === 404) {
|
|
24870
|
+
await response?.body?.cancel();
|
|
24871
|
+
throw new Error(`Resource server does not implement OAuth 2.0 Protected Resource Metadata.`);
|
|
24872
|
+
}
|
|
24873
|
+
if (!response.ok) {
|
|
24874
|
+
await response.body?.cancel();
|
|
24875
|
+
throw new Error(`HTTP ${response.status} trying to load well-known OAuth protected resource metadata.`);
|
|
24876
|
+
}
|
|
24877
|
+
return OAuthProtectedResourceMetadataSchema.parse(await response.json());
|
|
24878
|
+
}
|
|
24879
|
+
async function fetchWithCorsRetry(url2, headers, fetchFn = fetch) {
|
|
24880
|
+
try {
|
|
24881
|
+
return await fetchFn(url2, { headers });
|
|
24882
|
+
} catch (error2) {
|
|
24883
|
+
if (error2 instanceof TypeError) {
|
|
24884
|
+
if (headers) {
|
|
24885
|
+
return fetchWithCorsRetry(url2, void 0, fetchFn);
|
|
24886
|
+
} else {
|
|
24887
|
+
return void 0;
|
|
24888
|
+
}
|
|
24889
|
+
}
|
|
24890
|
+
throw error2;
|
|
24891
|
+
}
|
|
24892
|
+
}
|
|
24893
|
+
function buildWellKnownPath(wellKnownPrefix, pathname = "", options = {}) {
|
|
24894
|
+
if (pathname.endsWith("/")) {
|
|
24895
|
+
pathname = pathname.slice(0, -1);
|
|
24896
|
+
}
|
|
24897
|
+
return options.prependPathname ? `${pathname}/.well-known/${wellKnownPrefix}` : `/.well-known/${wellKnownPrefix}${pathname}`;
|
|
24898
|
+
}
|
|
24899
|
+
async function tryMetadataDiscovery(url2, protocolVersion, fetchFn = fetch) {
|
|
24900
|
+
const headers = {
|
|
24901
|
+
"MCP-Protocol-Version": protocolVersion
|
|
24902
|
+
};
|
|
24903
|
+
return await fetchWithCorsRetry(url2, headers, fetchFn);
|
|
24904
|
+
}
|
|
24905
|
+
function shouldAttemptFallback(response, pathname) {
|
|
24906
|
+
return !response || response.status >= 400 && response.status < 500 && pathname !== "/";
|
|
24907
|
+
}
|
|
24908
|
+
async function discoverMetadataWithFallback(serverUrl, wellKnownType, fetchFn, opts) {
|
|
24909
|
+
const issuer = new URL(serverUrl);
|
|
24910
|
+
const protocolVersion = opts?.protocolVersion ?? LATEST_PROTOCOL_VERSION;
|
|
24911
|
+
let url2;
|
|
24912
|
+
if (opts?.metadataUrl) {
|
|
24913
|
+
url2 = new URL(opts.metadataUrl);
|
|
24914
|
+
} else {
|
|
24915
|
+
const wellKnownPath = buildWellKnownPath(wellKnownType, issuer.pathname);
|
|
24916
|
+
url2 = new URL(wellKnownPath, opts?.metadataServerUrl ?? issuer);
|
|
24917
|
+
url2.search = issuer.search;
|
|
24918
|
+
}
|
|
24919
|
+
let response = await tryMetadataDiscovery(url2, protocolVersion, fetchFn);
|
|
24920
|
+
if (!opts?.metadataUrl && shouldAttemptFallback(response, issuer.pathname)) {
|
|
24921
|
+
const rootUrl = new URL(`/.well-known/${wellKnownType}`, issuer);
|
|
24922
|
+
response = await tryMetadataDiscovery(rootUrl, protocolVersion, fetchFn);
|
|
24923
|
+
}
|
|
24924
|
+
return response;
|
|
24925
|
+
}
|
|
24926
|
+
function buildDiscoveryUrls(authorizationServerUrl) {
|
|
24927
|
+
const url2 = typeof authorizationServerUrl === "string" ? new URL(authorizationServerUrl) : authorizationServerUrl;
|
|
24928
|
+
const hasPath = url2.pathname !== "/";
|
|
24929
|
+
const urlsToTry = [];
|
|
24930
|
+
if (!hasPath) {
|
|
24931
|
+
urlsToTry.push({
|
|
24932
|
+
url: new URL("/.well-known/oauth-authorization-server", url2.origin),
|
|
24933
|
+
type: "oauth"
|
|
24934
|
+
});
|
|
24935
|
+
urlsToTry.push({
|
|
24936
|
+
url: new URL(`/.well-known/openid-configuration`, url2.origin),
|
|
24937
|
+
type: "oidc"
|
|
24938
|
+
});
|
|
24939
|
+
return urlsToTry;
|
|
24940
|
+
}
|
|
24941
|
+
let pathname = url2.pathname;
|
|
24942
|
+
if (pathname.endsWith("/")) {
|
|
24943
|
+
pathname = pathname.slice(0, -1);
|
|
24944
|
+
}
|
|
24945
|
+
urlsToTry.push({
|
|
24946
|
+
url: new URL(`/.well-known/oauth-authorization-server${pathname}`, url2.origin),
|
|
24947
|
+
type: "oauth"
|
|
24948
|
+
});
|
|
24949
|
+
urlsToTry.push({
|
|
24950
|
+
url: new URL(`/.well-known/openid-configuration${pathname}`, url2.origin),
|
|
24951
|
+
type: "oidc"
|
|
24952
|
+
});
|
|
24953
|
+
urlsToTry.push({
|
|
24954
|
+
url: new URL(`${pathname}/.well-known/openid-configuration`, url2.origin),
|
|
24955
|
+
type: "oidc"
|
|
24956
|
+
});
|
|
24957
|
+
return urlsToTry;
|
|
24958
|
+
}
|
|
24959
|
+
async function discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn = fetch, protocolVersion = LATEST_PROTOCOL_VERSION } = {}) {
|
|
24960
|
+
const headers = {
|
|
24961
|
+
"MCP-Protocol-Version": protocolVersion,
|
|
24962
|
+
Accept: "application/json"
|
|
24963
|
+
};
|
|
24964
|
+
const urlsToTry = buildDiscoveryUrls(authorizationServerUrl);
|
|
24965
|
+
for (const { url: endpointUrl, type } of urlsToTry) {
|
|
24966
|
+
const response = await fetchWithCorsRetry(endpointUrl, headers, fetchFn);
|
|
24967
|
+
if (!response) {
|
|
24968
|
+
continue;
|
|
24969
|
+
}
|
|
24970
|
+
if (!response.ok) {
|
|
24971
|
+
await response.body?.cancel();
|
|
24972
|
+
if (response.status >= 400 && response.status < 500) {
|
|
24973
|
+
continue;
|
|
24974
|
+
}
|
|
24975
|
+
throw new Error(`HTTP ${response.status} trying to load ${type === "oauth" ? "OAuth" : "OpenID provider"} metadata from ${endpointUrl}`);
|
|
24976
|
+
}
|
|
24977
|
+
if (type === "oauth") {
|
|
24978
|
+
return OAuthMetadataSchema.parse(await response.json());
|
|
24979
|
+
} else {
|
|
24980
|
+
return OpenIdProviderDiscoveryMetadataSchema.parse(await response.json());
|
|
24981
|
+
}
|
|
24982
|
+
}
|
|
24983
|
+
return void 0;
|
|
24984
|
+
}
|
|
24985
|
+
async function discoverOAuthServerInfo(serverUrl, opts) {
|
|
24986
|
+
let resourceMetadata;
|
|
24987
|
+
let authorizationServerUrl;
|
|
24988
|
+
try {
|
|
24989
|
+
resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl: opts?.resourceMetadataUrl }, opts?.fetchFn);
|
|
24990
|
+
if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) {
|
|
24991
|
+
authorizationServerUrl = resourceMetadata.authorization_servers[0];
|
|
24992
|
+
}
|
|
24993
|
+
} catch {
|
|
24994
|
+
}
|
|
24995
|
+
if (!authorizationServerUrl) {
|
|
24996
|
+
authorizationServerUrl = String(new URL("/", serverUrl));
|
|
24997
|
+
}
|
|
24998
|
+
const authorizationServerMetadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn: opts?.fetchFn });
|
|
24999
|
+
return {
|
|
25000
|
+
authorizationServerUrl,
|
|
25001
|
+
authorizationServerMetadata,
|
|
25002
|
+
resourceMetadata
|
|
25003
|
+
};
|
|
25004
|
+
}
|
|
25005
|
+
async function startAuthorization(authorizationServerUrl, { metadata, clientInformation, redirectUrl, scope, state, resource }) {
|
|
25006
|
+
let authorizationUrl;
|
|
25007
|
+
if (metadata) {
|
|
25008
|
+
authorizationUrl = new URL(metadata.authorization_endpoint);
|
|
25009
|
+
if (!metadata.response_types_supported.includes(AUTHORIZATION_CODE_RESPONSE_TYPE)) {
|
|
25010
|
+
throw new Error(`Incompatible auth server: does not support response type ${AUTHORIZATION_CODE_RESPONSE_TYPE}`);
|
|
25011
|
+
}
|
|
25012
|
+
if (metadata.code_challenge_methods_supported && !metadata.code_challenge_methods_supported.includes(AUTHORIZATION_CODE_CHALLENGE_METHOD)) {
|
|
25013
|
+
throw new Error(`Incompatible auth server: does not support code challenge method ${AUTHORIZATION_CODE_CHALLENGE_METHOD}`);
|
|
25014
|
+
}
|
|
25015
|
+
} else {
|
|
25016
|
+
authorizationUrl = new URL("/authorize", authorizationServerUrl);
|
|
25017
|
+
}
|
|
25018
|
+
const challenge = await pkceChallenge();
|
|
25019
|
+
const codeVerifier = challenge.code_verifier;
|
|
25020
|
+
const codeChallenge = challenge.code_challenge;
|
|
25021
|
+
authorizationUrl.searchParams.set("response_type", AUTHORIZATION_CODE_RESPONSE_TYPE);
|
|
25022
|
+
authorizationUrl.searchParams.set("client_id", clientInformation.client_id);
|
|
25023
|
+
authorizationUrl.searchParams.set("code_challenge", codeChallenge);
|
|
25024
|
+
authorizationUrl.searchParams.set("code_challenge_method", AUTHORIZATION_CODE_CHALLENGE_METHOD);
|
|
25025
|
+
authorizationUrl.searchParams.set("redirect_uri", String(redirectUrl));
|
|
25026
|
+
if (state) {
|
|
25027
|
+
authorizationUrl.searchParams.set("state", state);
|
|
25028
|
+
}
|
|
25029
|
+
if (scope) {
|
|
25030
|
+
authorizationUrl.searchParams.set("scope", scope);
|
|
25031
|
+
}
|
|
25032
|
+
if (scope?.includes("offline_access")) {
|
|
25033
|
+
authorizationUrl.searchParams.append("prompt", "consent");
|
|
25034
|
+
}
|
|
25035
|
+
if (resource) {
|
|
25036
|
+
authorizationUrl.searchParams.set("resource", resource.href);
|
|
25037
|
+
}
|
|
25038
|
+
return { authorizationUrl, codeVerifier };
|
|
25039
|
+
}
|
|
25040
|
+
function prepareAuthorizationCodeRequest(authorizationCode, codeVerifier, redirectUri) {
|
|
25041
|
+
return new URLSearchParams({
|
|
25042
|
+
grant_type: "authorization_code",
|
|
25043
|
+
code: authorizationCode,
|
|
25044
|
+
code_verifier: codeVerifier,
|
|
25045
|
+
redirect_uri: String(redirectUri)
|
|
25046
|
+
});
|
|
25047
|
+
}
|
|
25048
|
+
async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequestParams, clientInformation, addClientAuthentication, resource, fetchFn }) {
|
|
25049
|
+
const tokenUrl = metadata?.token_endpoint ? new URL(metadata.token_endpoint) : new URL("/token", authorizationServerUrl);
|
|
25050
|
+
const headers = new Headers({
|
|
25051
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
25052
|
+
Accept: "application/json"
|
|
25053
|
+
});
|
|
25054
|
+
if (resource) {
|
|
25055
|
+
tokenRequestParams.set("resource", resource.href);
|
|
25056
|
+
}
|
|
25057
|
+
if (addClientAuthentication) {
|
|
25058
|
+
await addClientAuthentication(headers, tokenRequestParams, tokenUrl, metadata);
|
|
25059
|
+
} else if (clientInformation) {
|
|
25060
|
+
const supportedMethods = metadata?.token_endpoint_auth_methods_supported ?? [];
|
|
25061
|
+
const authMethod = selectClientAuthMethod(clientInformation, supportedMethods);
|
|
25062
|
+
applyClientAuthentication(authMethod, clientInformation, headers, tokenRequestParams);
|
|
25063
|
+
}
|
|
25064
|
+
const response = await (fetchFn ?? fetch)(tokenUrl, {
|
|
25065
|
+
method: "POST",
|
|
25066
|
+
headers,
|
|
25067
|
+
body: tokenRequestParams
|
|
25068
|
+
});
|
|
25069
|
+
if (!response.ok) {
|
|
25070
|
+
throw await parseErrorResponse(response);
|
|
25071
|
+
}
|
|
25072
|
+
return OAuthTokensSchema.parse(await response.json());
|
|
25073
|
+
}
|
|
25074
|
+
async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, fetchFn }) {
|
|
25075
|
+
const tokenRequestParams = new URLSearchParams({
|
|
25076
|
+
grant_type: "refresh_token",
|
|
25077
|
+
refresh_token: refreshToken
|
|
25078
|
+
});
|
|
25079
|
+
const tokens = await executeTokenRequest(authorizationServerUrl, {
|
|
25080
|
+
metadata,
|
|
25081
|
+
tokenRequestParams,
|
|
25082
|
+
clientInformation,
|
|
25083
|
+
addClientAuthentication,
|
|
25084
|
+
resource,
|
|
25085
|
+
fetchFn
|
|
25086
|
+
});
|
|
25087
|
+
return { refresh_token: refreshToken, ...tokens };
|
|
25088
|
+
}
|
|
25089
|
+
async function fetchToken(provider, authorizationServerUrl, { metadata, resource, authorizationCode, fetchFn } = {}) {
|
|
25090
|
+
const scope = provider.clientMetadata.scope;
|
|
25091
|
+
let tokenRequestParams;
|
|
25092
|
+
if (provider.prepareTokenRequest) {
|
|
25093
|
+
tokenRequestParams = await provider.prepareTokenRequest(scope);
|
|
25094
|
+
}
|
|
25095
|
+
if (!tokenRequestParams) {
|
|
25096
|
+
if (!authorizationCode) {
|
|
25097
|
+
throw new Error("Either provider.prepareTokenRequest() or authorizationCode is required");
|
|
25098
|
+
}
|
|
25099
|
+
if (!provider.redirectUrl) {
|
|
25100
|
+
throw new Error("redirectUrl is required for authorization_code flow");
|
|
25101
|
+
}
|
|
25102
|
+
const codeVerifier = await provider.codeVerifier();
|
|
25103
|
+
tokenRequestParams = prepareAuthorizationCodeRequest(authorizationCode, codeVerifier, provider.redirectUrl);
|
|
25104
|
+
}
|
|
25105
|
+
const clientInformation = await provider.clientInformation();
|
|
25106
|
+
return executeTokenRequest(authorizationServerUrl, {
|
|
25107
|
+
metadata,
|
|
25108
|
+
tokenRequestParams,
|
|
25109
|
+
clientInformation: clientInformation ?? void 0,
|
|
25110
|
+
addClientAuthentication: provider.addClientAuthentication,
|
|
25111
|
+
resource,
|
|
25112
|
+
fetchFn
|
|
25113
|
+
});
|
|
25114
|
+
}
|
|
25115
|
+
async function registerClient(authorizationServerUrl, { metadata, clientMetadata, scope, fetchFn }) {
|
|
25116
|
+
let registrationUrl;
|
|
25117
|
+
if (metadata) {
|
|
25118
|
+
if (!metadata.registration_endpoint) {
|
|
25119
|
+
throw new Error("Incompatible auth server: does not support dynamic client registration");
|
|
25120
|
+
}
|
|
25121
|
+
registrationUrl = new URL(metadata.registration_endpoint);
|
|
25122
|
+
} else {
|
|
25123
|
+
registrationUrl = new URL("/register", authorizationServerUrl);
|
|
25124
|
+
}
|
|
25125
|
+
const response = await (fetchFn ?? fetch)(registrationUrl, {
|
|
25126
|
+
method: "POST",
|
|
25127
|
+
headers: {
|
|
25128
|
+
"Content-Type": "application/json"
|
|
25129
|
+
},
|
|
25130
|
+
body: JSON.stringify({
|
|
25131
|
+
...clientMetadata,
|
|
25132
|
+
...scope !== void 0 ? { scope } : {}
|
|
25133
|
+
})
|
|
25134
|
+
});
|
|
25135
|
+
if (!response.ok) {
|
|
25136
|
+
throw await parseErrorResponse(response);
|
|
25137
|
+
}
|
|
25138
|
+
return OAuthClientInformationFullSchema.parse(await response.json());
|
|
25139
|
+
}
|
|
25140
|
+
|
|
25141
|
+
// ../../node_modules/.pnpm/eventsource-parser@3.0.6/node_modules/eventsource-parser/dist/index.js
|
|
25142
|
+
var ParseError = class extends Error {
|
|
25143
|
+
constructor(message, options) {
|
|
25144
|
+
super(message), this.name = "ParseError", this.type = options.type, this.field = options.field, this.value = options.value, this.line = options.line;
|
|
25145
|
+
}
|
|
25146
|
+
};
|
|
25147
|
+
function noop(_arg) {
|
|
25148
|
+
}
|
|
25149
|
+
function createParser(callbacks) {
|
|
25150
|
+
if (typeof callbacks == "function")
|
|
25151
|
+
throw new TypeError(
|
|
25152
|
+
"`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?"
|
|
25153
|
+
);
|
|
25154
|
+
const { onEvent = noop, onError = noop, onRetry = noop, onComment } = callbacks;
|
|
25155
|
+
let incompleteLine = "", isFirstChunk = true, id, data = "", eventType = "";
|
|
25156
|
+
function feed(newChunk) {
|
|
25157
|
+
const chunk = isFirstChunk ? newChunk.replace(/^\xEF\xBB\xBF/, "") : newChunk, [complete, incomplete] = splitLines(`${incompleteLine}${chunk}`);
|
|
25158
|
+
for (const line of complete)
|
|
25159
|
+
parseLine(line);
|
|
25160
|
+
incompleteLine = incomplete, isFirstChunk = false;
|
|
25161
|
+
}
|
|
25162
|
+
function parseLine(line) {
|
|
25163
|
+
if (line === "") {
|
|
25164
|
+
dispatchEvent();
|
|
25165
|
+
return;
|
|
25166
|
+
}
|
|
25167
|
+
if (line.startsWith(":")) {
|
|
25168
|
+
onComment && onComment(line.slice(line.startsWith(": ") ? 2 : 1));
|
|
25169
|
+
return;
|
|
25170
|
+
}
|
|
25171
|
+
const fieldSeparatorIndex = line.indexOf(":");
|
|
25172
|
+
if (fieldSeparatorIndex !== -1) {
|
|
25173
|
+
const field = line.slice(0, fieldSeparatorIndex), offset = line[fieldSeparatorIndex + 1] === " " ? 2 : 1, value = line.slice(fieldSeparatorIndex + offset);
|
|
25174
|
+
processField(field, value, line);
|
|
25175
|
+
return;
|
|
25176
|
+
}
|
|
25177
|
+
processField(line, "", line);
|
|
25178
|
+
}
|
|
25179
|
+
function processField(field, value, line) {
|
|
25180
|
+
switch (field) {
|
|
25181
|
+
case "event":
|
|
25182
|
+
eventType = value;
|
|
25183
|
+
break;
|
|
25184
|
+
case "data":
|
|
25185
|
+
data = `${data}${value}
|
|
25186
|
+
`;
|
|
25187
|
+
break;
|
|
25188
|
+
case "id":
|
|
25189
|
+
id = value.includes("\0") ? void 0 : value;
|
|
25190
|
+
break;
|
|
25191
|
+
case "retry":
|
|
25192
|
+
/^\d+$/.test(value) ? onRetry(parseInt(value, 10)) : onError(
|
|
25193
|
+
new ParseError(`Invalid \`retry\` value: "${value}"`, {
|
|
25194
|
+
type: "invalid-retry",
|
|
25195
|
+
value,
|
|
25196
|
+
line
|
|
25197
|
+
})
|
|
25198
|
+
);
|
|
25199
|
+
break;
|
|
25200
|
+
default:
|
|
25201
|
+
onError(
|
|
25202
|
+
new ParseError(
|
|
25203
|
+
`Unknown field "${field.length > 20 ? `${field.slice(0, 20)}\u2026` : field}"`,
|
|
25204
|
+
{ type: "unknown-field", field, value, line }
|
|
25205
|
+
)
|
|
25206
|
+
);
|
|
25207
|
+
break;
|
|
25208
|
+
}
|
|
25209
|
+
}
|
|
25210
|
+
function dispatchEvent() {
|
|
25211
|
+
data.length > 0 && onEvent({
|
|
25212
|
+
id,
|
|
25213
|
+
event: eventType || void 0,
|
|
25214
|
+
// If the data buffer's last character is a U+000A LINE FEED (LF) character,
|
|
25215
|
+
// then remove the last character from the data buffer.
|
|
25216
|
+
data: data.endsWith(`
|
|
25217
|
+
`) ? data.slice(0, -1) : data
|
|
25218
|
+
}), id = void 0, data = "", eventType = "";
|
|
25219
|
+
}
|
|
25220
|
+
function reset(options = {}) {
|
|
25221
|
+
incompleteLine && options.consume && parseLine(incompleteLine), isFirstChunk = true, id = void 0, data = "", eventType = "", incompleteLine = "";
|
|
25222
|
+
}
|
|
25223
|
+
return { feed, reset };
|
|
25224
|
+
}
|
|
25225
|
+
function splitLines(chunk) {
|
|
25226
|
+
const lines = [];
|
|
25227
|
+
let incompleteLine = "", searchIndex = 0;
|
|
25228
|
+
for (; searchIndex < chunk.length; ) {
|
|
25229
|
+
const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
|
|
25230
|
+
`, searchIndex);
|
|
25231
|
+
let lineEnd = -1;
|
|
25232
|
+
if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = Math.min(crIndex, lfIndex) : crIndex !== -1 ? crIndex === chunk.length - 1 ? lineEnd = -1 : lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1) {
|
|
25233
|
+
incompleteLine = chunk.slice(searchIndex);
|
|
25234
|
+
break;
|
|
25235
|
+
} else {
|
|
25236
|
+
const line = chunk.slice(searchIndex, lineEnd);
|
|
25237
|
+
lines.push(line), searchIndex = lineEnd + 1, chunk[searchIndex - 1] === "\r" && chunk[searchIndex] === `
|
|
25238
|
+
` && searchIndex++;
|
|
25239
|
+
}
|
|
25240
|
+
}
|
|
25241
|
+
return [lines, incompleteLine];
|
|
25242
|
+
}
|
|
25243
|
+
|
|
25244
|
+
// ../../node_modules/.pnpm/eventsource-parser@3.0.6/node_modules/eventsource-parser/dist/stream.js
|
|
25245
|
+
var EventSourceParserStream = class extends TransformStream {
|
|
25246
|
+
constructor({ onError, onRetry, onComment } = {}) {
|
|
25247
|
+
let parser;
|
|
25248
|
+
super({
|
|
25249
|
+
start(controller) {
|
|
25250
|
+
parser = createParser({
|
|
25251
|
+
onEvent: (event) => {
|
|
25252
|
+
controller.enqueue(event);
|
|
25253
|
+
},
|
|
25254
|
+
onError(error2) {
|
|
25255
|
+
onError === "terminate" ? controller.error(error2) : typeof onError == "function" && onError(error2);
|
|
25256
|
+
},
|
|
25257
|
+
onRetry,
|
|
25258
|
+
onComment
|
|
25259
|
+
});
|
|
25260
|
+
},
|
|
25261
|
+
transform(chunk) {
|
|
25262
|
+
parser.feed(chunk);
|
|
25263
|
+
}
|
|
25264
|
+
});
|
|
25265
|
+
}
|
|
25266
|
+
};
|
|
25267
|
+
|
|
25268
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.28.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js
|
|
25269
|
+
var DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS = {
|
|
25270
|
+
initialReconnectionDelay: 1e3,
|
|
25271
|
+
maxReconnectionDelay: 3e4,
|
|
25272
|
+
reconnectionDelayGrowFactor: 1.5,
|
|
25273
|
+
maxRetries: 2
|
|
25274
|
+
};
|
|
25275
|
+
var StreamableHTTPError = class extends Error {
|
|
25276
|
+
constructor(code, message) {
|
|
25277
|
+
super(`Streamable HTTP error: ${message}`);
|
|
25278
|
+
this.code = code;
|
|
25279
|
+
}
|
|
25280
|
+
};
|
|
25281
|
+
var StreamableHTTPClientTransport = class {
|
|
25282
|
+
constructor(url2, opts) {
|
|
25283
|
+
this._hasCompletedAuthFlow = false;
|
|
25284
|
+
this._url = url2;
|
|
25285
|
+
this._resourceMetadataUrl = void 0;
|
|
25286
|
+
this._scope = void 0;
|
|
25287
|
+
this._requestInit = opts?.requestInit;
|
|
25288
|
+
this._authProvider = opts?.authProvider;
|
|
25289
|
+
this._fetch = opts?.fetch;
|
|
25290
|
+
this._fetchWithInit = createFetchWithInit(opts?.fetch, opts?.requestInit);
|
|
25291
|
+
this._sessionId = opts?.sessionId;
|
|
25292
|
+
this._reconnectionOptions = opts?.reconnectionOptions ?? DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS;
|
|
25293
|
+
}
|
|
25294
|
+
async _authThenStart() {
|
|
25295
|
+
if (!this._authProvider) {
|
|
25296
|
+
throw new UnauthorizedError("No auth provider");
|
|
25297
|
+
}
|
|
25298
|
+
let result;
|
|
25299
|
+
try {
|
|
25300
|
+
result = await auth(this._authProvider, {
|
|
25301
|
+
serverUrl: this._url,
|
|
25302
|
+
resourceMetadataUrl: this._resourceMetadataUrl,
|
|
25303
|
+
scope: this._scope,
|
|
25304
|
+
fetchFn: this._fetchWithInit
|
|
25305
|
+
});
|
|
25306
|
+
} catch (error2) {
|
|
25307
|
+
this.onerror?.(error2);
|
|
25308
|
+
throw error2;
|
|
25309
|
+
}
|
|
25310
|
+
if (result !== "AUTHORIZED") {
|
|
25311
|
+
throw new UnauthorizedError();
|
|
25312
|
+
}
|
|
25313
|
+
return await this._startOrAuthSse({ resumptionToken: void 0 });
|
|
25314
|
+
}
|
|
25315
|
+
async _commonHeaders() {
|
|
25316
|
+
const headers = {};
|
|
25317
|
+
if (this._authProvider) {
|
|
25318
|
+
const tokens = await this._authProvider.tokens();
|
|
25319
|
+
if (tokens) {
|
|
25320
|
+
headers["Authorization"] = `Bearer ${tokens.access_token}`;
|
|
25321
|
+
}
|
|
25322
|
+
}
|
|
25323
|
+
if (this._sessionId) {
|
|
25324
|
+
headers["mcp-session-id"] = this._sessionId;
|
|
25325
|
+
}
|
|
25326
|
+
if (this._protocolVersion) {
|
|
25327
|
+
headers["mcp-protocol-version"] = this._protocolVersion;
|
|
25328
|
+
}
|
|
25329
|
+
const extraHeaders = normalizeHeaders(this._requestInit?.headers);
|
|
25330
|
+
return new Headers({
|
|
25331
|
+
...headers,
|
|
25332
|
+
...extraHeaders
|
|
25333
|
+
});
|
|
25334
|
+
}
|
|
25335
|
+
async _startOrAuthSse(options) {
|
|
25336
|
+
const { resumptionToken } = options;
|
|
25337
|
+
try {
|
|
25338
|
+
const headers = await this._commonHeaders();
|
|
25339
|
+
headers.set("Accept", "text/event-stream");
|
|
25340
|
+
if (resumptionToken) {
|
|
25341
|
+
headers.set("last-event-id", resumptionToken);
|
|
25342
|
+
}
|
|
25343
|
+
const response = await (this._fetch ?? fetch)(this._url, {
|
|
25344
|
+
method: "GET",
|
|
25345
|
+
headers,
|
|
25346
|
+
signal: this._abortController?.signal
|
|
25347
|
+
});
|
|
25348
|
+
if (!response.ok) {
|
|
25349
|
+
await response.body?.cancel();
|
|
25350
|
+
if (response.status === 401 && this._authProvider) {
|
|
25351
|
+
return await this._authThenStart();
|
|
25352
|
+
}
|
|
25353
|
+
if (response.status === 405) {
|
|
25354
|
+
return;
|
|
25355
|
+
}
|
|
25356
|
+
throw new StreamableHTTPError(response.status, `Failed to open SSE stream: ${response.statusText}`);
|
|
25357
|
+
}
|
|
25358
|
+
this._handleSseStream(response.body, options, true);
|
|
25359
|
+
} catch (error2) {
|
|
25360
|
+
this.onerror?.(error2);
|
|
25361
|
+
throw error2;
|
|
25362
|
+
}
|
|
25363
|
+
}
|
|
25364
|
+
/**
|
|
25365
|
+
* Calculates the next reconnection delay using backoff algorithm
|
|
25366
|
+
*
|
|
25367
|
+
* @param attempt Current reconnection attempt count for the specific stream
|
|
25368
|
+
* @returns Time to wait in milliseconds before next reconnection attempt
|
|
25369
|
+
*/
|
|
25370
|
+
_getNextReconnectionDelay(attempt) {
|
|
25371
|
+
if (this._serverRetryMs !== void 0) {
|
|
25372
|
+
return this._serverRetryMs;
|
|
25373
|
+
}
|
|
25374
|
+
const initialDelay = this._reconnectionOptions.initialReconnectionDelay;
|
|
25375
|
+
const growFactor = this._reconnectionOptions.reconnectionDelayGrowFactor;
|
|
25376
|
+
const maxDelay = this._reconnectionOptions.maxReconnectionDelay;
|
|
25377
|
+
return Math.min(initialDelay * Math.pow(growFactor, attempt), maxDelay);
|
|
25378
|
+
}
|
|
25379
|
+
/**
|
|
25380
|
+
* Schedule a reconnection attempt using server-provided retry interval or backoff
|
|
25381
|
+
*
|
|
25382
|
+
* @param lastEventId The ID of the last received event for resumability
|
|
25383
|
+
* @param attemptCount Current reconnection attempt count for this specific stream
|
|
25384
|
+
*/
|
|
25385
|
+
_scheduleReconnection(options, attemptCount = 0) {
|
|
25386
|
+
const maxRetries = this._reconnectionOptions.maxRetries;
|
|
25387
|
+
if (attemptCount >= maxRetries) {
|
|
25388
|
+
this.onerror?.(new Error(`Maximum reconnection attempts (${maxRetries}) exceeded.`));
|
|
25389
|
+
return;
|
|
25390
|
+
}
|
|
25391
|
+
const delay = this._getNextReconnectionDelay(attemptCount);
|
|
25392
|
+
this._reconnectionTimeout = setTimeout(() => {
|
|
25393
|
+
this._startOrAuthSse(options).catch((error2) => {
|
|
25394
|
+
this.onerror?.(new Error(`Failed to reconnect SSE stream: ${error2 instanceof Error ? error2.message : String(error2)}`));
|
|
25395
|
+
this._scheduleReconnection(options, attemptCount + 1);
|
|
25396
|
+
});
|
|
25397
|
+
}, delay);
|
|
25398
|
+
}
|
|
25399
|
+
_handleSseStream(stream, options, isReconnectable) {
|
|
25400
|
+
if (!stream) {
|
|
25401
|
+
return;
|
|
25402
|
+
}
|
|
25403
|
+
const { onresumptiontoken, replayMessageId } = options;
|
|
25404
|
+
let lastEventId;
|
|
25405
|
+
let hasPrimingEvent = false;
|
|
25406
|
+
let receivedResponse = false;
|
|
25407
|
+
const processStream = async () => {
|
|
25408
|
+
try {
|
|
25409
|
+
const reader = stream.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream({
|
|
25410
|
+
onRetry: (retryMs) => {
|
|
25411
|
+
this._serverRetryMs = retryMs;
|
|
25412
|
+
}
|
|
25413
|
+
})).getReader();
|
|
25414
|
+
while (true) {
|
|
25415
|
+
const { value: event, done } = await reader.read();
|
|
25416
|
+
if (done) {
|
|
25417
|
+
break;
|
|
25418
|
+
}
|
|
25419
|
+
if (event.id) {
|
|
25420
|
+
lastEventId = event.id;
|
|
25421
|
+
hasPrimingEvent = true;
|
|
25422
|
+
onresumptiontoken?.(event.id);
|
|
25423
|
+
}
|
|
25424
|
+
if (!event.data) {
|
|
25425
|
+
continue;
|
|
25426
|
+
}
|
|
25427
|
+
if (!event.event || event.event === "message") {
|
|
25428
|
+
try {
|
|
25429
|
+
const message = JSONRPCMessageSchema.parse(JSON.parse(event.data));
|
|
25430
|
+
if (isJSONRPCResultResponse(message)) {
|
|
25431
|
+
receivedResponse = true;
|
|
25432
|
+
if (replayMessageId !== void 0) {
|
|
25433
|
+
message.id = replayMessageId;
|
|
25434
|
+
}
|
|
25435
|
+
}
|
|
25436
|
+
this.onmessage?.(message);
|
|
25437
|
+
} catch (error2) {
|
|
25438
|
+
this.onerror?.(error2);
|
|
25439
|
+
}
|
|
25440
|
+
}
|
|
25441
|
+
}
|
|
25442
|
+
const canResume = isReconnectable || hasPrimingEvent;
|
|
25443
|
+
const needsReconnect = canResume && !receivedResponse;
|
|
25444
|
+
if (needsReconnect && this._abortController && !this._abortController.signal.aborted) {
|
|
25445
|
+
this._scheduleReconnection({
|
|
25446
|
+
resumptionToken: lastEventId,
|
|
25447
|
+
onresumptiontoken,
|
|
25448
|
+
replayMessageId
|
|
25449
|
+
}, 0);
|
|
25450
|
+
}
|
|
25451
|
+
} catch (error2) {
|
|
25452
|
+
this.onerror?.(new Error(`SSE stream disconnected: ${error2}`));
|
|
25453
|
+
const canResume = isReconnectable || hasPrimingEvent;
|
|
25454
|
+
const needsReconnect = canResume && !receivedResponse;
|
|
25455
|
+
if (needsReconnect && this._abortController && !this._abortController.signal.aborted) {
|
|
25456
|
+
try {
|
|
25457
|
+
this._scheduleReconnection({
|
|
25458
|
+
resumptionToken: lastEventId,
|
|
25459
|
+
onresumptiontoken,
|
|
25460
|
+
replayMessageId
|
|
25461
|
+
}, 0);
|
|
25462
|
+
} catch (error3) {
|
|
25463
|
+
this.onerror?.(new Error(`Failed to reconnect: ${error3 instanceof Error ? error3.message : String(error3)}`));
|
|
25464
|
+
}
|
|
25465
|
+
}
|
|
25466
|
+
}
|
|
25467
|
+
};
|
|
25468
|
+
processStream();
|
|
25469
|
+
}
|
|
25470
|
+
async start() {
|
|
25471
|
+
if (this._abortController) {
|
|
25472
|
+
throw new Error("StreamableHTTPClientTransport already started! If using Client class, note that connect() calls start() automatically.");
|
|
25473
|
+
}
|
|
25474
|
+
this._abortController = new AbortController();
|
|
25475
|
+
}
|
|
25476
|
+
/**
|
|
25477
|
+
* Call this method after the user has finished authorizing via their user agent and is redirected back to the MCP client application. This will exchange the authorization code for an access token, enabling the next connection attempt to successfully auth.
|
|
25478
|
+
*/
|
|
25479
|
+
async finishAuth(authorizationCode) {
|
|
25480
|
+
if (!this._authProvider) {
|
|
25481
|
+
throw new UnauthorizedError("No auth provider");
|
|
25482
|
+
}
|
|
25483
|
+
const result = await auth(this._authProvider, {
|
|
25484
|
+
serverUrl: this._url,
|
|
25485
|
+
authorizationCode,
|
|
25486
|
+
resourceMetadataUrl: this._resourceMetadataUrl,
|
|
25487
|
+
scope: this._scope,
|
|
25488
|
+
fetchFn: this._fetchWithInit
|
|
25489
|
+
});
|
|
25490
|
+
if (result !== "AUTHORIZED") {
|
|
25491
|
+
throw new UnauthorizedError("Failed to authorize");
|
|
25492
|
+
}
|
|
25493
|
+
}
|
|
25494
|
+
async close() {
|
|
25495
|
+
if (this._reconnectionTimeout) {
|
|
25496
|
+
clearTimeout(this._reconnectionTimeout);
|
|
25497
|
+
this._reconnectionTimeout = void 0;
|
|
25498
|
+
}
|
|
25499
|
+
this._abortController?.abort();
|
|
25500
|
+
this.onclose?.();
|
|
25501
|
+
}
|
|
25502
|
+
async send(message, options) {
|
|
25503
|
+
try {
|
|
25504
|
+
const { resumptionToken, onresumptiontoken } = options || {};
|
|
25505
|
+
if (resumptionToken) {
|
|
25506
|
+
this._startOrAuthSse({ resumptionToken, replayMessageId: isJSONRPCRequest(message) ? message.id : void 0 }).catch((err6) => this.onerror?.(err6));
|
|
25507
|
+
return;
|
|
25508
|
+
}
|
|
25509
|
+
const headers = await this._commonHeaders();
|
|
25510
|
+
headers.set("content-type", "application/json");
|
|
25511
|
+
headers.set("accept", "application/json, text/event-stream");
|
|
25512
|
+
const init = {
|
|
25513
|
+
...this._requestInit,
|
|
25514
|
+
method: "POST",
|
|
25515
|
+
headers,
|
|
25516
|
+
body: JSON.stringify(message),
|
|
25517
|
+
signal: this._abortController?.signal
|
|
25518
|
+
};
|
|
25519
|
+
const response = await (this._fetch ?? fetch)(this._url, init);
|
|
25520
|
+
const sessionId = response.headers.get("mcp-session-id");
|
|
25521
|
+
if (sessionId) {
|
|
25522
|
+
this._sessionId = sessionId;
|
|
25523
|
+
}
|
|
25524
|
+
if (!response.ok) {
|
|
25525
|
+
const text = await response.text().catch(() => null);
|
|
25526
|
+
if (response.status === 401 && this._authProvider) {
|
|
25527
|
+
if (this._hasCompletedAuthFlow) {
|
|
25528
|
+
throw new StreamableHTTPError(401, "Server returned 401 after successful authentication");
|
|
25529
|
+
}
|
|
25530
|
+
const { resourceMetadataUrl, scope } = extractWWWAuthenticateParams(response);
|
|
25531
|
+
this._resourceMetadataUrl = resourceMetadataUrl;
|
|
25532
|
+
this._scope = scope;
|
|
25533
|
+
const result = await auth(this._authProvider, {
|
|
25534
|
+
serverUrl: this._url,
|
|
25535
|
+
resourceMetadataUrl: this._resourceMetadataUrl,
|
|
25536
|
+
scope: this._scope,
|
|
25537
|
+
fetchFn: this._fetchWithInit
|
|
25538
|
+
});
|
|
25539
|
+
if (result !== "AUTHORIZED") {
|
|
25540
|
+
throw new UnauthorizedError();
|
|
25541
|
+
}
|
|
25542
|
+
this._hasCompletedAuthFlow = true;
|
|
25543
|
+
return this.send(message);
|
|
25544
|
+
}
|
|
25545
|
+
if (response.status === 403 && this._authProvider) {
|
|
25546
|
+
const { resourceMetadataUrl, scope, error: error2 } = extractWWWAuthenticateParams(response);
|
|
25547
|
+
if (error2 === "insufficient_scope") {
|
|
25548
|
+
const wwwAuthHeader = response.headers.get("WWW-Authenticate");
|
|
25549
|
+
if (this._lastUpscopingHeader === wwwAuthHeader) {
|
|
25550
|
+
throw new StreamableHTTPError(403, "Server returned 403 after trying upscoping");
|
|
25551
|
+
}
|
|
25552
|
+
if (scope) {
|
|
25553
|
+
this._scope = scope;
|
|
25554
|
+
}
|
|
25555
|
+
if (resourceMetadataUrl) {
|
|
25556
|
+
this._resourceMetadataUrl = resourceMetadataUrl;
|
|
25557
|
+
}
|
|
25558
|
+
this._lastUpscopingHeader = wwwAuthHeader ?? void 0;
|
|
25559
|
+
const result = await auth(this._authProvider, {
|
|
25560
|
+
serverUrl: this._url,
|
|
25561
|
+
resourceMetadataUrl: this._resourceMetadataUrl,
|
|
25562
|
+
scope: this._scope,
|
|
25563
|
+
fetchFn: this._fetch
|
|
25564
|
+
});
|
|
25565
|
+
if (result !== "AUTHORIZED") {
|
|
25566
|
+
throw new UnauthorizedError();
|
|
25567
|
+
}
|
|
25568
|
+
return this.send(message);
|
|
25569
|
+
}
|
|
25570
|
+
}
|
|
25571
|
+
throw new StreamableHTTPError(response.status, `Error POSTing to endpoint: ${text}`);
|
|
25572
|
+
}
|
|
25573
|
+
this._hasCompletedAuthFlow = false;
|
|
25574
|
+
this._lastUpscopingHeader = void 0;
|
|
25575
|
+
if (response.status === 202) {
|
|
25576
|
+
await response.body?.cancel();
|
|
25577
|
+
if (isInitializedNotification(message)) {
|
|
25578
|
+
this._startOrAuthSse({ resumptionToken: void 0 }).catch((err6) => this.onerror?.(err6));
|
|
25579
|
+
}
|
|
25580
|
+
return;
|
|
25581
|
+
}
|
|
25582
|
+
const messages = Array.isArray(message) ? message : [message];
|
|
25583
|
+
const hasRequests = messages.filter((msg) => "method" in msg && "id" in msg && msg.id !== void 0).length > 0;
|
|
25584
|
+
const contentType = response.headers.get("content-type");
|
|
25585
|
+
if (hasRequests) {
|
|
25586
|
+
if (contentType?.includes("text/event-stream")) {
|
|
25587
|
+
this._handleSseStream(response.body, { onresumptiontoken }, false);
|
|
25588
|
+
} else if (contentType?.includes("application/json")) {
|
|
25589
|
+
const data = await response.json();
|
|
25590
|
+
const responseMessages = Array.isArray(data) ? data.map((msg) => JSONRPCMessageSchema.parse(msg)) : [JSONRPCMessageSchema.parse(data)];
|
|
25591
|
+
for (const msg of responseMessages) {
|
|
25592
|
+
this.onmessage?.(msg);
|
|
25593
|
+
}
|
|
25594
|
+
} else {
|
|
25595
|
+
await response.body?.cancel();
|
|
25596
|
+
throw new StreamableHTTPError(-1, `Unexpected content type: ${contentType}`);
|
|
25597
|
+
}
|
|
25598
|
+
} else {
|
|
25599
|
+
await response.body?.cancel();
|
|
25600
|
+
}
|
|
25601
|
+
} catch (error2) {
|
|
25602
|
+
this.onerror?.(error2);
|
|
25603
|
+
throw error2;
|
|
25604
|
+
}
|
|
25605
|
+
}
|
|
25606
|
+
get sessionId() {
|
|
25607
|
+
return this._sessionId;
|
|
25608
|
+
}
|
|
25609
|
+
/**
|
|
25610
|
+
* Terminates the current session by sending a DELETE request to the server.
|
|
25611
|
+
*
|
|
25612
|
+
* Clients that no longer need a particular session
|
|
25613
|
+
* (e.g., because the user is leaving the client application) SHOULD send an
|
|
25614
|
+
* HTTP DELETE to the MCP endpoint with the Mcp-Session-Id header to explicitly
|
|
25615
|
+
* terminate the session.
|
|
25616
|
+
*
|
|
25617
|
+
* The server MAY respond with HTTP 405 Method Not Allowed, indicating that
|
|
25618
|
+
* the server does not allow clients to terminate sessions.
|
|
25619
|
+
*/
|
|
25620
|
+
async terminateSession() {
|
|
25621
|
+
if (!this._sessionId) {
|
|
25622
|
+
return;
|
|
25623
|
+
}
|
|
25624
|
+
try {
|
|
25625
|
+
const headers = await this._commonHeaders();
|
|
25626
|
+
const init = {
|
|
25627
|
+
...this._requestInit,
|
|
25628
|
+
method: "DELETE",
|
|
25629
|
+
headers,
|
|
25630
|
+
signal: this._abortController?.signal
|
|
25631
|
+
};
|
|
25632
|
+
const response = await (this._fetch ?? fetch)(this._url, init);
|
|
25633
|
+
await response.body?.cancel();
|
|
25634
|
+
if (!response.ok && response.status !== 405) {
|
|
25635
|
+
throw new StreamableHTTPError(response.status, `Failed to terminate session: ${response.statusText}`);
|
|
25636
|
+
}
|
|
25637
|
+
this._sessionId = void 0;
|
|
25638
|
+
} catch (error2) {
|
|
25639
|
+
this.onerror?.(error2);
|
|
25640
|
+
throw error2;
|
|
25641
|
+
}
|
|
25642
|
+
}
|
|
25643
|
+
setProtocolVersion(version2) {
|
|
25644
|
+
this._protocolVersion = version2;
|
|
25645
|
+
}
|
|
25646
|
+
get protocolVersion() {
|
|
25647
|
+
return this._protocolVersion;
|
|
25648
|
+
}
|
|
25649
|
+
/**
|
|
25650
|
+
* Resume an SSE stream from a previous event ID.
|
|
25651
|
+
* Opens a GET SSE connection with Last-Event-ID header to replay missed events.
|
|
25652
|
+
*
|
|
25653
|
+
* @param lastEventId The event ID to resume from
|
|
25654
|
+
* @param options Optional callback to receive new resumption tokens
|
|
25655
|
+
*/
|
|
25656
|
+
async resumeStream(lastEventId, options) {
|
|
25657
|
+
await this._startOrAuthSse({
|
|
25658
|
+
resumptionToken: lastEventId,
|
|
25659
|
+
onresumptiontoken: options?.onresumptiontoken
|
|
25660
|
+
});
|
|
25661
|
+
}
|
|
25662
|
+
};
|
|
25663
|
+
|
|
25664
|
+
// ../mcp-server/src/tools/codegraph.ts
|
|
25665
|
+
var CODEGRAPH_PORT = parseInt(process.env["CODEGRAPH_PORT"] ?? "3201", 10);
|
|
25666
|
+
var clientPromise = null;
|
|
25667
|
+
function getCodegraphClient() {
|
|
25668
|
+
if (!clientPromise) {
|
|
25669
|
+
clientPromise = (async () => {
|
|
25670
|
+
const client = new Client(
|
|
25671
|
+
{ name: "bridge-mcp-codegraph-proxy", version: "0.1.0" },
|
|
25672
|
+
{ capabilities: {} }
|
|
25673
|
+
);
|
|
25674
|
+
const transport = new StreamableHTTPClientTransport(
|
|
25675
|
+
new URL(`http://127.0.0.1:${CODEGRAPH_PORT}/mcp`)
|
|
25676
|
+
);
|
|
25677
|
+
await client.connect(transport);
|
|
25678
|
+
return client;
|
|
25679
|
+
})().catch((err6) => {
|
|
25680
|
+
clientPromise = null;
|
|
25681
|
+
throw err6;
|
|
25682
|
+
});
|
|
25683
|
+
}
|
|
25684
|
+
return clientPromise;
|
|
25685
|
+
}
|
|
25686
|
+
async function resolveCwd(ctx, cwd) {
|
|
25687
|
+
if (cwd && cwd.trim()) return cwd;
|
|
25688
|
+
try {
|
|
25689
|
+
const p = await getProject(ctx);
|
|
25690
|
+
if (p.cwd) return p.cwd;
|
|
25691
|
+
} catch {
|
|
25692
|
+
}
|
|
25693
|
+
return process.cwd();
|
|
25694
|
+
}
|
|
25695
|
+
async function proxy(ctx, toolName, rawArgs) {
|
|
25696
|
+
const cwd = await resolveCwd(ctx, rawArgs["cwd"]);
|
|
25697
|
+
try {
|
|
25698
|
+
const client = await getCodegraphClient();
|
|
25699
|
+
const res = await client.callTool({
|
|
25700
|
+
name: toolName,
|
|
25701
|
+
arguments: { ...rawArgs, cwd, agentId: ctx.agentId, projectId: ctx.projectId }
|
|
25702
|
+
});
|
|
25703
|
+
return {
|
|
25704
|
+
content: res.content,
|
|
25705
|
+
isError: res.isError === true
|
|
25706
|
+
};
|
|
25707
|
+
} catch (err6) {
|
|
25708
|
+
const msg = err6 instanceof Error ? err6.message : String(err6);
|
|
25709
|
+
return {
|
|
25710
|
+
content: [{ type: "text", text: JSON.stringify({ error: `Codegraph proxy error: ${msg}` }) }],
|
|
25711
|
+
isError: true
|
|
25712
|
+
};
|
|
25713
|
+
}
|
|
25714
|
+
}
|
|
25715
|
+
function registerCodegraphTools(server, ctx) {
|
|
25716
|
+
const P = (name, args) => proxy(ctx, name, args);
|
|
25717
|
+
server.tool(
|
|
25718
|
+
"bridge_codegraph_status",
|
|
25719
|
+
"Codegraph index status + resolution coverage for a project (health/coverage probe). Prefer over reading whole files for structural questions. Returns {indexed, total, coverage:{resolved,unresolved}}.",
|
|
25720
|
+
{ cwd: external_exports.string().optional().describe("Project root. Defaults to the bridge project cwd.") },
|
|
25721
|
+
({ cwd }) => P("bridge_codegraph_status", { cwd })
|
|
25722
|
+
);
|
|
25723
|
+
server.tool(
|
|
25724
|
+
"bridge_codegraph_index",
|
|
25725
|
+
"Index (or refresh) a project for codegraph structural queries. Call before find_symbol etc. if status shows not-indexed. Prefer over broad Grep for structural discovery.",
|
|
25726
|
+
{
|
|
25727
|
+
cwd: external_exports.string().optional().describe("Project root. Defaults to the bridge project cwd."),
|
|
25728
|
+
force: external_exports.boolean().optional().describe("Re-index from scratch"),
|
|
25729
|
+
wait: external_exports.boolean().optional().describe("Wait for indexing to finish (default true)")
|
|
25730
|
+
},
|
|
25731
|
+
({ cwd, force, wait }) => P("bridge_codegraph_index", { cwd, force, wait })
|
|
25732
|
+
);
|
|
25733
|
+
server.tool(
|
|
25734
|
+
"bridge_codegraph_find_symbol",
|
|
25735
|
+
'Find a symbol by name (and optional kind) in the indexed project. PREFER over Read/Grep for "where is X defined". Limits/offset supported for pagination.',
|
|
25736
|
+
{
|
|
25737
|
+
name: external_exports.string().describe("Symbol name to find (substring match)"),
|
|
25738
|
+
kind: external_exports.string().optional().describe("Optional symbol kind filter (function, class, method, ...)"),
|
|
25739
|
+
limit: external_exports.number().optional().describe("Max results (default 50)"),
|
|
25740
|
+
offset: external_exports.number().optional().describe("Pagination offset (default 0)"),
|
|
25741
|
+
cwd: external_exports.string().optional().describe("Project root. Defaults to the bridge project cwd.")
|
|
25742
|
+
},
|
|
25743
|
+
({ name, kind, limit, offset, cwd }) => P("bridge_codegraph_find_symbol", { name, kind, limit, offset, cwd })
|
|
25744
|
+
);
|
|
25745
|
+
server.tool(
|
|
25746
|
+
"bridge_codegraph_file_outline",
|
|
25747
|
+
"Return the structural outline (symbols + signatures) of a single file. PREFER over reading the whole file when you only need its shape.",
|
|
25748
|
+
{
|
|
25749
|
+
file: external_exports.string().describe("Path to the file to outline"),
|
|
25750
|
+
cwd: external_exports.string().optional().describe("Project root. Defaults to the bridge project cwd.")
|
|
25751
|
+
},
|
|
25752
|
+
({ file, cwd }) => P("bridge_codegraph_file_outline", { file, cwd })
|
|
25753
|
+
);
|
|
25754
|
+
server.tool(
|
|
25755
|
+
"bridge_codegraph_find_references",
|
|
25756
|
+
'Find all call/reference sites of a qualified symbol ("who calls X"). PREFER over Grep for "who calls/uses X". Returns callers with file+line.',
|
|
25757
|
+
{
|
|
25758
|
+
qualifiedName: external_exports.string().describe("Qualified symbol name (e.g. PtyManager)"),
|
|
25759
|
+
limit: external_exports.number().optional().describe("Max results (default 200)"),
|
|
25760
|
+
offset: external_exports.number().optional().describe("Pagination offset (default 0)"),
|
|
25761
|
+
cwd: external_exports.string().optional().describe("Project root. Defaults to the bridge project cwd.")
|
|
25762
|
+
},
|
|
25763
|
+
({ qualifiedName, limit, offset, cwd }) => P("bridge_codegraph_find_references", { qualifiedName, limit, offset, cwd })
|
|
25764
|
+
);
|
|
25765
|
+
server.tool(
|
|
25766
|
+
"bridge_codegraph_call_graph",
|
|
25767
|
+
'Get the call graph (in/out/both) around a qualified symbol with bounded depth. PREFER over manual Grep traversal for "what does X call / who depends on X".',
|
|
25768
|
+
{
|
|
25769
|
+
qualifiedName: external_exports.string().describe("Qualified symbol name"),
|
|
25770
|
+
direction: external_exports.enum(["in", "out", "both"]).optional().describe("Edge direction (default out)"),
|
|
25771
|
+
depth: external_exports.number().min(1).max(3).optional().describe("Traversal depth 1-3 (default 2)"),
|
|
25772
|
+
cwd: external_exports.string().optional().describe("Project root. Defaults to the bridge project cwd.")
|
|
25773
|
+
},
|
|
25774
|
+
({ qualifiedName, direction, depth, cwd }) => P("bridge_codegraph_call_graph", { qualifiedName, direction, depth, cwd })
|
|
25775
|
+
);
|
|
25776
|
+
server.tool(
|
|
25777
|
+
"bridge_codegraph_get_symbol_source",
|
|
25778
|
+
"Return the source snippet of a qualified symbol. PREFER over reading the whole file when you only need one symbol's body.",
|
|
25779
|
+
{
|
|
25780
|
+
qualifiedName: external_exports.string().describe("Qualified symbol name"),
|
|
25781
|
+
cwd: external_exports.string().optional().describe("Project root. Defaults to the bridge project cwd.")
|
|
25782
|
+
},
|
|
25783
|
+
({ qualifiedName, cwd }) => P("bridge_codegraph_get_symbol_source", { qualifiedName, cwd })
|
|
25784
|
+
);
|
|
25785
|
+
server.tool(
|
|
25786
|
+
"bridge_codegraph_diff_impact",
|
|
25787
|
+
"Blast-radius of a git diff: exported symbols changed in modified files + every transitive caller (depth \u2264 3) of those symbols. PREFER over manual Grep when reviewing what a change touches. Returns {changedFiles, changedSymbols, impactedSymbols:[{qualifiedName,file,line,depth}], truncated}.",
|
|
25788
|
+
{
|
|
25789
|
+
cwd: external_exports.string().optional().describe("Project root. Defaults to the bridge project cwd."),
|
|
25790
|
+
base: external_exports.string().optional().describe("Git diff base ref (default HEAD \u2014 working tree vs HEAD)")
|
|
25791
|
+
},
|
|
25792
|
+
({ cwd, base }) => P("bridge_codegraph_diff_impact", { cwd, base })
|
|
25793
|
+
);
|
|
25794
|
+
}
|
|
25795
|
+
|
|
25796
|
+
// ../mcp-server/src/codegraph-toggle.ts
|
|
25797
|
+
var TOGGLE_TTL_MS = 1e4;
|
|
25798
|
+
var TOGGLE_TIMEOUT_MS = 5e3;
|
|
25799
|
+
var cache = /* @__PURE__ */ new Map();
|
|
25800
|
+
function envOverride() {
|
|
25801
|
+
const v = process.env["BRIDGE_CODEGRAPH"];
|
|
25802
|
+
if (v === void 0 || v.trim() === "") return null;
|
|
25803
|
+
return !(v === "0" || v.toLowerCase() === "false");
|
|
25804
|
+
}
|
|
25805
|
+
async function codegraphToolsEnabled(ctx) {
|
|
25806
|
+
const hard = envOverride();
|
|
25807
|
+
if (hard !== null) return hard;
|
|
25808
|
+
const cacheKey2 = ctx.agentId ?? "";
|
|
25809
|
+
const now = Date.now();
|
|
25810
|
+
const hit = cache.get(cacheKey2);
|
|
25811
|
+
if (hit && now < hit.expiresAt) return hit.enabled;
|
|
25812
|
+
let enabled = true;
|
|
25813
|
+
try {
|
|
25814
|
+
const base = ctx.serverUrl.replace(/\/$/, "");
|
|
25815
|
+
const params = new URLSearchParams();
|
|
25816
|
+
if (ctx.agentId) params.set("agentId", ctx.agentId);
|
|
25817
|
+
const res = await request(
|
|
25818
|
+
ctx,
|
|
25819
|
+
"GET",
|
|
25820
|
+
`${base}/api/meta/codegraph?${params.toString()}`,
|
|
25821
|
+
void 0,
|
|
25822
|
+
{ timeoutMs: TOGGLE_TIMEOUT_MS }
|
|
25823
|
+
);
|
|
25824
|
+
if (res.arm === "on" || res.arm === "off") enabled = res.arm === "on";
|
|
25825
|
+
else if (typeof res.enabled === "boolean") enabled = res.enabled;
|
|
25826
|
+
} catch (err6) {
|
|
25827
|
+
console.warn("[codegraph-toggle] arm fetch failed, failing OPEN (tools ON):", err6 instanceof Error ? err6.message : err6);
|
|
25828
|
+
}
|
|
25829
|
+
cache.set(cacheKey2, { enabled, expiresAt: now + TOGGLE_TTL_MS });
|
|
25830
|
+
return enabled;
|
|
25831
|
+
}
|
|
25832
|
+
|
|
25833
|
+
// ../mcp-server/src/index.ts
|
|
25834
|
+
var sessions = /* @__PURE__ */ new Map();
|
|
25835
|
+
async function buildMcpServer(ctx) {
|
|
25836
|
+
const srv = new McpServer({ name: "bridge", version: "0.1.0" });
|
|
25837
|
+
registerPlanTools(srv, ctx);
|
|
25838
|
+
registerTodoTools(srv, ctx);
|
|
25839
|
+
registerOrchestrationTools(srv, ctx);
|
|
25840
|
+
registerMessagingTools(srv, ctx);
|
|
25841
|
+
registerWorkspaceTools(srv, ctx);
|
|
25842
|
+
registerPersonaTools(srv, ctx);
|
|
25843
|
+
registerRolePromptTools(srv, ctx);
|
|
25844
|
+
registerGroupSchemaTools(srv, ctx);
|
|
25845
|
+
if (await codegraphToolsEnabled(ctx)) {
|
|
25846
|
+
registerCodegraphTools(srv, ctx);
|
|
25847
|
+
}
|
|
23202
25848
|
return srv;
|
|
23203
25849
|
}
|
|
23204
25850
|
async function parseBody(req) {
|
|
@@ -23226,15 +25872,15 @@ function startHttpServer() {
|
|
|
23226
25872
|
}
|
|
23227
25873
|
const port = parseInt(process.env["PORT"] ?? "3200", 10);
|
|
23228
25874
|
const httpServer = (0, import_node_http.createServer)(async (req, res) => {
|
|
23229
|
-
const
|
|
25875
|
+
const url2 = req.url ?? "/";
|
|
23230
25876
|
const method = req.method ?? "GET";
|
|
23231
25877
|
try {
|
|
23232
|
-
if (method === "GET" && (
|
|
25878
|
+
if (method === "GET" && (url2 === "/health" || url2 === "/health/")) {
|
|
23233
25879
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
23234
25880
|
res.end(JSON.stringify({ ok: true, sessions: sessions.size }));
|
|
23235
25881
|
return;
|
|
23236
25882
|
}
|
|
23237
|
-
const match =
|
|
25883
|
+
const match = url2.match(/^\/mcp\/([^/?#]+)\/([^/?#]+)/);
|
|
23238
25884
|
if (!match || !["GET", "POST", "DELETE"].includes(method)) {
|
|
23239
25885
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
23240
25886
|
res.end(JSON.stringify({ error: "Not found" }));
|
|
@@ -23242,8 +25888,8 @@ function startHttpServer() {
|
|
|
23242
25888
|
}
|
|
23243
25889
|
const workspaceId = match[1];
|
|
23244
25890
|
const projectId = match[2];
|
|
23245
|
-
const
|
|
23246
|
-
const token =
|
|
25891
|
+
const auth2 = req.headers["authorization"] ?? "";
|
|
25892
|
+
const token = auth2.startsWith("Bearer ") ? auth2.slice(7).trim() : "";
|
|
23247
25893
|
if (!token) {
|
|
23248
25894
|
res.writeHead(401, { "Content-Type": "application/json" });
|
|
23249
25895
|
res.end(JSON.stringify({ error: "Authorization: Bearer <token> required" }));
|
|
@@ -23300,11 +25946,11 @@ function startHttpServer() {
|
|
|
23300
25946
|
sessions.delete(id);
|
|
23301
25947
|
}
|
|
23302
25948
|
});
|
|
23303
|
-
const mcpServer = buildMcpServer(ctx);
|
|
25949
|
+
const mcpServer = await buildMcpServer(ctx);
|
|
23304
25950
|
await mcpServer.connect(transport);
|
|
23305
25951
|
await transport.handleRequest(req, res, body);
|
|
23306
|
-
} catch (
|
|
23307
|
-
console.error("[bridge-mcp] request error:",
|
|
25952
|
+
} catch (err6) {
|
|
25953
|
+
console.error("[bridge-mcp] request error:", err6);
|
|
23308
25954
|
if (!res.headersSent) {
|
|
23309
25955
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
23310
25956
|
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
@@ -23331,7 +25977,7 @@ async function startStdioServer() {
|
|
|
23331
25977
|
agentId: process.env["BRIDGE_PANEL_ID"] || void 0,
|
|
23332
25978
|
personaId: process.env["BRIDGE_PERSONA_ID"] || void 0
|
|
23333
25979
|
};
|
|
23334
|
-
const srv = buildMcpServer(ctx);
|
|
25980
|
+
const srv = await buildMcpServer(ctx);
|
|
23335
25981
|
const transport = new StdioServerTransport();
|
|
23336
25982
|
await srv.connect(transport);
|
|
23337
25983
|
console.error("[bridge-mcp] connected via stdio");
|
|
@@ -23339,8 +25985,8 @@ async function startStdioServer() {
|
|
|
23339
25985
|
if (process.env["HTTP_MODE"] !== "false") {
|
|
23340
25986
|
startHttpServer();
|
|
23341
25987
|
} else {
|
|
23342
|
-
startStdioServer().catch((
|
|
23343
|
-
console.error("[bridge-mcp] fatal:",
|
|
25988
|
+
startStdioServer().catch((err6) => {
|
|
25989
|
+
console.error("[bridge-mcp] fatal:", err6);
|
|
23344
25990
|
process.exit(1);
|
|
23345
25991
|
});
|
|
23346
25992
|
}
|