infinitecampus-mcp 3.1.9 → 3.2.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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.mcp.json +2 -2
- package/dist/bundle.js +369 -57
- package/dist/client.js +71 -1
- package/dist/index.js +1 -1
- package/dist/tools/assignments.js +3 -2
- package/dist/tools/attendance.js +3 -2
- package/dist/tools/attendance_events.js +3 -2
- package/dist/tools/behavior.js +3 -2
- package/dist/tools/calendar.js +111 -19
- package/dist/tools/foodservice.js +3 -2
- package/dist/tools/healthcheck.js +8 -1
- package/dist/tools/recent_grades.js +8 -6
- package/package.json +2 -2
- package/server.json +2 -2
- package/skills/ic/SKILL.md +9 -8
- package/skills/infinitecampus-api/references/endpoints.md +6 -0
package/dist/bundle.js
CHANGED
|
@@ -91,6 +91,7 @@ var require_util = __commonJS({
|
|
|
91
91
|
exports.explicitlyAborted = explicitlyAborted2;
|
|
92
92
|
exports.prefixIssues = prefixIssues2;
|
|
93
93
|
exports.unwrapMessage = unwrapMessage2;
|
|
94
|
+
exports.sizeCaps = sizeCaps2;
|
|
94
95
|
exports.attachSchema = attachSchema2;
|
|
95
96
|
exports.finalizeIssue = finalizeIssue2;
|
|
96
97
|
exports.getSizableOrigin = getSizableOrigin2;
|
|
@@ -625,6 +626,18 @@ var require_util = __commonJS({
|
|
|
625
626
|
function unwrapMessage2(message) {
|
|
626
627
|
return typeof message === "string" ? message : message?.message;
|
|
627
628
|
}
|
|
629
|
+
function sizeCaps2(defChecks) {
|
|
630
|
+
const caps = [];
|
|
631
|
+
for (const ch of defChecks ?? []) {
|
|
632
|
+
const d = ch._zod.def;
|
|
633
|
+
if (!/_(length|size)$|_equals$/.test(d.check))
|
|
634
|
+
break;
|
|
635
|
+
const max = d.maximum ?? d.length ?? d.size;
|
|
636
|
+
if (max >= 0)
|
|
637
|
+
caps.push([max, ch]);
|
|
638
|
+
}
|
|
639
|
+
return caps;
|
|
640
|
+
}
|
|
628
641
|
function attachSchema2(issues, start, inst) {
|
|
629
642
|
var _a3;
|
|
630
643
|
for (let i = start; i < issues.length; i++) {
|
|
@@ -2289,7 +2302,7 @@ var require_versions = __commonJS({
|
|
|
2289
2302
|
exports.version = {
|
|
2290
2303
|
major: 4,
|
|
2291
2304
|
minor: 6,
|
|
2292
|
-
patch:
|
|
2305
|
+
patch: 7
|
|
2293
2306
|
};
|
|
2294
2307
|
(function() {
|
|
2295
2308
|
var keys = Object.getOwnPropertyNames(exports);
|
|
@@ -3123,6 +3136,31 @@ var require_schemas = __commonJS({
|
|
|
3123
3136
|
return payload;
|
|
3124
3137
|
};
|
|
3125
3138
|
});
|
|
3139
|
+
function capSize2(inst, size) {
|
|
3140
|
+
const caps = util.sizeCaps(inst._zod.def.checks);
|
|
3141
|
+
if (!caps.length)
|
|
3142
|
+
return;
|
|
3143
|
+
const cap = Math.min(...caps.map((c) => c[0]));
|
|
3144
|
+
const parse3 = inst._zod.parse;
|
|
3145
|
+
inst._zod.parse = (payload, ctx) => {
|
|
3146
|
+
const n = size(payload.value);
|
|
3147
|
+
if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
|
|
3148
|
+
for (const [max, ch] of util.sizeCaps(inst._zod.def.checks)) {
|
|
3149
|
+
if (n > max && ch._zod.def.when(payload)) {
|
|
3150
|
+
const start = payload.issues.length;
|
|
3151
|
+
ch._zod.check(payload);
|
|
3152
|
+
payload.issues[start].continue = false;
|
|
3153
|
+
util.attachSchema(payload.issues, start, inst);
|
|
3154
|
+
return payload;
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
return parse3(payload, ctx);
|
|
3159
|
+
};
|
|
3160
|
+
}
|
|
3161
|
+
var arraySize2 = (input2) => Array.isArray(input2) ? input2.length : -1;
|
|
3162
|
+
var mapSize2 = (input2) => input2 instanceof Map ? input2.size : -1;
|
|
3163
|
+
var setSize2 = (input2) => input2 instanceof Set ? input2.size : -1;
|
|
3126
3164
|
function handleArrayResult2(result, final, index) {
|
|
3127
3165
|
if (result.issues.length) {
|
|
3128
3166
|
final.issues.push(...util.prefixIssues(index, result.issues));
|
|
@@ -3166,6 +3204,7 @@ var require_schemas = __commonJS({
|
|
|
3166
3204
|
}
|
|
3167
3205
|
return payload;
|
|
3168
3206
|
};
|
|
3207
|
+
capSize2(inst, arraySize2);
|
|
3169
3208
|
});
|
|
3170
3209
|
function handlePropertyResult2(result, final, key, input2, optin, optout) {
|
|
3171
3210
|
const isPresent = key in input2;
|
|
@@ -4122,6 +4161,7 @@ var require_schemas = __commonJS({
|
|
|
4122
4161
|
return Promise.all(proms).then(() => payload);
|
|
4123
4162
|
return payload;
|
|
4124
4163
|
};
|
|
4164
|
+
capSize2(inst, mapSize2);
|
|
4125
4165
|
});
|
|
4126
4166
|
function handleMapResult2(keyResult, valueResult, final, key, input2, inst, ctx) {
|
|
4127
4167
|
if (keyResult.issues.length) {
|
|
@@ -4188,6 +4228,7 @@ var require_schemas = __commonJS({
|
|
|
4188
4228
|
return Promise.all(proms).then(() => payload);
|
|
4189
4229
|
return payload;
|
|
4190
4230
|
};
|
|
4231
|
+
capSize2(inst, setSize2);
|
|
4191
4232
|
});
|
|
4192
4233
|
function handleSetResult2(result, final) {
|
|
4193
4234
|
if (result.issues.length) {
|
|
@@ -16292,9 +16333,15 @@ ${code}
|
|
|
16292
16333
|
doc.write(`}`);
|
|
16293
16334
|
return outputVar;
|
|
16294
16335
|
}
|
|
16336
|
+
function generateSizeGate2(doc, schema, size) {
|
|
16337
|
+
for (const [max, check2] of util.sizeCaps(schema._zod.def.checks)) {
|
|
16338
|
+
doc.write(`if (${size} > ${numericOperand2(max, check2._zod.def.check)}) return INVALID;`);
|
|
16339
|
+
}
|
|
16340
|
+
}
|
|
16295
16341
|
function generateArrayCheck2(doc, ctx, schema, accessor, buildsValue = true) {
|
|
16296
16342
|
const def = schema._zod.def;
|
|
16297
16343
|
doc.write(`if (!Array.isArray(${accessor})) return INVALID;`);
|
|
16344
|
+
generateSizeGate2(doc, schema, `${accessor}.length`);
|
|
16298
16345
|
const outputVar = buildsValue ? newVar2(ctx) : null;
|
|
16299
16346
|
const iVar = newVar2(ctx);
|
|
16300
16347
|
const elemVar = newVar2(ctx);
|
|
@@ -16694,6 +16741,7 @@ ${code}
|
|
|
16694
16741
|
function generateMapCheck2(doc, ctx, schema, accessor) {
|
|
16695
16742
|
const def = schema._zod.def;
|
|
16696
16743
|
doc.write(`if (!(${accessor} instanceof Map)) return INVALID;`);
|
|
16744
|
+
generateSizeGate2(doc, schema, `${accessor}.size`);
|
|
16697
16745
|
const outputVar = newVar2(ctx);
|
|
16698
16746
|
const kVar = newVar2(ctx);
|
|
16699
16747
|
const valVar = newVar2(ctx);
|
|
@@ -16710,6 +16758,7 @@ ${code}
|
|
|
16710
16758
|
function generateSetCheck2(doc, ctx, schema, accessor) {
|
|
16711
16759
|
const def = schema._zod.def;
|
|
16712
16760
|
doc.write(`if (!(${accessor} instanceof Set)) return INVALID;`);
|
|
16761
|
+
generateSizeGate2(doc, schema, `${accessor}.size`);
|
|
16713
16762
|
const outputVar = newVar2(ctx);
|
|
16714
16763
|
const valVar = newVar2(ctx);
|
|
16715
16764
|
doc.write(`const ${outputVar} = new Set();`);
|
|
@@ -27078,7 +27127,7 @@ function declaredDialect(schema, remedy) {
|
|
|
27078
27127
|
throw new Error(`JSON Schema declares an unsupported dialect ("$schema": "${schema.$schema.slice(0, 200)}"). The default validator supports JSON Schema 2020-12, 2019-09, draft-07, and draft-06; ${remedy}`);
|
|
27079
27128
|
}
|
|
27080
27129
|
|
|
27081
|
-
// node_modules/@modelcontextprotocol/core/dist/auth-BNDyLTqp.mjs
|
|
27130
|
+
// node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/dist/auth-BNDyLTqp.mjs
|
|
27082
27131
|
var z = __toESM(require_v4(), 1);
|
|
27083
27132
|
var LATEST_PROTOCOL_VERSION = "2025-11-25";
|
|
27084
27133
|
var SUPPORTED_PROTOCOL_VERSIONS = [
|
|
@@ -41871,7 +41920,7 @@ var API_KEY_RE = new RegExp([
|
|
|
41871
41920
|
// webhook signing secret (Stripe-style)
|
|
41872
41921
|
].map((p) => `\\b${p}`).join("|"), "g");
|
|
41873
41922
|
var GOOGLE_OAUTH_TOKEN_RE = /(?<![A-Za-z0-9+/])(?:ya29\.|1\/\/)[A-Za-z0-9._-]{8,}/g;
|
|
41874
|
-
var QUERY_SECRET_RE = new RegExp(`([
|
|
41923
|
+
var QUERY_SECRET_RE = new RegExp(`([?&#;](?:(?:access|refresh|id|auth|session|csrf|xsrf|api)[_-]?token|client[_-]?secret|api[_-]?secret|api[_-]?key|password|passwd|signature|secret|token|auth|key|sig|(?:code[_-]?)?verifier|(?:php|j)?sess(?:ion)?[_-]?id|sid|x[-_]${HEADER_NAME_RUN}?(?:api[-_]?key|token|secret|auth)${HEADER_NAME_RUN})=)[^&#\\s"'<>\`]+`, "gi");
|
|
41875
41924
|
var OAUTH_CODE_RE = /([?&]code=)(?=[^&#\s"'<>`]{16,})[^&#\s"'<>`]+/gi;
|
|
41876
41925
|
var FORM_PASSWORD_RE = /((?:^|[\s,;:"'(\[{])(?:password|passwd)=)[^&#\s"'<>`]+/gim;
|
|
41877
41926
|
var HEADER_SECRET_RE = new RegExp(`(\\b(?:x[-_]${HEADER_NAME_RUN}?(?:api[-_]?key|token|secret|auth)${HEADER_NAME_RUN}|api[-_]?key)\\s*:\\s*)[^\\s,;"'<>\`]+`, "gi");
|
|
@@ -41882,6 +41931,8 @@ var JSON_SECRET_KEYS = [
|
|
|
41882
41931
|
"api[_-]?secret",
|
|
41883
41932
|
"(?:x[_-])?api[_-]?key",
|
|
41884
41933
|
"private[_-]?key",
|
|
41934
|
+
"aws[_-]?secret[_-]?access[_-]?key",
|
|
41935
|
+
// fleet-audit#1297
|
|
41885
41936
|
"code[_-]?verifier",
|
|
41886
41937
|
// PKCE; a bare `verifier` key is too generic for JSON
|
|
41887
41938
|
`x[_-]${HEADER_NAME_RUN}?(?:api[_-]?key|token|secret|auth)${HEADER_NAME_RUN}`,
|
|
@@ -42579,6 +42630,7 @@ __export(util_exports, {
|
|
|
42579
42630
|
required: () => required,
|
|
42580
42631
|
safeExtend: () => safeExtend,
|
|
42581
42632
|
shallowClone: () => shallowClone,
|
|
42633
|
+
sizeCaps: () => sizeCaps,
|
|
42582
42634
|
slugify: () => slugify,
|
|
42583
42635
|
stringifyPrimitive: () => stringifyPrimitive,
|
|
42584
42636
|
toZod: () => toZod,
|
|
@@ -43098,6 +43150,18 @@ function prefixIssues(path, issues) {
|
|
|
43098
43150
|
function unwrapMessage(message) {
|
|
43099
43151
|
return typeof message === "string" ? message : message?.message;
|
|
43100
43152
|
}
|
|
43153
|
+
function sizeCaps(defChecks) {
|
|
43154
|
+
const caps = [];
|
|
43155
|
+
for (const ch of defChecks ?? []) {
|
|
43156
|
+
const d = ch._zod.def;
|
|
43157
|
+
if (!/_(length|size)$|_equals$/.test(d.check))
|
|
43158
|
+
break;
|
|
43159
|
+
const max = d.maximum ?? d.length ?? d.size;
|
|
43160
|
+
if (max >= 0)
|
|
43161
|
+
caps.push([max, ch]);
|
|
43162
|
+
}
|
|
43163
|
+
return caps;
|
|
43164
|
+
}
|
|
43101
43165
|
function attachSchema(issues, start, inst) {
|
|
43102
43166
|
var _a3;
|
|
43103
43167
|
for (let i = start; i < issues.length; i++) {
|
|
@@ -44518,7 +44582,7 @@ ${content.join("\n")}
|
|
|
44518
44582
|
var version = {
|
|
44519
44583
|
major: 4,
|
|
44520
44584
|
minor: 6,
|
|
44521
|
-
patch:
|
|
44585
|
+
patch: 7
|
|
44522
44586
|
};
|
|
44523
44587
|
|
|
44524
44588
|
// node_modules/zod/v4/core/schemas.js
|
|
@@ -45274,6 +45338,31 @@ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
|
|
|
45274
45338
|
return payload;
|
|
45275
45339
|
};
|
|
45276
45340
|
});
|
|
45341
|
+
function capSize(inst, size) {
|
|
45342
|
+
const caps = sizeCaps(inst._zod.def.checks);
|
|
45343
|
+
if (!caps.length)
|
|
45344
|
+
return;
|
|
45345
|
+
const cap = Math.min(...caps.map((c) => c[0]));
|
|
45346
|
+
const parse3 = inst._zod.parse;
|
|
45347
|
+
inst._zod.parse = (payload, ctx) => {
|
|
45348
|
+
const n = size(payload.value);
|
|
45349
|
+
if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
|
|
45350
|
+
for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
|
|
45351
|
+
if (n > max && ch._zod.def.when(payload)) {
|
|
45352
|
+
const start = payload.issues.length;
|
|
45353
|
+
ch._zod.check(payload);
|
|
45354
|
+
payload.issues[start].continue = false;
|
|
45355
|
+
attachSchema(payload.issues, start, inst);
|
|
45356
|
+
return payload;
|
|
45357
|
+
}
|
|
45358
|
+
}
|
|
45359
|
+
}
|
|
45360
|
+
return parse3(payload, ctx);
|
|
45361
|
+
};
|
|
45362
|
+
}
|
|
45363
|
+
var arraySize = (input2) => Array.isArray(input2) ? input2.length : -1;
|
|
45364
|
+
var mapSize = (input2) => input2 instanceof Map ? input2.size : -1;
|
|
45365
|
+
var setSize = (input2) => input2 instanceof Set ? input2.size : -1;
|
|
45277
45366
|
function handleArrayResult(result, final, index) {
|
|
45278
45367
|
if (result.issues.length) {
|
|
45279
45368
|
final.issues.push(...prefixIssues(index, result.issues));
|
|
@@ -45317,6 +45406,7 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
|
|
|
45317
45406
|
}
|
|
45318
45407
|
return payload;
|
|
45319
45408
|
};
|
|
45409
|
+
capSize(inst, arraySize);
|
|
45320
45410
|
});
|
|
45321
45411
|
function handlePropertyResult(result, final, key, input2, optin, optout) {
|
|
45322
45412
|
const isPresent = key in input2;
|
|
@@ -46273,6 +46363,7 @@ var $ZodMap = /* @__PURE__ */ $constructor("$ZodMap", (inst, def) => {
|
|
|
46273
46363
|
return Promise.all(proms).then(() => payload);
|
|
46274
46364
|
return payload;
|
|
46275
46365
|
};
|
|
46366
|
+
capSize(inst, mapSize);
|
|
46276
46367
|
});
|
|
46277
46368
|
function handleMapResult(keyResult, valueResult, final, key, input2, inst, ctx) {
|
|
46278
46369
|
if (keyResult.issues.length) {
|
|
@@ -46339,6 +46430,7 @@ var $ZodSet = /* @__PURE__ */ $constructor("$ZodSet", (inst, def) => {
|
|
|
46339
46430
|
return Promise.all(proms).then(() => payload);
|
|
46340
46431
|
return payload;
|
|
46341
46432
|
};
|
|
46433
|
+
capSize(inst, setSize);
|
|
46342
46434
|
});
|
|
46343
46435
|
function handleSetResult(result, final) {
|
|
46344
46436
|
if (result.issues.length) {
|
|
@@ -55869,9 +55961,15 @@ function generateNullableCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
|
55869
55961
|
doc.write(`}`);
|
|
55870
55962
|
return outputVar;
|
|
55871
55963
|
}
|
|
55964
|
+
function generateSizeGate(doc, schema, size) {
|
|
55965
|
+
for (const [max, check2] of sizeCaps(schema._zod.def.checks)) {
|
|
55966
|
+
doc.write(`if (${size} > ${numericOperand(max, check2._zod.def.check)}) return INVALID;`);
|
|
55967
|
+
}
|
|
55968
|
+
}
|
|
55872
55969
|
function generateArrayCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
55873
55970
|
const def = schema._zod.def;
|
|
55874
55971
|
doc.write(`if (!Array.isArray(${accessor})) return INVALID;`);
|
|
55972
|
+
generateSizeGate(doc, schema, `${accessor}.length`);
|
|
55875
55973
|
const outputVar = buildsValue ? newVar(ctx) : null;
|
|
55876
55974
|
const iVar = newVar(ctx);
|
|
55877
55975
|
const elemVar = newVar(ctx);
|
|
@@ -56271,6 +56369,7 @@ function literalPropertyKey(ctx, key) {
|
|
|
56271
56369
|
function generateMapCheck(doc, ctx, schema, accessor) {
|
|
56272
56370
|
const def = schema._zod.def;
|
|
56273
56371
|
doc.write(`if (!(${accessor} instanceof Map)) return INVALID;`);
|
|
56372
|
+
generateSizeGate(doc, schema, `${accessor}.size`);
|
|
56274
56373
|
const outputVar = newVar(ctx);
|
|
56275
56374
|
const kVar = newVar(ctx);
|
|
56276
56375
|
const valVar = newVar(ctx);
|
|
@@ -56287,6 +56386,7 @@ function generateMapCheck(doc, ctx, schema, accessor) {
|
|
|
56287
56386
|
function generateSetCheck(doc, ctx, schema, accessor) {
|
|
56288
56387
|
const def = schema._zod.def;
|
|
56289
56388
|
doc.write(`if (!(${accessor} instanceof Set)) return INVALID;`);
|
|
56389
|
+
generateSizeGate(doc, schema, `${accessor}.size`);
|
|
56290
56390
|
const outputVar = newVar(ctx);
|
|
56291
56391
|
const valVar = newVar(ctx);
|
|
56292
56392
|
doc.write(`const ${outputVar} = new Set();`);
|
|
@@ -62094,10 +62194,63 @@ function codePointOr(code, raw) {
|
|
|
62094
62194
|
return String.fromCodePoint(code);
|
|
62095
62195
|
}
|
|
62096
62196
|
|
|
62197
|
+
// node_modules/@chrischall/mcp-utils/dist/internal/tags.js
|
|
62198
|
+
function replaceTags(html, replacement) {
|
|
62199
|
+
let out = "";
|
|
62200
|
+
let i = 0;
|
|
62201
|
+
for (; ; ) {
|
|
62202
|
+
const lt = html.indexOf("<", i);
|
|
62203
|
+
if (lt < 0)
|
|
62204
|
+
break;
|
|
62205
|
+
const gt = html.indexOf(">", lt + 1);
|
|
62206
|
+
if (gt < 0)
|
|
62207
|
+
break;
|
|
62208
|
+
if (gt === lt + 1) {
|
|
62209
|
+
out += html.slice(i, lt + 1);
|
|
62210
|
+
i = lt + 1;
|
|
62211
|
+
continue;
|
|
62212
|
+
}
|
|
62213
|
+
out += html.slice(i, lt) + replacement;
|
|
62214
|
+
i = gt + 1;
|
|
62215
|
+
}
|
|
62216
|
+
return out + html.slice(i);
|
|
62217
|
+
}
|
|
62218
|
+
|
|
62097
62219
|
// node_modules/@chrischall/mcp-utils/dist/scrape/index.js
|
|
62220
|
+
var NAMED_ENTITIES = {
|
|
62221
|
+
nbsp: " ",
|
|
62222
|
+
lt: "<",
|
|
62223
|
+
gt: ">",
|
|
62224
|
+
quot: '"',
|
|
62225
|
+
apos: "'"
|
|
62226
|
+
};
|
|
62227
|
+
function decodeHtmlEntities(text) {
|
|
62228
|
+
return text.replace(/&#(\d+);/g, (whole, d) => codePointOr(Number(d), whole)).replace(/&#x([0-9a-fA-F]+);/g, (whole, h) => codePointOr(parseInt(h, 16), whole)).replace(/&(nbsp|lt|gt|quot|apos);/gi, (whole, name) => {
|
|
62229
|
+
return NAMED_ENTITIES[name.toLowerCase()] ?? whole;
|
|
62230
|
+
}).replace(/&/gi, "&");
|
|
62231
|
+
}
|
|
62098
62232
|
var NEXT_DATA_MAX_CHARS = 16 * 1024 * 1024;
|
|
62099
62233
|
function isCloudflareChallenge(html) {
|
|
62100
|
-
return
|
|
62234
|
+
return html.includes("_cf_chl_opt") || hasJustAMomentTitle(html);
|
|
62235
|
+
}
|
|
62236
|
+
var JUST_A_MOMENT = "just a moment";
|
|
62237
|
+
function hasJustAMomentTitle(html) {
|
|
62238
|
+
const lower = asciiLower(html);
|
|
62239
|
+
let i = 0;
|
|
62240
|
+
for (; ; ) {
|
|
62241
|
+
const open3 = lower.indexOf("<title", i);
|
|
62242
|
+
if (open3 < 0)
|
|
62243
|
+
return false;
|
|
62244
|
+
const gt = lower.indexOf(">", open3 + 6);
|
|
62245
|
+
if (gt < 0)
|
|
62246
|
+
return false;
|
|
62247
|
+
let j = gt + 1;
|
|
62248
|
+
while (j < lower.length && /\s/.test(lower[j]))
|
|
62249
|
+
j++;
|
|
62250
|
+
if (lower.startsWith(JUST_A_MOMENT, j))
|
|
62251
|
+
return true;
|
|
62252
|
+
i = gt + 1;
|
|
62253
|
+
}
|
|
62101
62254
|
}
|
|
62102
62255
|
|
|
62103
62256
|
// node_modules/@chrischall/mcp-utils/dist/http/index.js
|
|
@@ -62231,6 +62384,55 @@ function splitSetCookie(header) {
|
|
|
62231
62384
|
return header.split(/,(?=\s*[^;,\s]+\s*=)/).map((s) => s.trim()).filter((s) => s.length > 0);
|
|
62232
62385
|
}
|
|
62233
62386
|
|
|
62387
|
+
// node_modules/@chrischall/mcp-utils/dist/dates/index.js
|
|
62388
|
+
var ISO_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
62389
|
+
var pad2 = (n) => String(n).padStart(2, "0");
|
|
62390
|
+
var USER_TIME_ZONE_ENV = "MCP_USER_TZ";
|
|
62391
|
+
function isValidTimeZone(timeZone) {
|
|
62392
|
+
if (!timeZone)
|
|
62393
|
+
return false;
|
|
62394
|
+
try {
|
|
62395
|
+
new Intl.DateTimeFormat("en-US", { timeZone });
|
|
62396
|
+
return true;
|
|
62397
|
+
} catch {
|
|
62398
|
+
return false;
|
|
62399
|
+
}
|
|
62400
|
+
}
|
|
62401
|
+
function resolveUserTimeZone(opts = {}) {
|
|
62402
|
+
if (opts.timeZone !== void 0)
|
|
62403
|
+
return opts.timeZone;
|
|
62404
|
+
const fromEnv = readEnvVar(USER_TIME_ZONE_ENV, { env: opts.env });
|
|
62405
|
+
return fromEnv !== void 0 && isValidTimeZone(fromEnv) ? fromEnv : void 0;
|
|
62406
|
+
}
|
|
62407
|
+
function todayIso(nowOrOpts) {
|
|
62408
|
+
const opts = nowOrOpts instanceof Date ? { now: nowOrOpts } : nowOrOpts ?? {};
|
|
62409
|
+
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
62410
|
+
const timeZone = resolveUserTimeZone(opts);
|
|
62411
|
+
if (timeZone === void 0) {
|
|
62412
|
+
return `${now.getFullYear()}-${pad2(now.getMonth() + 1)}-${pad2(now.getDate())}`;
|
|
62413
|
+
}
|
|
62414
|
+
if (!isValidTimeZone(timeZone))
|
|
62415
|
+
throw new RangeError(`Invalid IANA time zone: ${timeZone}`);
|
|
62416
|
+
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
62417
|
+
timeZone,
|
|
62418
|
+
year: "numeric",
|
|
62419
|
+
month: "2-digit",
|
|
62420
|
+
day: "2-digit"
|
|
62421
|
+
}).formatToParts(now);
|
|
62422
|
+
const part = (type) => parts.find((p) => p.type === type)?.value ?? "";
|
|
62423
|
+
return `${part("year")}-${part("month")}-${part("day")}`;
|
|
62424
|
+
}
|
|
62425
|
+
function toIsoDateUtc(d) {
|
|
62426
|
+
return `${d.getUTCFullYear()}-${pad2(d.getUTCMonth() + 1)}-${pad2(d.getUTCDate())}`;
|
|
62427
|
+
}
|
|
62428
|
+
function shiftIsoDate(date5, days) {
|
|
62429
|
+
const m = ISO_DATE.exec(date5.trim());
|
|
62430
|
+
if (!m)
|
|
62431
|
+
return date5.trim();
|
|
62432
|
+
const shifted = new Date(Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3]) + days));
|
|
62433
|
+
return toIsoDateUtc(shifted);
|
|
62434
|
+
}
|
|
62435
|
+
|
|
62234
62436
|
// node_modules/@chrischall/mcp-utils/dist/zod/index.js
|
|
62235
62437
|
var PositiveInt = external_exports.number().int().positive();
|
|
62236
62438
|
var NonNegInt = external_exports.number().int().nonnegative();
|
|
@@ -68700,7 +68902,7 @@ function resolveDownloadDir(env = process.env) {
|
|
|
68700
68902
|
// package.json
|
|
68701
68903
|
var package_default = {
|
|
68702
68904
|
name: "infinitecampus-mcp",
|
|
68703
|
-
version: "3.1
|
|
68905
|
+
version: "3.2.1",
|
|
68704
68906
|
mcpName: "io.github.chrischall/infinitecampus-mcp",
|
|
68705
68907
|
description: "Infinite Campus (Campus Parent) MCP server \u2014 multi-district, read-only (plus local document download)",
|
|
68706
68908
|
author: "Claude Code (AI) <https://www.anthropic.com/claude>",
|
|
@@ -68745,7 +68947,7 @@ var package_default = {
|
|
|
68745
68947
|
typecheck: "tsc -p tsconfig.json --noEmit"
|
|
68746
68948
|
},
|
|
68747
68949
|
dependencies: {
|
|
68748
|
-
"@chrischall/mcp-utils": "^3.0.
|
|
68950
|
+
"@chrischall/mcp-utils": "^3.0.3",
|
|
68749
68951
|
"@fetchproxy/bootstrap": "^3.6.0",
|
|
68750
68952
|
"@fetchproxy/server": "^3.6.0",
|
|
68751
68953
|
"@modelcontextprotocol/server": "^2.3.0",
|
|
@@ -69427,6 +69629,10 @@ var ICClient = class {
|
|
|
69427
69629
|
// linkedDistrictName → primaryDistrictName
|
|
69428
69630
|
primaryName;
|
|
69429
69631
|
featuresCache = /* @__PURE__ */ new Map();
|
|
69632
|
+
/** Campus version per district, read once. A failed read is dropped, to be retried after VERSION_RETRY_MS. */
|
|
69633
|
+
versions = /* @__PURE__ */ new Map();
|
|
69634
|
+
/** When each district's last version read failed — see VERSION_RETRY_MS. */
|
|
69635
|
+
versionFailedAt = /* @__PURE__ */ new Map();
|
|
69430
69636
|
/**
|
|
69431
69637
|
* True when the primary account has empty creds (fetchproxy mode). The
|
|
69432
69638
|
* client uses pre-loaded cookies in place of the `verify.jsp` POST and
|
|
@@ -69597,7 +69803,37 @@ var ICClient = class {
|
|
|
69597
69803
|
async request(district, path, opts = {}) {
|
|
69598
69804
|
const account2 = await this.resolveAccount(district);
|
|
69599
69805
|
await this.managers.get(account2.name).ensure();
|
|
69600
|
-
|
|
69806
|
+
try {
|
|
69807
|
+
return await this.doRequest(account2, path, opts);
|
|
69808
|
+
} catch (e) {
|
|
69809
|
+
if (e instanceof PortalUnreachableError) e.setCampusVersion(await this.campusVersion(account2.name));
|
|
69810
|
+
throw e;
|
|
69811
|
+
}
|
|
69812
|
+
}
|
|
69813
|
+
/**
|
|
69814
|
+
* The district's Campus version (e.g. "2635.16"), or null when it cannot be
|
|
69815
|
+
* read. DIAGNOSTIC ONLY — nothing chooses behaviour by it. The only place IC
|
|
69816
|
+
* states it is the parent login page footer ("Version:Campus-2635.16"),
|
|
69817
|
+
* which needs no session, so this works in fetchproxy mode too and never
|
|
69818
|
+
* touches a district's cookies.
|
|
69819
|
+
*/
|
|
69820
|
+
campusVersion(district) {
|
|
69821
|
+
const account2 = this.accounts.get(district);
|
|
69822
|
+
if (!account2) return Promise.resolve(null);
|
|
69823
|
+
const failedAt = this.versionFailedAt.get(account2.name);
|
|
69824
|
+
if (failedAt !== void 0 && Date.now() - failedAt < VERSION_RETRY_MS) return Promise.resolve(null);
|
|
69825
|
+
let pending = this.versions.get(account2.name);
|
|
69826
|
+
if (!pending) {
|
|
69827
|
+
pending = fetchCampusVersion(account2).then((v) => {
|
|
69828
|
+
if (v === null) {
|
|
69829
|
+
this.versions.delete(account2.name);
|
|
69830
|
+
this.versionFailedAt.set(account2.name, Date.now());
|
|
69831
|
+
}
|
|
69832
|
+
return v;
|
|
69833
|
+
});
|
|
69834
|
+
this.versions.set(account2.name, pending);
|
|
69835
|
+
}
|
|
69836
|
+
return pending;
|
|
69601
69837
|
}
|
|
69602
69838
|
/**
|
|
69603
69839
|
* The account for `district`, running CUPS discovery once on a miss.
|
|
@@ -69973,7 +70209,30 @@ var PortalUnreachableError = class extends Error {
|
|
|
69973
70209
|
}
|
|
69974
70210
|
district;
|
|
69975
70211
|
status;
|
|
70212
|
+
/** The district's Campus version, when it could be read — for bug reports. */
|
|
70213
|
+
campusVersion;
|
|
70214
|
+
setCampusVersion(version2) {
|
|
70215
|
+
if (version2 === null) return;
|
|
70216
|
+
this.campusVersion = version2;
|
|
70217
|
+
this.message += ` [Campus ${version2}]`;
|
|
70218
|
+
}
|
|
69976
70219
|
};
|
|
70220
|
+
function parseCampusVersion(html) {
|
|
70221
|
+
return /Version:\s*Campus-([0-9][\w.-]*)/.exec(html)?.[1] ?? null;
|
|
70222
|
+
}
|
|
70223
|
+
async function fetchCampusVersion(account2) {
|
|
70224
|
+
try {
|
|
70225
|
+
const res = await icFetch(
|
|
70226
|
+
`${account2.baseUrl}/campus/portal/parents/${encodeURIComponent(account2.district)}.jsp`,
|
|
70227
|
+
{},
|
|
70228
|
+
VERSION_TIMEOUT_MS
|
|
70229
|
+
);
|
|
70230
|
+
if (!res.ok) return null;
|
|
70231
|
+
return parseCampusVersion(await res.text());
|
|
70232
|
+
} catch {
|
|
70233
|
+
return null;
|
|
70234
|
+
}
|
|
70235
|
+
}
|
|
69977
70236
|
var SessionExpiredError = class extends Error {
|
|
69978
70237
|
constructor(district) {
|
|
69979
70238
|
super(`Session expired for district '${district}' after re-login retry`);
|
|
@@ -69995,6 +70254,8 @@ var DocumentOriginNotAllowedError = class extends Error {
|
|
|
69995
70254
|
allowedOrigin;
|
|
69996
70255
|
};
|
|
69997
70256
|
var REQUEST_TIMEOUT_MS = 3e4;
|
|
70257
|
+
var VERSION_TIMEOUT_MS = 5e3;
|
|
70258
|
+
var VERSION_RETRY_MS = 5 * 60 * 1e3;
|
|
69998
70259
|
var DOWNLOAD_TIMEOUT_MS = 12e4;
|
|
69999
70260
|
var MAX_DOWNLOAD_BYTES = 50 * 1024 * 1024;
|
|
70000
70261
|
function icFetch(url4, init = {}, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
@@ -70119,12 +70380,19 @@ function registerHealthcheckTools(server, state) {
|
|
|
70119
70380
|
const detail = {
|
|
70120
70381
|
base_url: state.account.baseUrl,
|
|
70121
70382
|
configured_district: state.account.district,
|
|
70122
|
-
auth_source: state.source ?? "unknown"
|
|
70383
|
+
auth_source: state.source ?? "unknown",
|
|
70384
|
+
// Read off the login page, so it needs no session and is reported
|
|
70385
|
+
// even when discovery cannot run. Diagnostic only (#253).
|
|
70386
|
+
campus_version: await state.client.campusVersion(state.account.name)
|
|
70123
70387
|
};
|
|
70124
70388
|
try {
|
|
70125
70389
|
await state.client.ensureDiscovery();
|
|
70126
70390
|
const districts = state.client.listDistricts();
|
|
70127
|
-
detail.districts = districts.map((d) => ({
|
|
70391
|
+
detail.districts = await Promise.all(districts.map(async (d) => ({
|
|
70392
|
+
name: d.name,
|
|
70393
|
+
linked: d.linked,
|
|
70394
|
+
campus_version: await state.client.campusVersion(d.name)
|
|
70395
|
+
})));
|
|
70128
70396
|
const linked = districts.filter((d) => d.linked).map((d) => d.name);
|
|
70129
70397
|
detail.configured_district_is_linked = districts.some(
|
|
70130
70398
|
(d) => d.name === state.account.district && d.linked
|
|
@@ -70189,8 +70457,8 @@ var argsSchema3 = external_exports.object({
|
|
|
70189
70457
|
district: external_exports.string(),
|
|
70190
70458
|
studentId: external_exports.string(),
|
|
70191
70459
|
courseId: external_exports.string().describe("sectionID (optional, from ic_get_schedule). The endpoint supports server-side filtering by sectionID only.").optional(),
|
|
70192
|
-
since:
|
|
70193
|
-
until:
|
|
70460
|
+
since: IsoDate.describe("YYYY-MM-DD; filters dueDate >= since (client-side)").optional(),
|
|
70461
|
+
until: IsoDate.describe("YYYY-MM-DD; filters dueDate <= until (client-side)").optional(),
|
|
70194
70462
|
missingOnly: external_exports.boolean().describe("Only return assignments flagged missing by the teacher").optional()
|
|
70195
70463
|
});
|
|
70196
70464
|
function registerAssignmentTools(server, client) {
|
|
@@ -70277,8 +70545,8 @@ function toArray(value) {
|
|
|
70277
70545
|
var argsSchema5 = external_exports.object({
|
|
70278
70546
|
district: external_exports.string(),
|
|
70279
70547
|
studentId: external_exports.string(),
|
|
70280
|
-
since:
|
|
70281
|
-
until:
|
|
70548
|
+
since: IsoDate.describe("YYYY-MM-DD").optional(),
|
|
70549
|
+
until: IsoDate.describe("YYYY-MM-DD").optional()
|
|
70282
70550
|
});
|
|
70283
70551
|
function inRange(date5, since, until) {
|
|
70284
70552
|
if (typeof date5 !== "string") return true;
|
|
@@ -70349,8 +70617,8 @@ function registerAttendanceTools(server, client) {
|
|
|
70349
70617
|
var argsSchema6 = external_exports.object({
|
|
70350
70618
|
district: external_exports.string(),
|
|
70351
70619
|
studentId: external_exports.string(),
|
|
70352
|
-
since:
|
|
70353
|
-
until:
|
|
70620
|
+
since: IsoDate.describe("YYYY-MM-DD").optional(),
|
|
70621
|
+
until: IsoDate.describe("YYYY-MM-DD").optional()
|
|
70354
70622
|
});
|
|
70355
70623
|
function registerBehaviorTools(server, client) {
|
|
70356
70624
|
server.registerTool("ic_list_behavior", {
|
|
@@ -70380,8 +70648,8 @@ function registerBehaviorTools(server, client) {
|
|
|
70380
70648
|
var argsSchema7 = external_exports.object({
|
|
70381
70649
|
district: external_exports.string(),
|
|
70382
70650
|
studentId: external_exports.string(),
|
|
70383
|
-
since:
|
|
70384
|
-
until:
|
|
70651
|
+
since: IsoDate.describe("YYYY-MM-DD").optional(),
|
|
70652
|
+
until: IsoDate.describe("YYYY-MM-DD").optional()
|
|
70385
70653
|
});
|
|
70386
70654
|
var EMPTY_FOOD = { balance: null, transactions: [] };
|
|
70387
70655
|
function registerFoodServiceTools(server, client) {
|
|
@@ -70417,25 +70685,11 @@ function registerFoodServiceTools(server, client) {
|
|
|
70417
70685
|
}
|
|
70418
70686
|
|
|
70419
70687
|
// node_modules/@chrischall/mcp-utils/dist/html/index.js
|
|
70420
|
-
var NAMED_ENTITIES = {
|
|
70421
|
-
nbsp: " ",
|
|
70422
|
-
amp: "&",
|
|
70423
|
-
lt: "<",
|
|
70424
|
-
gt: ">",
|
|
70425
|
-
quot: '"',
|
|
70426
|
-
apos: "'"
|
|
70427
|
-
};
|
|
70428
70688
|
function extractPlainTextFromHtml(html) {
|
|
70429
70689
|
if (!html)
|
|
70430
70690
|
return "";
|
|
70431
70691
|
let text = stripElementContent(stripElementContent(html, "script"), "style");
|
|
70432
|
-
text = text
|
|
70433
|
-
text = text.replace(/&#(\d+);/g, (whole, d) => codePointOr(Number(d), whole));
|
|
70434
|
-
text = text.replace(/&#x([0-9a-fA-F]+);/g, (whole, h) => codePointOr(parseInt(h, 16), whole));
|
|
70435
|
-
text = text.replace(/&([a-zA-Z]+);/g, (whole, name) => {
|
|
70436
|
-
const decoded = NAMED_ENTITIES[name.toLowerCase()];
|
|
70437
|
-
return decoded ?? whole;
|
|
70438
|
-
});
|
|
70692
|
+
text = decodeHtmlEntities(replaceTags(text, " "));
|
|
70439
70693
|
return text.replace(/\s+/g, " ").trim();
|
|
70440
70694
|
}
|
|
70441
70695
|
function stripElementContent(html, tag) {
|
|
@@ -70637,15 +70891,70 @@ function registerDocumentTools(server, client) {
|
|
|
70637
70891
|
}
|
|
70638
70892
|
|
|
70639
70893
|
// src/tools/calendar.ts
|
|
70894
|
+
function isRouteFailure(e) {
|
|
70895
|
+
return e instanceof PortalUnreachableError || is404(e);
|
|
70896
|
+
}
|
|
70897
|
+
var preferDayRoute = /* @__PURE__ */ new WeakMap();
|
|
70898
|
+
async function fetchDayRoute(client, district, calendarID, route) {
|
|
70899
|
+
if (route === "instructionalDay") {
|
|
70900
|
+
return toArray(await client.request(
|
|
70901
|
+
district,
|
|
70902
|
+
`/campus/resources/calendar/instructionalDay?calendarID=${calendarID}`
|
|
70903
|
+
));
|
|
70904
|
+
}
|
|
70905
|
+
const all = toArray(await client.request(
|
|
70906
|
+
district,
|
|
70907
|
+
`/campus/resources/calendar/day?calendarID=${calendarID}`
|
|
70908
|
+
));
|
|
70909
|
+
return all.filter((d) => d.isInstructionalDay);
|
|
70910
|
+
}
|
|
70911
|
+
async function fetchInstructionalDays(client, district, calendarID) {
|
|
70912
|
+
let preferred = preferDayRoute.get(client);
|
|
70913
|
+
if (!preferred) preferDayRoute.set(client, preferred = /* @__PURE__ */ new Set());
|
|
70914
|
+
const routes = preferred.has(district) ? ["day", "instructionalDay"] : ["instructionalDay", "day"];
|
|
70915
|
+
for (const route of routes) {
|
|
70916
|
+
try {
|
|
70917
|
+
const days = await fetchDayRoute(client, district, calendarID, route);
|
|
70918
|
+
if (route === "day") preferred.add(district);
|
|
70919
|
+
else preferred.delete(district);
|
|
70920
|
+
return days;
|
|
70921
|
+
} catch (e) {
|
|
70922
|
+
if (!isRouteFailure(e)) throw e;
|
|
70923
|
+
}
|
|
70924
|
+
}
|
|
70925
|
+
return null;
|
|
70926
|
+
}
|
|
70927
|
+
async function fetchDayEvents(client, district, personID) {
|
|
70928
|
+
let groups;
|
|
70929
|
+
try {
|
|
70930
|
+
groups = toArray(await client.request(
|
|
70931
|
+
district,
|
|
70932
|
+
`/campus/resources/portal/dayEvent/byEnrollment?personID=${encodeURIComponent(personID)}`
|
|
70933
|
+
));
|
|
70934
|
+
} catch (e) {
|
|
70935
|
+
if (!isRouteFailure(e)) throw e;
|
|
70936
|
+
groups = [];
|
|
70937
|
+
}
|
|
70938
|
+
const byCalendar = /* @__PURE__ */ new Map();
|
|
70939
|
+
for (const ev of groups.flatMap((g) => toArray(g.events))) {
|
|
70940
|
+
let byDate = byCalendar.get(ev.calendarID);
|
|
70941
|
+
if (!byDate) byCalendar.set(ev.calendarID, byDate = /* @__PURE__ */ new Map());
|
|
70942
|
+
byDate.set(ev.date, [...byDate.get(ev.date) ?? [], ev]);
|
|
70943
|
+
}
|
|
70944
|
+
return byCalendar;
|
|
70945
|
+
}
|
|
70946
|
+
function joinLabels(labels) {
|
|
70947
|
+
return [...new Set(labels.filter((l) => !!l))].join("; ");
|
|
70948
|
+
}
|
|
70640
70949
|
var argsSchema8 = external_exports.object({
|
|
70641
70950
|
district: external_exports.string(),
|
|
70642
70951
|
studentId: external_exports.string().describe("Student personID from ic_list_students"),
|
|
70643
|
-
since:
|
|
70644
|
-
until:
|
|
70952
|
+
since: IsoDate.describe("YYYY-MM-DD; include only days on or after this date").optional(),
|
|
70953
|
+
until: IsoDate.describe("YYYY-MM-DD; include only days on or before this date").optional()
|
|
70645
70954
|
});
|
|
70646
70955
|
function registerCalendarTools(server, client) {
|
|
70647
70956
|
server.registerTool("ic_list_school_days", {
|
|
70648
|
-
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
|
|
70957
|
+
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 a day carries comments when the calendar labels it (e.g. 'Early Release Day'). Each enrollment also lists its labelled daysOff (e.g. 'Holiday', 'Teacher Work Day', 'Spring Break'), including breaks that fall between terms. Use since/until to narrow the range. An enrollment whose day list the district won't serve comes back with warning 'SchoolDaysUnavailable' (plus campusVersion when known), its terms and days off, and no school days.",
|
|
70649
70958
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
70650
70959
|
inputSchema: external_exports.object({ ...argsSchema8.shape, view: viewArg() })
|
|
70651
70960
|
}, async (rawArgs) => {
|
|
@@ -70653,18 +70962,18 @@ function registerCalendarTools(server, client) {
|
|
|
70653
70962
|
const student = await findStudent(client, args.district, args.studentId);
|
|
70654
70963
|
if (!student) return studentNotFound(args.studentId);
|
|
70655
70964
|
const result = [];
|
|
70656
|
-
|
|
70657
|
-
|
|
70965
|
+
const enrollments = student.enrollments ?? [];
|
|
70966
|
+
const events = enrollments.length > 0 ? await fetchDayEvents(client, args.district, args.studentId) : /* @__PURE__ */ new Map();
|
|
70967
|
+
for (const enr of enrollments) {
|
|
70968
|
+
const [termsRaw, days] = await Promise.all([
|
|
70658
70969
|
client.request(args.district, `/campus/resources/term?structureID=${enr.structureID}`),
|
|
70659
|
-
client
|
|
70970
|
+
fetchInstructionalDays(client, args.district, enr.calendarID)
|
|
70660
70971
|
]);
|
|
70661
70972
|
const terms = toArray(termsRaw);
|
|
70662
|
-
const
|
|
70663
|
-
const filteredDays = days.filter((d) =>
|
|
70664
|
-
|
|
70665
|
-
|
|
70666
|
-
return true;
|
|
70667
|
-
});
|
|
70973
|
+
const inRange2 = (date5) => !(args.since && date5 < args.since) && !(args.until && date5 > args.until);
|
|
70974
|
+
const filteredDays = (days ?? []).filter((d) => inRange2(d.date));
|
|
70975
|
+
const calendarEvents = events.get(enr.calendarID) ?? /* @__PURE__ */ new Map();
|
|
70976
|
+
const daysOff = [...calendarEvents.entries()].filter(([date5, evs]) => inRange2(date5) && evs.some((e) => e.instruction === false)).map(([date5, evs]) => ({ date: date5, comments: joinLabels(evs.map((e) => e.name)) })).sort((a, b) => a.date.localeCompare(b.date));
|
|
70668
70977
|
const enrollmentTerms = terms.filter((t) => t.structureID === enr.structureID).sort((a, b) => a.seq - b.seq);
|
|
70669
70978
|
const trimmedTerms = enrollmentTerms.map((t) => ({
|
|
70670
70979
|
termID: t.termID,
|
|
@@ -70673,16 +70982,21 @@ function registerCalendarTools(server, client) {
|
|
|
70673
70982
|
endDate: t.endDate,
|
|
70674
70983
|
days: filteredDays.filter((d) => d.date >= t.startDate && d.date <= t.endDate).map((d) => {
|
|
70675
70984
|
const out = { date: d.date, requiresAttendance: d.requiresAttendance };
|
|
70676
|
-
|
|
70985
|
+
const comments = joinLabels([d.comments, ...(calendarEvents.get(d.date) ?? []).map((e) => e.name)]);
|
|
70986
|
+
if (comments) out.comments = comments;
|
|
70677
70987
|
return out;
|
|
70678
70988
|
})
|
|
70679
|
-
})).filter((t) => t.days.length > 0 || !args.since && !args.until);
|
|
70989
|
+
})).filter((t) => days === null ? !(args.since && t.endDate < args.since) && !(args.until && t.startDate > args.until) : t.days.length > 0 || !args.since && !args.until);
|
|
70990
|
+
const campusVersion = days === null ? await client.campusVersion(args.district) : null;
|
|
70680
70991
|
result.push({
|
|
70681
70992
|
enrollmentID: enr.enrollmentID,
|
|
70682
70993
|
calendarID: enr.calendarID,
|
|
70683
70994
|
structureID: enr.structureID,
|
|
70684
70995
|
calendarName: enr.calendarName,
|
|
70685
|
-
|
|
70996
|
+
...days === null ? { warning: "SchoolDaysUnavailable" } : {},
|
|
70997
|
+
...campusVersion ? { campusVersion } : {},
|
|
70998
|
+
terms: trimmedTerms,
|
|
70999
|
+
...daysOff.length > 0 ? { daysOff } : {}
|
|
70686
71000
|
});
|
|
70687
71001
|
}
|
|
70688
71002
|
return viewResponse(rawArgs.view, result);
|
|
@@ -70693,8 +71007,8 @@ function registerCalendarTools(server, client) {
|
|
|
70693
71007
|
var argsSchema9 = external_exports.object({
|
|
70694
71008
|
district: external_exports.string(),
|
|
70695
71009
|
studentId: external_exports.string().describe("Student personID from ic_list_students"),
|
|
70696
|
-
since:
|
|
70697
|
-
until:
|
|
71010
|
+
since: IsoDate.describe("YYYY-MM-DD; include only events on or after this date").optional(),
|
|
71011
|
+
until: IsoDate.describe("YYYY-MM-DD; include only events on or before this date").optional(),
|
|
70698
71012
|
excusedOnly: external_exports.boolean().describe("Only include events with excuse=E").optional()
|
|
70699
71013
|
});
|
|
70700
71014
|
var EVENT_KEYS = [
|
|
@@ -70788,7 +71102,7 @@ function registerAttendanceEventsTools(server, client) {
|
|
|
70788
71102
|
var argsSchema10 = external_exports.object({
|
|
70789
71103
|
district: external_exports.string(),
|
|
70790
71104
|
studentId: external_exports.string(),
|
|
70791
|
-
since:
|
|
71105
|
+
since: IsoDate.describe("YYYY-MM-DD; defaults to 14 days ago. Passed to the endpoint as an ISO timestamp (modifiedDate filter).").optional()
|
|
70792
71106
|
});
|
|
70793
71107
|
var KEYS = [
|
|
70794
71108
|
"assignmentName",
|
|
@@ -70806,10 +71120,8 @@ var KEYS = [
|
|
|
70806
71120
|
"feedback",
|
|
70807
71121
|
"comments"
|
|
70808
71122
|
];
|
|
70809
|
-
function defaultSinceDate(
|
|
70810
|
-
|
|
70811
|
-
d.setUTCDate(d.getUTCDate() - 14);
|
|
70812
|
-
return d.toISOString().substring(0, 10);
|
|
71123
|
+
function defaultSinceDate() {
|
|
71124
|
+
return shiftIsoDate(todayIso(), -14);
|
|
70813
71125
|
}
|
|
70814
71126
|
function registerRecentGradesTools(server, client) {
|
|
70815
71127
|
server.registerTool("ic_list_recent_grades", {
|
|
@@ -70818,7 +71130,7 @@ function registerRecentGradesTools(server, client) {
|
|
|
70818
71130
|
inputSchema: external_exports.object({ ...argsSchema10.shape, view: viewArg() })
|
|
70819
71131
|
}, async (rawArgs) => {
|
|
70820
71132
|
const args = argsSchema10.parse(rawArgs);
|
|
70821
|
-
const sinceDate = args.since ?? defaultSinceDate(
|
|
71133
|
+
const sinceDate = args.since ?? defaultSinceDate();
|
|
70822
71134
|
const modifiedDate = `${sinceDate}T00:00:00`;
|
|
70823
71135
|
const raw = await client.request(
|
|
70824
71136
|
args.district,
|
|
@@ -71034,7 +71346,7 @@ try {
|
|
|
71034
71346
|
}
|
|
71035
71347
|
var COMMON = {
|
|
71036
71348
|
name: "infinitecampus",
|
|
71037
|
-
version: "3.1
|
|
71349
|
+
version: "3.2.1"
|
|
71038
71350
|
// x-release-please-version
|
|
71039
71351
|
};
|
|
71040
71352
|
var healthState = { account, source, configError, client: null };
|