infinitecampus-mcp 2.7.0 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bundle.js CHANGED
@@ -3116,9 +3116,28 @@ var require_utils = __commonJS({
3116
3116
  "use strict";
3117
3117
  var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
3118
3118
  var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
3119
+ var isPort = RegExp.prototype.test.bind(/^\d*$/u);
3119
3120
  var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
3120
3121
  var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
3121
- var isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu);
3122
+ var isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
3123
+ var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
3124
+ var isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
3125
+ var BYTE_HEX = new Array(256);
3126
+ {
3127
+ const HEX_DIGITS = "0123456789ABCDEF";
3128
+ for (let i = 0; i < 256; i++) {
3129
+ BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
3130
+ }
3131
+ }
3132
+ function percentEncodeNonAscii(cp) {
3133
+ if (cp < 2048) {
3134
+ return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
3135
+ }
3136
+ if (cp < 65536) {
3137
+ return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
3138
+ }
3139
+ return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
3140
+ }
3122
3141
  function stringArrayToHexStripped(input) {
3123
3142
  let acc = "";
3124
3143
  let code = 0;
@@ -3143,91 +3162,105 @@ var require_utils = __commonJS({
3143
3162
  }
3144
3163
  return acc;
3145
3164
  }
3165
+ var isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
3166
+ var isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
3167
+ var isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
3146
3168
  var nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
3147
- function consumeIsZone(buffer) {
3148
- buffer.length = 0;
3149
- return true;
3150
- }
3151
- function consumeHextets(buffer, address, output) {
3152
- if (buffer.length) {
3153
- const hex3 = stringArrayToHexStripped(buffer);
3154
- if (hex3 !== "") {
3155
- address.push(hex3);
3156
- } else {
3157
- output.error = true;
3158
- return false;
3169
+ function isZoneIdentifier(zone) {
3170
+ if (zone.length === 0) return false;
3171
+ for (let i = 0; i < zone.length; i++) {
3172
+ if (isZoneCharacter(zone[i])) continue;
3173
+ if (zone[i] === "%" && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
3174
+ i += 2;
3175
+ continue;
3159
3176
  }
3160
- buffer.length = 0;
3177
+ return false;
3161
3178
  }
3162
3179
  return true;
3163
3180
  }
3164
- function getIPV6(input) {
3165
- let tokenCount = 0;
3166
- const output = { error: false, address: "", zone: "" };
3167
- const address = [];
3168
- const buffer = [];
3169
- let endipv6Encountered = false;
3170
- let endIpv6 = false;
3171
- let consume = consumeHextets;
3172
- for (let i = 0; i < input.length; i++) {
3173
- const cursor = input[i];
3174
- if (cursor === "[" || cursor === "]") {
3175
- continue;
3176
- }
3177
- if (cursor === ":") {
3178
- if (endipv6Encountered === true) {
3179
- endIpv6 = true;
3180
- }
3181
- if (!consume(buffer, address, output)) {
3182
- break;
3183
- }
3184
- if (++tokenCount > 7) {
3185
- output.error = true;
3186
- break;
3187
- }
3188
- if (i > 0 && input[i - 1] === ":") {
3189
- endipv6Encountered = true;
3190
- }
3191
- address.push(":");
3192
- continue;
3193
- } else if (cursor === "%") {
3194
- if (!consume(buffer, address, output)) {
3195
- break;
3181
+ function compressIPv6ZeroRun(hextets) {
3182
+ let bestStart = -1;
3183
+ let bestLength = 0;
3184
+ let runStart = -1;
3185
+ let runLength = 0;
3186
+ for (let i = 0; i < hextets.length; i++) {
3187
+ if (hextets[i] === "0") {
3188
+ if (runStart === -1) runStart = i;
3189
+ runLength++;
3190
+ if (runLength > bestLength) {
3191
+ bestLength = runLength;
3192
+ bestStart = runStart;
3196
3193
  }
3197
- consume = consumeIsZone;
3198
3194
  } else {
3199
- buffer.push(cursor);
3195
+ runStart = -1;
3196
+ runLength = 0;
3197
+ }
3198
+ }
3199
+ if (bestLength < 2) return hextets.join(":");
3200
+ const head = hextets.slice(0, bestStart).join(":");
3201
+ const tail = hextets.slice(bestStart + bestLength).join(":");
3202
+ return head + "::" + tail;
3203
+ }
3204
+ function normalizeIPv6Address(input) {
3205
+ const compression = input.indexOf("::");
3206
+ if (compression !== -1 && input.indexOf("::", compression + 1) !== -1) return void 0;
3207
+ const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
3208
+ const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
3209
+ if (compression !== -1) {
3210
+ if (left.length === 1 && left[0] === "") left.length = 0;
3211
+ if (right.length === 1 && right[0] === "") right.length = 0;
3212
+ }
3213
+ const parts = left.concat(right);
3214
+ let hextetCount = 0;
3215
+ for (let i = 0; i < parts.length; i++) {
3216
+ const part = parts[i];
3217
+ if (part === "") return void 0;
3218
+ if (part.indexOf(".") !== -1) {
3219
+ if (i !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part)) return void 0;
3220
+ hextetCount += 2;
3200
3221
  continue;
3201
3222
  }
3223
+ if (!isHextet(part)) return void 0;
3224
+ parts[i] = parseInt(part, 16).toString(16);
3225
+ hextetCount++;
3202
3226
  }
3203
- if (buffer.length) {
3204
- if (consume === consumeIsZone) {
3205
- output.zone = buffer.join("");
3206
- } else if (endIpv6) {
3207
- address.push(buffer.join(""));
3208
- } else {
3209
- address.push(stringArrayToHexStripped(buffer));
3210
- }
3227
+ if (compression === -1) {
3228
+ if (hextetCount !== 8) return void 0;
3229
+ return compressIPv6ZeroRun(parts);
3211
3230
  }
3212
- output.address = address.join("");
3213
- return output;
3231
+ if (hextetCount >= 8) return void 0;
3232
+ const expanded = parts.slice(0, left.length);
3233
+ for (let i = hextetCount; i < 8; i++) expanded.push("0");
3234
+ for (let i = left.length; i < parts.length; i++) expanded.push(parts[i]);
3235
+ return compressIPv6ZeroRun(expanded);
3214
3236
  }
3215
3237
  function normalizeIPv6(host) {
3216
- if (findToken(host, ":") < 2) {
3217
- return { host, isIPV6: false };
3218
- }
3219
- const ipv63 = getIPV6(host);
3220
- if (!ipv63.error) {
3221
- let newHost = ipv63.address;
3222
- let escapedHost = ipv63.address;
3223
- if (ipv63.zone) {
3224
- newHost += "%" + ipv63.zone;
3225
- escapedHost += "%25" + ipv63.zone;
3226
- }
3227
- return { host: newHost, isIPV6: true, escapedHost };
3228
- } else {
3229
- return { host, isIPV6: false };
3230
- }
3238
+ const bracketed = host[0] === "[" && host[host.length - 1] === "]";
3239
+ const hasBracket = host[0] === "[" || host[host.length - 1] === "]";
3240
+ if (hasBracket && !bracketed) return { host, isIPV6: false, error: true };
3241
+ let input = bracketed ? host.slice(1, -1) : host;
3242
+ if (bracketed && isIPvFuture(input)) {
3243
+ input = input.toLowerCase();
3244
+ return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true };
3245
+ }
3246
+ if (findToken(input, ":") < 2) {
3247
+ return { host, isIPV6: false, error: bracketed };
3248
+ }
3249
+ let zoneIdentifier = "";
3250
+ const zoneSeparator = input.indexOf("%");
3251
+ if (zoneSeparator !== -1) {
3252
+ const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
3253
+ zoneIdentifier = input.slice(zoneSeparator + separatorLength);
3254
+ if (!isZoneIdentifier(zoneIdentifier)) return { host, isIPV6: false, error: true };
3255
+ input = input.slice(0, zoneSeparator);
3256
+ }
3257
+ const address = normalizeIPv6Address(input);
3258
+ if (address === void 0) return { host, isIPV6: false, error: true };
3259
+ return {
3260
+ host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
3261
+ escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
3262
+ isIPV6: true
3263
+ };
3231
3264
  }
3232
3265
  function findToken(str, token) {
3233
3266
  let ind = 0;
@@ -3346,7 +3379,8 @@ var require_utils = __commonJS({
3346
3379
  function normalizePathEncoding(input) {
3347
3380
  let output = "";
3348
3381
  for (let i = 0; i < input.length; i++) {
3349
- if (input[i] === "%" && i + 2 < input.length) {
3382
+ const ch = input[i];
3383
+ if (ch === "%" && i + 2 < input.length) {
3350
3384
  const hex3 = input.slice(i + 1, i + 3);
3351
3385
  if (isHexPair(hex3)) {
3352
3386
  const normalizedHex = hex3.toUpperCase();
@@ -3360,10 +3394,152 @@ var require_utils = __commonJS({
3360
3394
  continue;
3361
3395
  }
3362
3396
  }
3363
- if (isPathCharacter(input[i])) {
3364
- output += input[i];
3397
+ if (isPathCharacter(ch)) {
3398
+ output += ch;
3399
+ } else {
3400
+ const code = input.charCodeAt(i);
3401
+ if (code < 128) {
3402
+ output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
3403
+ } else if (code < 55296 || code > 57343) {
3404
+ output += percentEncodeNonAscii(code);
3405
+ } else if (code <= 56319 && i + 1 < input.length) {
3406
+ const low = input.charCodeAt(i + 1);
3407
+ if (low >= 56320 && low <= 57343) {
3408
+ output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
3409
+ i++;
3410
+ } else {
3411
+ output += percentEncodeNonAscii(65533);
3412
+ }
3413
+ } else {
3414
+ output += percentEncodeNonAscii(65533);
3415
+ }
3416
+ }
3417
+ }
3418
+ return output;
3419
+ }
3420
+ function serializePathEncoding(input, pathNoScheme = false) {
3421
+ let output = "";
3422
+ let firstSegment = pathNoScheme && input[0] !== "/";
3423
+ for (let i = 0; i < input.length; i++) {
3424
+ const ch = input[i];
3425
+ if (ch === "%" && i + 2 < input.length) {
3426
+ const hex3 = input.slice(i + 1, i + 3);
3427
+ if (isHexPair(hex3)) {
3428
+ output += "%" + hex3.toUpperCase();
3429
+ i += 2;
3430
+ continue;
3431
+ }
3432
+ }
3433
+ if (ch === "/") {
3434
+ firstSegment = false;
3435
+ }
3436
+ if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) {
3437
+ output += ch;
3438
+ } else {
3439
+ const code = input.charCodeAt(i);
3440
+ if (code < 128) {
3441
+ output += BYTE_HEX[code];
3442
+ } else if (code < 55296 || code > 57343) {
3443
+ output += percentEncodeNonAscii(code);
3444
+ } else if (code <= 56319 && i + 1 < input.length) {
3445
+ const low = input.charCodeAt(i + 1);
3446
+ if (low >= 56320 && low <= 57343) {
3447
+ output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
3448
+ i++;
3449
+ } else {
3450
+ output += percentEncodeNonAscii(65533);
3451
+ }
3452
+ } else {
3453
+ output += percentEncodeNonAscii(65533);
3454
+ }
3455
+ }
3456
+ }
3457
+ return output;
3458
+ }
3459
+ function encodeComponent(input, isAllowed) {
3460
+ let output = "";
3461
+ for (let i = 0; i < input.length; i++) {
3462
+ const ch = input[i];
3463
+ if (ch === "%" && i + 2 < input.length) {
3464
+ const hex3 = input.slice(i + 1, i + 3);
3465
+ if (isHexPair(hex3)) {
3466
+ output += "%" + hex3.toUpperCase();
3467
+ i += 2;
3468
+ continue;
3469
+ }
3470
+ }
3471
+ if (isAllowed(ch)) {
3472
+ output += ch;
3473
+ } else {
3474
+ const code = input.charCodeAt(i);
3475
+ if (code < 128) {
3476
+ output += BYTE_HEX[code];
3477
+ } else if (code < 55296 || code > 57343) {
3478
+ output += percentEncodeNonAscii(code);
3479
+ } else if (code <= 56319 && i + 1 < input.length) {
3480
+ const low = input.charCodeAt(i + 1);
3481
+ if (low >= 56320 && low <= 57343) {
3482
+ output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
3483
+ i++;
3484
+ } else {
3485
+ output += percentEncodeNonAscii(65533);
3486
+ }
3487
+ } else {
3488
+ output += percentEncodeNonAscii(65533);
3489
+ }
3490
+ }
3491
+ }
3492
+ return output;
3493
+ }
3494
+ function encodeUserinfo(input) {
3495
+ return encodeComponent(input, isUserinfoCharacter);
3496
+ }
3497
+ function encodeQuery(input) {
3498
+ return encodeComponent(input, isQueryFragmentCharacter);
3499
+ }
3500
+ function encodeFragment(input) {
3501
+ return encodeComponent(input, isQueryFragmentCharacter);
3502
+ }
3503
+ function isEscapeSafe(cp) {
3504
+ return cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp === 42 || cp === 43 || cp === 45 || cp === 46 || cp === 47 || cp === 64 || cp === 95;
3505
+ }
3506
+ function normalizeQueryFragmentEncoding(input) {
3507
+ let output = "";
3508
+ for (let i = 0; i < input.length; i++) {
3509
+ const ch = input[i];
3510
+ if (ch === "%" && i + 2 < input.length) {
3511
+ const hex3 = input.slice(i + 1, i + 3);
3512
+ if (isHexPair(hex3)) {
3513
+ const normalizedHex = hex3.toUpperCase();
3514
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
3515
+ if (isUnreserved(decoded)) {
3516
+ output += decoded;
3517
+ } else {
3518
+ output += "%" + normalizedHex;
3519
+ }
3520
+ i += 2;
3521
+ continue;
3522
+ }
3523
+ }
3524
+ if (isQueryFragmentCharacter(ch)) {
3525
+ output += ch;
3365
3526
  } else {
3366
- output += escape(input[i]);
3527
+ const code = input.charCodeAt(i);
3528
+ if (code < 128) {
3529
+ output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
3530
+ } else if (code < 55296 || code > 57343) {
3531
+ output += percentEncodeNonAscii(code);
3532
+ } else if (code <= 56319 && i + 1 < input.length) {
3533
+ const low = input.charCodeAt(i + 1);
3534
+ if (low >= 56320 && low <= 57343) {
3535
+ output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
3536
+ i++;
3537
+ } else {
3538
+ output += percentEncodeNonAscii(65533);
3539
+ }
3540
+ } else {
3541
+ output += percentEncodeNonAscii(65533);
3542
+ }
3367
3543
  }
3368
3544
  }
3369
3545
  return output;
@@ -3386,14 +3562,18 @@ var require_utils = __commonJS({
3386
3562
  function recomposeAuthority(component) {
3387
3563
  const uriTokens = [];
3388
3564
  if (component.userinfo !== void 0) {
3389
- uriTokens.push(component.userinfo);
3565
+ uriTokens.push(encodeUserinfo(component.userinfo));
3390
3566
  uriTokens.push("@");
3391
3567
  }
3392
3568
  if (component.host !== void 0) {
3393
- let host = unescape(component.host);
3569
+ let host = component.host;
3394
3570
  if (!isIPv4(host)) {
3395
- const ipV6res = normalizeIPv6(host);
3396
- if (ipV6res.isIPV6 === true) {
3571
+ let ipV6res = normalizeIPv6(host);
3572
+ if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
3573
+ host = normalizePercentEncoding(host, true);
3574
+ ipV6res = normalizeIPv6(host);
3575
+ }
3576
+ if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
3397
3577
  host = `[${ipV6res.escapedHost}]`;
3398
3578
  } else {
3399
3579
  host = reescapeHostDelimiters(host, false);
@@ -3402,8 +3582,12 @@ var require_utils = __commonJS({
3402
3582
  uriTokens.push(host);
3403
3583
  }
3404
3584
  if (typeof component.port === "number" || typeof component.port === "string") {
3585
+ const port = String(component.port);
3586
+ if (!isPort(port)) {
3587
+ throw new TypeError("URI port is malformed.");
3588
+ }
3405
3589
  uriTokens.push(":");
3406
- uriTokens.push(String(component.port));
3590
+ uriTokens.push(port);
3407
3591
  }
3408
3592
  return uriTokens.length ? uriTokens.join("") : void 0;
3409
3593
  }
@@ -3413,6 +3597,11 @@ var require_utils = __commonJS({
3413
3597
  reescapeHostDelimiters,
3414
3598
  normalizePercentEncoding,
3415
3599
  normalizePathEncoding,
3600
+ serializePathEncoding,
3601
+ normalizeQueryFragmentEncoding,
3602
+ encodeUserinfo,
3603
+ encodeQuery,
3604
+ encodeFragment,
3416
3605
  escapePreservingEscapes,
3417
3606
  removeDotSegments,
3418
3607
  isIPv4,
@@ -3428,7 +3617,7 @@ var require_schemes = __commonJS({
3428
3617
  "node_modules/fast-uri/lib/schemes.js"(exports, module) {
3429
3618
  "use strict";
3430
3619
  var { isUUID } = require_utils();
3431
- var URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu;
3620
+ var URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
3432
3621
  var supportedSchemeNames = (
3433
3622
  /** @type {const} */
3434
3623
  [
@@ -3489,9 +3678,10 @@ var require_schemes = __commonJS({
3489
3678
  wsComponent.secure = void 0;
3490
3679
  }
3491
3680
  if (wsComponent.resourceName) {
3492
- const [path, query] = wsComponent.resourceName.split("?");
3681
+ const queryIndex = wsComponent.resourceName.indexOf("?");
3682
+ const path = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
3493
3683
  wsComponent.path = path && path !== "/" ? path : void 0;
3494
- wsComponent.query = query;
3684
+ wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
3495
3685
  wsComponent.resourceName = void 0;
3496
3686
  }
3497
3687
  wsComponent.fragment = void 0;
@@ -3503,7 +3693,7 @@ var require_schemes = __commonJS({
3503
3693
  return urnComponent;
3504
3694
  }
3505
3695
  const matches = urnComponent.path.match(URN_REG);
3506
- if (matches) {
3696
+ if (matches && matches[0] === urnComponent.path) {
3507
3697
  const scheme = options.scheme || urnComponent.scheme || "urn";
3508
3698
  urnComponent.nid = matches[1].toLowerCase();
3509
3699
  urnComponent.nss = matches[2];
@@ -3637,8 +3827,17 @@ var require_schemes = __commonJS({
3637
3827
  var require_fast_uri = __commonJS({
3638
3828
  "node_modules/fast-uri/index.js"(exports, module) {
3639
3829
  "use strict";
3640
- var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
3830
+ var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
3641
3831
  var { SCHEMES, getSchemeHandler } = require_schemes();
3832
+ var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
3833
+ var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
3834
+ function decodeValidScheme(scheme) {
3835
+ const decodedScheme = unescape(String(scheme));
3836
+ if (!VALID_SCHEME.test(decodedScheme)) {
3837
+ throw new TypeError(MALFORMED_SCHEME_ERROR);
3838
+ }
3839
+ return decodedScheme;
3840
+ }
3642
3841
  function normalize(uri, options) {
3643
3842
  if (typeof uri === "string") {
3644
3843
  uri = /** @type {T} */
@@ -3651,12 +3850,34 @@ var require_fast_uri = __commonJS({
3651
3850
  }
3652
3851
  function resolve2(baseURI, relativeURI, options) {
3653
3852
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3654
- const { parsed: baseParsed, malformedAuthorityOrPort: baseMalformed } = parseWithStatus(baseURI, schemelessOptions);
3655
- const { parsed: relativeParsed, malformedAuthorityOrPort: relativeMalformed } = parseWithStatus(relativeURI, schemelessOptions);
3656
- if (baseMalformed || relativeMalformed) {
3853
+ const {
3854
+ parsed: baseParsed,
3855
+ malformedAuthorityOrPort: baseMalformed,
3856
+ malformedPercentEncoding: baseMalformedPercentEncoding,
3857
+ malformedSchemeSpecific: baseMalformedSchemeSpecific,
3858
+ malformedHost: baseMalformedHost,
3859
+ malformedScheme: baseMalformedScheme
3860
+ } = parseWithStatus(baseURI, schemelessOptions);
3861
+ const {
3862
+ parsed: relativeParsed,
3863
+ malformedAuthorityOrPort: relativeMalformed,
3864
+ malformedPercentEncoding: relativeMalformedPercentEncoding,
3865
+ malformedSchemeSpecific: relativeMalformedSchemeSpecific,
3866
+ malformedHost: relativeMalformedHost,
3867
+ malformedScheme: relativeMalformedScheme
3868
+ } = parseWithStatus(relativeURI, schemelessOptions);
3869
+ if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
3657
3870
  throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
3658
3871
  }
3659
3872
  const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
3873
+ const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
3874
+ const resolvedHost = resolved.host;
3875
+ const resolvedHostIsIP = resolvedHost !== void 0 && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
3876
+ canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
3877
+ const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !/\P{ASCII}/u.test(resolvedHost);
3878
+ if (resolved.error && !encodedASCIIHost) {
3879
+ throw new Error(resolved.error);
3880
+ }
3660
3881
  schemelessOptions.skipEscape = true;
3661
3882
  return serialize(resolved, schemelessOptions);
3662
3883
  }
@@ -3716,7 +3937,7 @@ var require_fast_uri = __commonJS({
3716
3937
  function equal(uriA, uriB, options) {
3717
3938
  const normalizedA = normalizeComparableURI(uriA, options);
3718
3939
  const normalizedB = normalizeComparableURI(uriB, options);
3719
- return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA.toLowerCase() === normalizedB.toLowerCase();
3940
+ return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA === normalizedB;
3720
3941
  }
3721
3942
  function serialize(cmpts, opts) {
3722
3943
  const component = {
@@ -3737,19 +3958,22 @@ var require_fast_uri = __commonJS({
3737
3958
  };
3738
3959
  const options = Object.assign({}, opts);
3739
3960
  const uriTokens = [];
3961
+ if (component.scheme) {
3962
+ component.scheme = decodeValidScheme(component.scheme);
3963
+ }
3740
3964
  const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
3741
3965
  if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
3966
+ const hasAuthority = component.userinfo !== void 0 || component.host !== void 0 || component.port !== void 0;
3967
+ const pathNoScheme = !options.skipEscape && component.scheme === void 0 && !hasAuthority;
3742
3968
  if (component.path !== void 0) {
3743
3969
  if (!options.skipEscape) {
3744
- component.path = escapePreservingEscapes(component.path);
3745
- if (component.scheme !== void 0) {
3746
- component.path = component.path.split("%3A").join(":");
3747
- }
3970
+ component.path = serializePathEncoding(component.path, pathNoScheme);
3748
3971
  } else {
3749
3972
  component.path = normalizePercentEncoding(component.path);
3750
3973
  }
3751
3974
  }
3752
3975
  if (options.reference !== "suffix" && component.scheme) {
3976
+ component.scheme = decodeValidScheme(component.scheme);
3753
3977
  uriTokens.push(component.scheme, ":");
3754
3978
  }
3755
3979
  const authority = recomposeAuthority(component);
@@ -3767,16 +3991,19 @@ var require_fast_uri = __commonJS({
3767
3991
  if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
3768
3992
  s = removeDotSegments(s);
3769
3993
  }
3994
+ if (pathNoScheme) {
3995
+ s = serializePathEncoding(s, true);
3996
+ }
3770
3997
  if (authority === void 0 && s[0] === "/" && s[1] === "/") {
3771
3998
  s = "/%2F" + s.slice(2);
3772
3999
  }
3773
4000
  uriTokens.push(s);
3774
4001
  }
3775
4002
  if (component.query !== void 0) {
3776
- uriTokens.push("?", component.query);
4003
+ uriTokens.push("?", encodeQuery(component.query));
3777
4004
  }
3778
4005
  if (component.fragment !== void 0) {
3779
- uriTokens.push("#", component.fragment);
4006
+ uriTokens.push("#", encodeFragment(component.fragment));
3780
4007
  }
3781
4008
  return uriTokens.join("");
3782
4009
  }
@@ -3792,6 +4019,35 @@ var require_fast_uri = __commonJS({
3792
4019
  }
3793
4020
  return void 0;
3794
4021
  }
4022
+ function hasMalformedPercentEncoding(component) {
4023
+ if (component === void 0) return false;
4024
+ let percent = component.indexOf("%");
4025
+ while (percent !== -1) {
4026
+ if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) {
4027
+ return true;
4028
+ }
4029
+ percent = component.indexOf("%", percent + 3);
4030
+ }
4031
+ return false;
4032
+ }
4033
+ function isIPLiteral(host) {
4034
+ return host[0] === "[" && host[host.length - 1] === "]";
4035
+ }
4036
+ function hasMalformedComponentPercentEncoding(matches) {
4037
+ const host = matches[4];
4038
+ return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
4039
+ }
4040
+ function canonicalizeHost(parsed, options, schemeHandler, isIP2) {
4041
+ if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP2 === false && nonSimpleDomain(parsed.host)) {
4042
+ try {
4043
+ parsed.host = new URL("http://" + parsed.host).hostname;
4044
+ } catch (e) {
4045
+ parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
4046
+ return true;
4047
+ }
4048
+ }
4049
+ return false;
4050
+ }
3795
4051
  function parseWithStatus(uri, opts) {
3796
4052
  const options = Object.assign({}, opts);
3797
4053
  const parsed = {
@@ -3804,6 +4060,11 @@ var require_fast_uri = __commonJS({
3804
4060
  fragment: void 0
3805
4061
  };
3806
4062
  let malformedAuthorityOrPort = false;
4063
+ let malformedPercentEncoding = false;
4064
+ let malformedSchemeSpecific = false;
4065
+ let malformedHost = false;
4066
+ let malformedIPLiteral = false;
4067
+ let malformedScheme = false;
3807
4068
  let isIP2 = false;
3808
4069
  if (options.reference === "suffix") {
3809
4070
  if (options.scheme) {
@@ -3840,6 +4101,19 @@ var require_fast_uri = __commonJS({
3840
4101
  parsed.path = matches[6] || "";
3841
4102
  parsed.query = matches[7];
3842
4103
  parsed.fragment = matches[8];
4104
+ if (parsed.scheme !== void 0) {
4105
+ const decodedScheme = unescape(parsed.scheme);
4106
+ if (VALID_SCHEME.test(decodedScheme)) {
4107
+ parsed.scheme = decodedScheme.toLowerCase();
4108
+ } else {
4109
+ parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
4110
+ malformedScheme = true;
4111
+ }
4112
+ }
4113
+ malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
4114
+ if (malformedPercentEncoding) {
4115
+ parsed.error = parsed.error || "URI contains malformed percent-encoding.";
4116
+ }
3843
4117
  if (isNaN(parsed.port)) {
3844
4118
  parsed.port = matches[5];
3845
4119
  }
@@ -3851,9 +4125,16 @@ var require_fast_uri = __commonJS({
3851
4125
  if (parsed.host) {
3852
4126
  const ipv4result = isIPv4(parsed.host);
3853
4127
  if (ipv4result === false) {
4128
+ const bracketedIPLiteral = isIPLiteral(parsed.host);
4129
+ const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
3854
4130
  const ipv6result = normalizeIPv6(parsed.host);
3855
- parsed.host = ipv6result.host.toLowerCase();
3856
- isIP2 = ipv6result.isIPV6;
4131
+ isIP2 = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
4132
+ malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
4133
+ parsed.host = isIP2 ? ipv6result.host : ipv6result.host.toLowerCase();
4134
+ if (malformedIPLiteral) {
4135
+ parsed.error = parsed.error || "URI host is malformed.";
4136
+ malformedAuthorityOrPort = true;
4137
+ }
3857
4138
  } else {
3858
4139
  isIP2 = true;
3859
4140
  }
@@ -3871,42 +4152,36 @@ var require_fast_uri = __commonJS({
3871
4152
  parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
3872
4153
  }
3873
4154
  const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
3874
- if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
3875
- if (parsed.host && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP2 === false && nonSimpleDomain(parsed.host)) {
3876
- try {
3877
- parsed.host = new URL("http://" + parsed.host).hostname;
3878
- } catch (e) {
3879
- parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
3880
- }
3881
- }
4155
+ if (!malformedIPLiteral) {
4156
+ malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP2);
3882
4157
  }
3883
4158
  if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
3884
4159
  if (uri.indexOf("%") !== -1) {
3885
- if (parsed.scheme !== void 0) {
3886
- parsed.scheme = unescape(parsed.scheme);
3887
- }
3888
- if (parsed.host !== void 0) {
3889
- parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP2);
4160
+ if (parsed.host !== void 0 && !malformedIPLiteral) {
4161
+ const host = isIP2 ? parsed.host : normalizePercentEncoding(parsed.host, true);
4162
+ parsed.host = reescapeHostDelimiters(host, isIP2);
3890
4163
  }
3891
4164
  }
3892
4165
  if (parsed.path) {
3893
4166
  parsed.path = normalizePathEncoding(parsed.path);
3894
4167
  }
4168
+ if (parsed.query) {
4169
+ parsed.query = normalizeQueryFragmentEncoding(parsed.query);
4170
+ }
3895
4171
  if (parsed.fragment) {
3896
- try {
3897
- parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
3898
- } catch {
3899
- parsed.error = parsed.error || "URI malformed";
3900
- }
4172
+ parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
3901
4173
  }
3902
4174
  }
3903
4175
  if (schemeHandler && schemeHandler.parse) {
3904
4176
  schemeHandler.parse(parsed, options);
4177
+ if (schemeHandler === SCHEMES.urn && parsed.nid === void 0) {
4178
+ malformedSchemeSpecific = true;
4179
+ }
3905
4180
  }
3906
4181
  } else {
3907
4182
  parsed.error = parsed.error || "URI can not be parsed.";
3908
4183
  }
3909
- return { parsed, malformedAuthorityOrPort };
4184
+ return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
3910
4185
  }
3911
4186
  function parse3(uri, opts) {
3912
4187
  return parseWithStatus(uri, opts).parsed;
@@ -3915,20 +4190,28 @@ var require_fast_uri = __commonJS({
3915
4190
  return normalizeStringWithStatus(uri, opts).normalized;
3916
4191
  }
3917
4192
  function normalizeStringWithStatus(uri, opts) {
3918
- const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
4193
+ const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
3919
4194
  return {
3920
- normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
3921
- malformedAuthorityOrPort
4195
+ normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
4196
+ malformedAuthorityOrPort,
4197
+ malformedPercentEncoding,
4198
+ malformedSchemeSpecific,
4199
+ malformedHost,
4200
+ malformedScheme
3922
4201
  };
3923
4202
  }
3924
4203
  function normalizeComparableURI(uri, opts) {
3925
- if (typeof uri === "string") {
3926
- const { normalized, malformedAuthorityOrPort } = normalizeStringWithStatus(uri, opts);
3927
- return malformedAuthorityOrPort ? void 0 : normalized;
4204
+ if (typeof uri !== "string" && typeof uri !== "object") {
4205
+ return void 0;
3928
4206
  }
3929
- if (typeof uri === "object") {
3930
- return serialize(uri, opts);
4207
+ let value;
4208
+ try {
4209
+ value = typeof uri === "string" ? uri : serialize(uri, opts);
4210
+ } catch {
4211
+ return void 0;
3931
4212
  }
4213
+ const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
4214
+ return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? void 0 : normalized;
3932
4215
  }
3933
4216
  var fastUri = {
3934
4217
  SCHEMES,
@@ -34734,12 +35017,82 @@ function messageOf(err) {
34734
35017
  return String(err);
34735
35018
  }
34736
35019
 
34737
- // node_modules/@chrischall/mcp-utils/dist/response/index.js
34738
- function textResult(data) {
34739
- return {
34740
- content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
34741
- };
35020
+ // node_modules/@chrischall/mcp-utils/dist/response/view.js
35021
+ var VIEWS = ["compact", "full", "raw"];
35022
+ var DEFAULT_VIEW = "compact";
35023
+ var BLURB = {
35024
+ compact: '"compact" (default) drops fields the response already carries elsewhere',
35025
+ full: '"full" returns every field this server understands',
35026
+ raw: '"raw" returns the upstream payload unprojected'
35027
+ };
35028
+ function viewParam(honoured, opts = {}) {
35029
+ if (honoured.length < 2) {
35030
+ throw new Error("viewParam needs at least two rungs: a parameter offering one value decides nothing");
35031
+ }
35032
+ if (!honoured.includes("compact")) {
35033
+ throw new Error('viewParam must offer "compact": a tool with no cheap rung has nothing to default to');
35034
+ }
35035
+ const ordered = VIEWS.filter((v) => honoured.includes(v));
35036
+ const sentence = `Response shape: ${ordered.map((v) => BLURB[v]).join("; ")}.`;
35037
+ return external_exports.enum(Object.fromEntries(ordered.map((v) => [v, v]))).optional().describe(opts.note ? `${sentence} ${opts.note}` : sentence);
34742
35038
  }
35039
+ function resolveView(value, honoured) {
35040
+ return value !== void 0 && honoured.includes(value) ? value : DEFAULT_VIEW;
35041
+ }
35042
+ function minifiedResult(data) {
35043
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
35044
+ }
35045
+
35046
+ // node_modules/@chrischall/mcp-utils/dist/response/media.js
35047
+ var MEDIA_NOUN = "(?:avatar|picture|photo|thumbnail|thumb|image|icon|banner|profile_pic(?:ture)?|logo)";
35048
+ var MEDIA_QUALIFIER = "(?:primary|secondary|main|default|cover|hero|profile|master|rendered|small|medium|large|full|original|tall)";
35049
+ var MEDIA_KEY = new RegExp(`^(?:(?:${MEDIA_QUALIFIER}|${MEDIA_NOUN})[_-]?)?${MEDIA_NOUN}s?(?:[_-]?(?:link|uri|url|src)s?)?$`, "i");
35050
+ var MEDIA_URL = /^https?:\/\/[^\s]+?\.(png|jpe?g|gif|webp|svg|avif|bmp|ico)([?#]|$)/i;
35051
+ function stripMediaUrls(value, opts = {}) {
35052
+ const keep = normalizeRules(opts.keep ?? []);
35053
+ const drop = normalizeRules(opts.drop ?? []);
35054
+ return walk(value, keep, drop);
35055
+ }
35056
+ function normalizeRules(rules) {
35057
+ return rules.map((rule) => typeof rule === "string" ? rule.toLowerCase() : new RegExp(rule.source, rule.flags));
35058
+ }
35059
+ function matchesRule(key, rules) {
35060
+ const lower = key.toLowerCase();
35061
+ for (const rule of rules) {
35062
+ if (typeof rule === "string") {
35063
+ if (rule === lower)
35064
+ return true;
35065
+ continue;
35066
+ }
35067
+ rule.lastIndex = 0;
35068
+ if (rule.test(key))
35069
+ return true;
35070
+ }
35071
+ return false;
35072
+ }
35073
+ function walk(value, keep, drop) {
35074
+ if (Array.isArray(value))
35075
+ return value.map((v) => walk(v, keep, drop));
35076
+ if (value === null || typeof value !== "object")
35077
+ return value;
35078
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)
35079
+ return value;
35080
+ const out = {};
35081
+ for (const [key, v] of Object.entries(value)) {
35082
+ if (matchesRule(key, keep)) {
35083
+ out[key] = v;
35084
+ continue;
35085
+ }
35086
+ if (MEDIA_KEY.test(key) || matchesRule(key, drop))
35087
+ continue;
35088
+ if (typeof v === "string" && MEDIA_URL.test(v))
35089
+ continue;
35090
+ out[key] = walk(v, keep, drop);
35091
+ }
35092
+ return out;
35093
+ }
35094
+
35095
+ // node_modules/@chrischall/mcp-utils/dist/response/index.js
34743
35096
  function errorResult(message) {
34744
35097
  return {
34745
35098
  content: [{ type: "text", text: redactSecrets(message) }],
@@ -39035,6 +39388,18 @@ function statusOf(err) {
39035
39388
  const s = err.status ?? err.statusCode;
39036
39389
  return typeof s === "number" ? s : void 0;
39037
39390
  }
39391
+ var CREDENTIAL_ARMS = /* @__PURE__ */ new Set([
39392
+ "ok",
39393
+ "no_credential",
39394
+ "credential_rejected",
39395
+ "timeout",
39396
+ "http",
39397
+ "transport",
39398
+ "unknown"
39399
+ ]);
39400
+ function isArm(kind) {
39401
+ return kind !== void 0 && CREDENTIAL_ARMS.has(kind);
39402
+ }
39038
39403
  function credentialHint(arm, prefix, hostLabel, source2) {
39039
39404
  switch (arm) {
39040
39405
  case "ok":
@@ -39072,13 +39437,27 @@ function registerCredentialHealthcheckTool(args) {
39072
39437
  try {
39073
39438
  state = await resolveCredential();
39074
39439
  } catch (e) {
39440
+ const classified = classifyThrown?.(e);
39075
39441
  const result2 = {
39076
39442
  ok: false,
39443
+ // Still false, and still no source: a classification explains WHY
39444
+ // nothing resolved, it does not invent a credential that did.
39077
39445
  credential: { source: null, resolved: false },
39078
39446
  // No `url`: nothing was probed, and naming one implies it was tried.
39079
39447
  probe: { elapsed_ms: 0 },
39080
- error: { kind: "no_credential", message: truncateErrorMessage(messageOf(e)) },
39081
- hint: hints?.no_credential ?? credentialHint("no_credential", prefix, hostLabel, null)
39448
+ error: {
39449
+ kind: classified?.kind ?? "no_credential",
39450
+ message: truncateErrorMessage(messageOf(e)),
39451
+ ...classified?.detail !== void 0 ? { detail: classified.detail } : {}
39452
+ },
39453
+ // The hint must follow the KIND beside it. Falling back to
39454
+ // `no_credential`'s copy under a classified kind would state a cause
39455
+ // the kind contradicts — the same disagreement this path exists to
39456
+ // remove. So: an inline hint wins; else the classified arm's own
39457
+ // copy (consumer override first); else, for a kind this module has
39458
+ // no copy for, the neutral `unknown` text rather than one that
39459
+ // asserts a cause; else the unclassified `no_credential` default.
39460
+ hint: classified?.hint ?? (isArm(classified?.kind) ? hints?.[classified.kind] ?? credentialHint(classified.kind, prefix, hostLabel, null) : classified !== void 0 ? credentialHint("unknown", prefix, hostLabel, null) : hints?.no_credential ?? credentialHint("no_credential", prefix, hostLabel, null))
39082
39461
  };
39083
39462
  return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
39084
39463
  }
@@ -39181,7 +39560,7 @@ function loadAccount(env = process.env) {
39181
39560
  // package.json
39182
39561
  var package_default = {
39183
39562
  name: "infinitecampus-mcp",
39184
- version: "2.7.0",
39563
+ version: "2.8.0",
39185
39564
  mcpName: "io.github.chrischall/infinitecampus-mcp",
39186
39565
  description: "Infinite Campus (Campus Parent) MCP server \u2014 multi-district read + message/document write",
39187
39566
  author: "Claude Code (AI) <https://www.anthropic.com/claude>",
@@ -39226,7 +39605,7 @@ var package_default = {
39226
39605
  typecheck: "tsc -p tsconfig.json --noEmit"
39227
39606
  },
39228
39607
  dependencies: {
39229
- "@chrischall/mcp-utils": "^0.19.2",
39608
+ "@chrischall/mcp-utils": "^0.23.2",
39230
39609
  "@fetchproxy/bootstrap": "^2.2.0",
39231
39610
  "@fetchproxy/server": "^2.2.0",
39232
39611
  "@modelcontextprotocol/sdk": "^1.29.0",
@@ -40238,15 +40617,27 @@ var FileExistsError = class extends Error {
40238
40617
  path;
40239
40618
  };
40240
40619
 
40620
+ // src/view.ts
40621
+ var IC_VIEWS = ["compact", "full"];
40622
+ var NOTE = `compact strips image/avatar URLs from the response; "full" returns Infinite Campus's payload untouched. No field projection: this server has no verified record of which Infinite Campus fields matter, and inventing one would risk dropping a field a caller needs.`;
40623
+ var viewArg = () => viewParam(IC_VIEWS, { note: NOTE });
40624
+ function viewResponse(view, data) {
40625
+ const rung = resolveView(view, IC_VIEWS);
40626
+ return minifiedResult(rung === "compact" ? stripMediaUrls(data) : data);
40627
+ }
40628
+
40241
40629
  // src/tools/districts.ts
40242
40630
  function registerDistrictTools(server, client) {
40243
40631
  server.registerTool("ic_list_districts", {
40244
40632
  description: "List Infinite Campus districts configured for this MCP server. Returns names + base URLs (no credentials).",
40633
+ inputSchema: {
40634
+ view: viewArg()
40635
+ },
40245
40636
  annotations: { readOnlyHint: true }
40246
- }, async () => {
40637
+ }, async ({ view }) => {
40247
40638
  await client.ensureDiscovery();
40248
40639
  const data = client.listDistricts();
40249
- return textResult(data);
40640
+ return viewResponse(view, data);
40250
40641
  });
40251
40642
  }
40252
40643
 
@@ -40302,11 +40693,11 @@ function registerStudentTools(server, client) {
40302
40693
  server.registerTool("ic_list_students", {
40303
40694
  description: "List students enrolled under the parent account for a given district.",
40304
40695
  annotations: { readOnlyHint: true },
40305
- inputSchema: argsSchema.shape
40696
+ inputSchema: { ...argsSchema.shape, view: viewArg() }
40306
40697
  }, async (rawArgs) => {
40307
40698
  const args = argsSchema.parse(rawArgs);
40308
40699
  const data = await client.request(args.district, "/campus/api/portal/students");
40309
- return textResult(data);
40700
+ return viewResponse(rawArgs.view, data);
40310
40701
  });
40311
40702
  }
40312
40703
 
@@ -40321,12 +40712,12 @@ function registerScheduleTools(server, client) {
40321
40712
  server.registerTool("ic_get_schedule", {
40322
40713
  description: "Get a student's class schedule for a given date (default: today).",
40323
40714
  annotations: { readOnlyHint: true },
40324
- inputSchema: argsSchema2.shape
40715
+ inputSchema: { ...argsSchema2.shape, view: viewArg() }
40325
40716
  }, async (rawArgs) => {
40326
40717
  const args = argsSchema2.parse(rawArgs);
40327
40718
  const params = new URLSearchParams({ personID: args.studentId });
40328
40719
  const data = await client.request(args.district, `/campus/resources/portal/roster?${params}`);
40329
- return textResult(data);
40720
+ return viewResponse(rawArgs.view, data);
40330
40721
  });
40331
40722
  }
40332
40723
 
@@ -40343,7 +40734,7 @@ function registerAssignmentTools(server, client) {
40343
40734
  server.registerTool("ic_list_assignments", {
40344
40735
  description: "List a student's assignments. The IC endpoint returns the full term history (~hundreds of items); date and missing filters are applied client-side. For a single course, pass courseId (the sectionID from ic_get_schedule).",
40345
40736
  annotations: { readOnlyHint: true },
40346
- inputSchema: argsSchema3.shape
40737
+ inputSchema: { ...argsSchema3.shape, view: viewArg() }
40347
40738
  }, async (rawArgs) => {
40348
40739
  const args = argsSchema3.parse(rawArgs);
40349
40740
  const params = new URLSearchParams({ personID: args.studentId });
@@ -40364,7 +40755,7 @@ function registerAssignmentTools(server, client) {
40364
40755
  if (args.missingOnly) {
40365
40756
  data = data.filter((a) => a.missing);
40366
40757
  }
40367
- return textResult(data);
40758
+ return viewResponse(rawArgs.view, data);
40368
40759
  });
40369
40760
  }
40370
40761
 
@@ -40378,13 +40769,13 @@ function registerGradeTools(server, client) {
40378
40769
  server.registerTool("ic_list_grades", {
40379
40770
  description: "List a student's term grades and in-progress course grades.",
40380
40771
  annotations: { readOnlyHint: true },
40381
- inputSchema: argsSchema4.shape
40772
+ inputSchema: { ...argsSchema4.shape, view: viewArg() }
40382
40773
  }, async (rawArgs) => {
40383
40774
  const args = argsSchema4.parse(rawArgs);
40384
40775
  const params = new URLSearchParams({ personID: args.studentId });
40385
40776
  if (args.termId) params.set("termID", args.termId);
40386
40777
  const data = await client.request(args.district, `/campus/resources/portal/grades?${params}`);
40387
- return textResult(data);
40778
+ return viewResponse(rawArgs.view, data);
40388
40779
  });
40389
40780
  }
40390
40781
 
@@ -40393,14 +40784,14 @@ function is404(e) {
40393
40784
  return e instanceof Error && e.message.startsWith("IC 404 ");
40394
40785
  }
40395
40786
  function featureDisabled(feature, district, data = []) {
40396
- return textResult({ warning: "FeatureDisabled", feature, district, data });
40787
+ return minifiedResult({ warning: "FeatureDisabled", feature, district, data });
40397
40788
  }
40398
40789
  async function findStudent(client, district, studentId) {
40399
40790
  const students = await client.request(district, "/campus/api/portal/students");
40400
40791
  return students.find((s) => String(s.personID) === studentId) ?? null;
40401
40792
  }
40402
40793
  function studentNotFound(studentId) {
40403
- return textResult({ error: "StudentNotFound", studentId });
40794
+ return minifiedResult({ error: "StudentNotFound", studentId });
40404
40795
  }
40405
40796
  async function checkFeatureDisabled(client, district, studentId, student, flag, toolName, emptyData = []) {
40406
40797
  const structureID = student.enrollments?.[0]?.structureID;
@@ -40453,7 +40844,7 @@ function registerAttendanceTools(server, client) {
40453
40844
  server.registerTool("ic_list_attendance", {
40454
40845
  description: "List a student's absences and tardies (per-course summary grouped by term). Auto-resolves enrollmentID from the student record.",
40455
40846
  annotations: { readOnlyHint: true },
40456
- inputSchema: argsSchema5.shape
40847
+ inputSchema: { ...argsSchema5.shape, view: viewArg() }
40457
40848
  }, async (rawArgs) => {
40458
40849
  const args = argsSchema5.parse(rawArgs);
40459
40850
  const student = await findStudent(client, args.district, args.studentId);
@@ -40483,7 +40874,7 @@ function registerAttendanceTools(server, client) {
40483
40874
  results.push({ ...entry, terms: trimmedTerms });
40484
40875
  }
40485
40876
  }
40486
- return textResult(results);
40877
+ return viewResponse(rawArgs.view, results);
40487
40878
  } catch (e) {
40488
40879
  if (is404(e)) return featureDisabled("attendance", args.district);
40489
40880
  throw e;
@@ -40502,7 +40893,7 @@ function registerBehaviorTools(server, client) {
40502
40893
  server.registerTool("ic_list_behavior", {
40503
40894
  description: "List a student's behavior events / referrals. Returns FeatureDisabled if the district has the behavior module turned off (detected via displayOptions or a 404 backstop).",
40504
40895
  annotations: { readOnlyHint: true },
40505
- inputSchema: argsSchema6.shape
40896
+ inputSchema: { ...argsSchema6.shape, view: viewArg() }
40506
40897
  }, async (rawArgs) => {
40507
40898
  const args = argsSchema6.parse(rawArgs);
40508
40899
  const student = await findStudent(client, args.district, args.studentId);
@@ -40514,7 +40905,7 @@ function registerBehaviorTools(server, client) {
40514
40905
  if (args.until) params.set("endDate", args.until);
40515
40906
  try {
40516
40907
  const data = await client.request(args.district, `/campus/resources/portal/behavior?${params}`);
40517
- return textResult(data);
40908
+ return viewResponse(rawArgs.view, data);
40518
40909
  } catch (e) {
40519
40910
  if (is404(e)) return featureDisabled("behavior", args.district);
40520
40911
  throw e;
@@ -40534,7 +40925,7 @@ function registerFoodServiceTools(server, client) {
40534
40925
  server.registerTool("ic_list_food_service", {
40535
40926
  description: "List a student's lunch balance and recent food-service transactions. Returns FeatureDisabled if the district has the module turned off (detected via displayOptions or a 404 backstop).",
40536
40927
  annotations: { readOnlyHint: true },
40537
- inputSchema: argsSchema7.shape
40928
+ inputSchema: { ...argsSchema7.shape, view: viewArg() }
40538
40929
  }, async (rawArgs) => {
40539
40930
  const args = argsSchema7.parse(rawArgs);
40540
40931
  const student = await findStudent(client, args.district, args.studentId);
@@ -40554,7 +40945,7 @@ function registerFoodServiceTools(server, client) {
40554
40945
  if (args.until) params.set("endDate", args.until);
40555
40946
  try {
40556
40947
  const data = await client.request(args.district, `/campus/resources/portal/foodService?${params}`);
40557
- return textResult(data);
40948
+ return viewResponse(rawArgs.view, data);
40558
40949
  } catch (e) {
40559
40950
  if (is404(e)) return featureDisabled("foodService", args.district, EMPTY_FOOD);
40560
40951
  throw e;
@@ -40679,7 +41070,7 @@ function registerMessageTools(server, client) {
40679
41070
  server.registerTool("ic_list_messages", {
40680
41071
  description: "List all parent-visible messages from three IC sources combined: (1) prism notifications (assignment alerts, grade postings, attendance alerts), (2) Messenger 2.0 inbox (teacher messages, district announcements with newMessage/actionRequired flags), and (3) portal userNotice announcements. Each section has its own count and items; if any source errors, that section contains an error field and the others still return normally. The `limit` arg caps the prism notifications only (the high-volume source). Note: listing inbox messages does not mark them as read in normal portal behavior, but some district configurations may update read-tracking; use ic_get_message for the full HTML body.",
40681
41072
  annotations: { readOnlyHint: true },
40682
- inputSchema: listArgs.shape
41073
+ inputSchema: { ...listArgs.shape, view: viewArg() }
40683
41074
  }, async (rawArgs) => {
40684
41075
  const args = listArgs.parse(rawArgs);
40685
41076
  const limit = args.limit ?? 20;
@@ -40712,18 +41103,18 @@ function registerMessageTools(server, client) {
40712
41103
  return { count: 0, items: [], error: e instanceof Error ? e.message : String(e) };
40713
41104
  });
40714
41105
  const [notifications, inbox, announcements] = await Promise.all([prismPromise, inboxPromise, noticePromise]);
40715
- return textResult({ notifications, inbox, announcements });
41106
+ return viewResponse(rawArgs.view, { notifications, inbox, announcements });
40716
41107
  });
40717
41108
  server.registerTool("ic_get_message", {
40718
41109
  description: "Fetch the HTML body of an inbox message and return it parsed into { subject, date, body, url }. Takes a `messageUrl` which is the `url` field from an item returned by ic_list_messages' inbox section (e.g. 'portal/messageView.xsl?x=messenger.MessengerEngine-getMessageRecipientView&messageID=...'). Relative and /campus/-prefixed URLs are both accepted. Note: fetching the HTML body may mark the message as read on some district configurations; probe against an empty inbox could not confirm the side effect.",
40719
41110
  annotations: { readOnlyHint: true },
40720
- inputSchema: getArgs.shape
41111
+ inputSchema: { ...getArgs.shape, view: viewArg() }
40721
41112
  }, async (rawArgs) => {
40722
41113
  const args = getArgs.parse(rawArgs);
40723
41114
  const path = normalizeMessageUrl(args.messageUrl);
40724
41115
  const html = await client.request(args.district, path, { responseType: "text" });
40725
41116
  const parsed = parseMessageHtml(html ?? "", path);
40726
- return textResult(parsed);
41117
+ return viewResponse(rawArgs.view, parsed);
40727
41118
  });
40728
41119
  }
40729
41120
 
@@ -40742,7 +41133,7 @@ function registerDocumentTools(server, client) {
40742
41133
  server.registerTool("ic_list_documents", {
40743
41134
  description: "List a student's available documents (report cards, transcripts, schedules). Returns metadata only \u2014 use ic_download_document to fetch the file. Returns FeatureDisabled if the district has the module turned off.",
40744
41135
  annotations: { readOnlyHint: true },
40745
- inputSchema: listArgs2.shape
41136
+ inputSchema: { ...listArgs2.shape, view: viewArg() }
40746
41137
  }, async (rawArgs) => {
40747
41138
  const args = listArgs2.parse(rawArgs);
40748
41139
  const student = await findStudent(client, args.district, args.studentId);
@@ -40763,7 +41154,7 @@ function registerDocumentTools(server, client) {
40763
41154
  if (d.endYear !== void 0) out.endYear = d.endYear;
40764
41155
  return out;
40765
41156
  });
40766
- return textResult(trimmed);
41157
+ return viewResponse(rawArgs.view, trimmed);
40767
41158
  } catch (e) {
40768
41159
  if (is404(e)) return featureDisabled("documents", args.district);
40769
41160
  throw e;
@@ -40779,10 +41170,10 @@ function registerDocumentTools(server, client) {
40779
41170
  const meta3 = await client.download(args.district, args.documentId, args.destinationPath, {
40780
41171
  overwrite: args.overwrite ?? false
40781
41172
  });
40782
- return textResult(meta3);
41173
+ return minifiedResult(meta3);
40783
41174
  } catch (e) {
40784
41175
  if (e instanceof Error && e.message.startsWith("IC download 404")) {
40785
- return textResult({ warning: "FeatureDisabled", feature: "documents", district: args.district });
41176
+ return minifiedResult({ warning: "FeatureDisabled", feature: "documents", district: args.district });
40786
41177
  }
40787
41178
  throw e;
40788
41179
  }
@@ -40800,7 +41191,7 @@ function registerCalendarTools(server, client) {
40800
41191
  server.registerTool("ic_list_school_days", {
40801
41192
  description: "List a student's school days (instructional calendar) grouped by term. Returns one entry per enrollment, with term boundaries (Q1-Q4 start/end dates) and the school days inside each term \u2014 including comments like 'Teacher Workday' or 'Spring Break'. Use since/until to narrow the range.",
40802
41193
  annotations: { readOnlyHint: true },
40803
- inputSchema: argsSchema8.shape
41194
+ inputSchema: { ...argsSchema8.shape, view: viewArg() }
40804
41195
  }, async (rawArgs) => {
40805
41196
  const args = argsSchema8.parse(rawArgs);
40806
41197
  const student = await findStudent(client, args.district, args.studentId);
@@ -40838,7 +41229,7 @@ function registerCalendarTools(server, client) {
40838
41229
  terms: trimmedTerms
40839
41230
  });
40840
41231
  }
40841
- return textResult(result);
41232
+ return viewResponse(rawArgs.view, result);
40842
41233
  });
40843
41234
  }
40844
41235
 
@@ -40896,7 +41287,7 @@ function registerAttendanceEventsTools(server, client) {
40896
41287
  server.registerTool("ic_list_attendance_events", {
40897
41288
  description: "List individual attendance events (absences, tardies, early releases) for a student. Each event has a code, description, excuse reason, and optional human-readable comments. Auto-resolves enrollmentID from the student record. Use since/until to filter by date and excusedOnly to show only excused events.",
40898
41289
  annotations: { readOnlyHint: true },
40899
- inputSchema: argsSchema9.shape
41290
+ inputSchema: { ...argsSchema9.shape, view: viewArg() }
40900
41291
  }, async (rawArgs) => {
40901
41292
  const args = argsSchema9.parse(rawArgs);
40902
41293
  const student = await findStudent(client, args.district, args.studentId);
@@ -40929,7 +41320,7 @@ function registerAttendanceEventsTools(server, client) {
40929
41320
  results.push(trimmed);
40930
41321
  }
40931
41322
  }
40932
- return textResult(results);
41323
+ return viewResponse(rawArgs.view, results);
40933
41324
  } catch (e) {
40934
41325
  if (is404(e)) return featureDisabled("attendance_events", args.district);
40935
41326
  throw e;
@@ -40968,7 +41359,7 @@ function registerRecentGradesTools(server, client) {
40968
41359
  server.registerTool("ic_list_recent_grades", {
40969
41360
  description: "List recently-graded assignments for a student. Server-side filtered by scoreModifiedDate. Pass since=YYYY-MM-DD to set the cutoff; defaults to 14 days ago.",
40970
41361
  annotations: { readOnlyHint: true },
40971
- inputSchema: argsSchema10.shape
41362
+ inputSchema: { ...argsSchema10.shape, view: viewArg() }
40972
41363
  }, async (rawArgs) => {
40973
41364
  const args = argsSchema10.parse(rawArgs);
40974
41365
  const sinceDate = args.since ?? defaultSinceDate(/* @__PURE__ */ new Date());
@@ -40985,7 +41376,7 @@ function registerRecentGradesTools(server, client) {
40985
41376
  }
40986
41377
  return out;
40987
41378
  });
40988
- return textResult(trimmed);
41379
+ return viewResponse(rawArgs.view, trimmed);
40989
41380
  });
40990
41381
  }
40991
41382
 
@@ -41019,7 +41410,7 @@ function registerTeacherTools(server, client) {
41019
41410
  server.registerTool("ic_list_teachers", {
41020
41411
  description: "List a student's teachers (per enrolled section) and assigned counselor(s). Combines two endpoints (section/contacts and studentCounselor/byUser). Response field shapes may vary slightly by district \u2014 core fields (firstName, lastName, email) are consistent; additional fields are passed through.",
41021
41412
  annotations: { readOnlyHint: true },
41022
- inputSchema: argsSchema11.shape
41413
+ inputSchema: { ...argsSchema11.shape, view: viewArg() }
41023
41414
  }, async (rawArgs) => {
41024
41415
  const args = argsSchema11.parse(rawArgs);
41025
41416
  const personID = encodeURIComponent(args.studentId);
@@ -41040,7 +41431,7 @@ function registerTeacherTools(server, client) {
41040
41431
  const [teachersRaw, counselorsRaw] = await Promise.all([teachersPromise, counselorsPromise]);
41041
41432
  const teachers = toArray(teachersRaw).map((t) => trimRecord(t));
41042
41433
  const counselors = toArray(counselorsRaw).map((c) => trimRecord(c));
41043
- return textResult({ counselors, teachers });
41434
+ return viewResponse(rawArgs.view, { counselors, teachers });
41044
41435
  });
41045
41436
  }
41046
41437
 
@@ -41053,7 +41444,7 @@ function registerAssessmentTools(server, client) {
41053
41444
  server.registerTool("ic_list_assessments", {
41054
41445
  description: "List a student's standardized test scores (state, national, district tests). Auto-resolves calendarID from each of the student's enrollments and returns one entry per enrollment. The shape of individual test records varies by district and test type \u2014 fields are passed through unchanged.",
41055
41446
  annotations: { readOnlyHint: true },
41056
- inputSchema: argsSchema12.shape
41447
+ inputSchema: { ...argsSchema12.shape, view: viewArg() }
41057
41448
  }, async (rawArgs) => {
41058
41449
  const args = argsSchema12.parse(rawArgs);
41059
41450
  const student = await findStudent(client, args.district, args.studentId);
@@ -41091,7 +41482,7 @@ function registerAssessmentTools(server, client) {
41091
41482
  if (feature404 && result.length === 0) {
41092
41483
  return featureDisabled("assessments", args.district);
41093
41484
  }
41094
- return textResult(result);
41485
+ return viewResponse(rawArgs.view, result);
41095
41486
  });
41096
41487
  }
41097
41488
 
@@ -41104,7 +41495,7 @@ function registerFeeTools(server, client) {
41104
41495
  server.registerTool("ic_list_fees", {
41105
41496
  description: "List a student's fee assignments (charges owed) and running balance/surplus. Combines two endpoints: fee assignments and totalSurplus. Returns FeatureDisabled only if both endpoints 404; if only one works, returns that side with warning: 'PartialSuccess' and an issues[] explaining which endpoint failed.",
41106
41497
  annotations: { readOnlyHint: true },
41107
- inputSchema: argsSchema13.shape
41498
+ inputSchema: { ...argsSchema13.shape, view: viewArg() }
41108
41499
  }, async (rawArgs) => {
41109
41500
  const args = argsSchema13.parse(rawArgs);
41110
41501
  const personIDEnc = encodeURIComponent(args.studentId);
@@ -41135,7 +41526,7 @@ function registerFeeTools(server, client) {
41135
41526
  feeAssignments: assignments.ok ? assignments.value : [],
41136
41527
  ...issues.length > 0 ? { issues } : {}
41137
41528
  };
41138
- return textResult(response);
41529
+ return viewResponse(rawArgs.view, response);
41139
41530
  });
41140
41531
  }
41141
41532
 
@@ -41148,7 +41539,7 @@ function registerFeaturesTools(server, client) {
41148
41539
  server.registerTool("ic_get_features", {
41149
41540
  description: "List the district's displayOptions feature-flag allow-list for each of a student's enrollments. Each enrollment's `features` object is a map of ~90 flag names (attendance, behavior, assessment, documents, grades, schedule, etc.) to booleans. A `false` value means the district has that feature disabled for this enrollment; `true` or missing means it's available. Used internally by other tools to short-circuit disabled features, but exposed here so the LLM can answer capability questions directly.",
41150
41541
  annotations: { readOnlyHint: true },
41151
- inputSchema: argsSchema14.shape
41542
+ inputSchema: { ...argsSchema14.shape, view: viewArg() }
41152
41543
  }, async (rawArgs) => {
41153
41544
  const args = argsSchema14.parse(rawArgs);
41154
41545
  const student = await findStudent(client, args.district, args.studentId);
@@ -41163,7 +41554,7 @@ function registerFeaturesTools(server, client) {
41163
41554
  features
41164
41555
  });
41165
41556
  }
41166
- return textResult(result);
41557
+ return viewResponse(rawArgs.view, result);
41167
41558
  });
41168
41559
  }
41169
41560
 
@@ -41187,7 +41578,7 @@ try {
41187
41578
  }
41188
41579
  var COMMON = {
41189
41580
  name: "infinitecampus",
41190
- version: "2.7.0"
41581
+ version: "2.8.0"
41191
41582
  // x-release-please-version
41192
41583
  };
41193
41584
  var healthState = { account, source, configError, client: null };