@chrischall/pickuppatrol-mcp 1.2.1 → 1.2.2
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/dist/auth.js +6 -3
- package/dist/bundle.js +152 -14
- package/dist/client.js +4 -2
- package/dist/tools/plans.js +4 -4
- package/dist/tools/school.js +3 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
- package/server.json +2 -2
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "PickUp Patrol school-dismissal tools for Claude Code",
|
|
9
|
-
"version": "1.2.
|
|
9
|
+
"version": "1.2.2"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"displayName": "PickUp Patrol",
|
|
15
15
|
"source": "./",
|
|
16
16
|
"description": "Read and change your children's school dismissal plans in PickUp Patrol — defaults, day-by-day changes and school cutoff times — via MCP",
|
|
17
|
-
"version": "1.2.
|
|
17
|
+
"version": "1.2.2",
|
|
18
18
|
"author": {
|
|
19
19
|
"name": "Chris Chall"
|
|
20
20
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pickuppatrol",
|
|
3
3
|
"displayName": "PickUp Patrol",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.2",
|
|
5
5
|
"description": "Read and change your children's school dismissal plans in PickUp Patrol — defaults, day-by-day changes and school cutoff times — via MCP",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Chris Chall"
|
package/dist/auth.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readEnvVar, McpToolError, CookieJar, EdgeBlockedError, detectEdgeBlock, } from '@chrischall/mcp-utils';
|
|
1
|
+
import { readEnvVar, McpToolError, CookieJar, EdgeBlockedError, detectEdgeBlock, withAmbientCancellation, } from '@chrischall/mcp-utils';
|
|
2
2
|
export const BASE_URL = 'https://app.pickuppatrol.net';
|
|
3
3
|
export const BASE_PATH = '/api/json/reply';
|
|
4
4
|
/** Upper bound on any one request to PickUp Patrol, sign-in included. */
|
|
@@ -215,7 +215,10 @@ export class PickUpPatrolAuth {
|
|
|
215
215
|
// sign-in would otherwise stall every tool — the healthcheck included —
|
|
216
216
|
// for as long as undici's own ~300s default. The signal also covers the
|
|
217
217
|
// body read below.
|
|
218
|
-
|
|
218
|
+
// The running call's cancellation is folded in too, so a cancelled call
|
|
219
|
+
// does not leave the shared sign-in running for the full deadline.
|
|
220
|
+
const deadline = AbortSignal.timeout(this.timeoutMs);
|
|
221
|
+
const signal = withAmbientCancellation(deadline);
|
|
219
222
|
let res;
|
|
220
223
|
let text;
|
|
221
224
|
try {
|
|
@@ -240,7 +243,7 @@ export class PickUpPatrolAuth {
|
|
|
240
243
|
catch (err) {
|
|
241
244
|
// Transient: a timeout says nothing about the credentials, so it is
|
|
242
245
|
// never cached as permanentError and the next call signs in afresh.
|
|
243
|
-
if (
|
|
246
|
+
if (deadline.aborted) {
|
|
244
247
|
throw new McpToolError(`PickUp Patrol did not answer the sign-in within ${this.timeoutMs / 1000}s`, { hint: 'The service may be slow or down. Try again shortly.' });
|
|
245
248
|
}
|
|
246
249
|
throw err;
|
package/dist/bundle.js
CHANGED
|
@@ -84,6 +84,7 @@ var require_util = __commonJS({
|
|
|
84
84
|
exports.explicitlyAborted = explicitlyAborted2;
|
|
85
85
|
exports.prefixIssues = prefixIssues2;
|
|
86
86
|
exports.unwrapMessage = unwrapMessage2;
|
|
87
|
+
exports.sizeCaps = sizeCaps2;
|
|
87
88
|
exports.attachSchema = attachSchema2;
|
|
88
89
|
exports.finalizeIssue = finalizeIssue2;
|
|
89
90
|
exports.getSizableOrigin = getSizableOrigin2;
|
|
@@ -618,6 +619,18 @@ var require_util = __commonJS({
|
|
|
618
619
|
function unwrapMessage2(message) {
|
|
619
620
|
return typeof message === "string" ? message : message?.message;
|
|
620
621
|
}
|
|
622
|
+
function sizeCaps2(defChecks) {
|
|
623
|
+
const caps = [];
|
|
624
|
+
for (const ch of defChecks ?? []) {
|
|
625
|
+
const d = ch._zod.def;
|
|
626
|
+
if (!/_(length|size)$|_equals$/.test(d.check))
|
|
627
|
+
break;
|
|
628
|
+
const max = d.maximum ?? d.length ?? d.size;
|
|
629
|
+
if (max >= 0)
|
|
630
|
+
caps.push([max, ch]);
|
|
631
|
+
}
|
|
632
|
+
return caps;
|
|
633
|
+
}
|
|
621
634
|
function attachSchema2(issues, start, inst) {
|
|
622
635
|
var _a3;
|
|
623
636
|
for (let i = start; i < issues.length; i++) {
|
|
@@ -2282,7 +2295,7 @@ var require_versions = __commonJS({
|
|
|
2282
2295
|
exports.version = {
|
|
2283
2296
|
major: 4,
|
|
2284
2297
|
minor: 6,
|
|
2285
|
-
patch:
|
|
2298
|
+
patch: 7
|
|
2286
2299
|
};
|
|
2287
2300
|
(function() {
|
|
2288
2301
|
var keys = Object.getOwnPropertyNames(exports);
|
|
@@ -3116,6 +3129,31 @@ var require_schemas = __commonJS({
|
|
|
3116
3129
|
return payload;
|
|
3117
3130
|
};
|
|
3118
3131
|
});
|
|
3132
|
+
function capSize2(inst, size) {
|
|
3133
|
+
const caps = util.sizeCaps(inst._zod.def.checks);
|
|
3134
|
+
if (!caps.length)
|
|
3135
|
+
return;
|
|
3136
|
+
const cap = Math.min(...caps.map((c) => c[0]));
|
|
3137
|
+
const parse3 = inst._zod.parse;
|
|
3138
|
+
inst._zod.parse = (payload, ctx) => {
|
|
3139
|
+
const n = size(payload.value);
|
|
3140
|
+
if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
|
|
3141
|
+
for (const [max, ch] of util.sizeCaps(inst._zod.def.checks)) {
|
|
3142
|
+
if (n > max && ch._zod.def.when(payload)) {
|
|
3143
|
+
const start = payload.issues.length;
|
|
3144
|
+
ch._zod.check(payload);
|
|
3145
|
+
payload.issues[start].continue = false;
|
|
3146
|
+
util.attachSchema(payload.issues, start, inst);
|
|
3147
|
+
return payload;
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
return parse3(payload, ctx);
|
|
3152
|
+
};
|
|
3153
|
+
}
|
|
3154
|
+
var arraySize2 = (input2) => Array.isArray(input2) ? input2.length : -1;
|
|
3155
|
+
var mapSize2 = (input2) => input2 instanceof Map ? input2.size : -1;
|
|
3156
|
+
var setSize2 = (input2) => input2 instanceof Set ? input2.size : -1;
|
|
3119
3157
|
function handleArrayResult2(result, final, index) {
|
|
3120
3158
|
if (result.issues.length) {
|
|
3121
3159
|
final.issues.push(...util.prefixIssues(index, result.issues));
|
|
@@ -3159,6 +3197,7 @@ var require_schemas = __commonJS({
|
|
|
3159
3197
|
}
|
|
3160
3198
|
return payload;
|
|
3161
3199
|
};
|
|
3200
|
+
capSize2(inst, arraySize2);
|
|
3162
3201
|
});
|
|
3163
3202
|
function handlePropertyResult2(result, final, key, input2, optin, optout) {
|
|
3164
3203
|
const isPresent = key in input2;
|
|
@@ -4115,6 +4154,7 @@ var require_schemas = __commonJS({
|
|
|
4115
4154
|
return Promise.all(proms).then(() => payload);
|
|
4116
4155
|
return payload;
|
|
4117
4156
|
};
|
|
4157
|
+
capSize2(inst, mapSize2);
|
|
4118
4158
|
});
|
|
4119
4159
|
function handleMapResult2(keyResult, valueResult, final, key, input2, inst, ctx) {
|
|
4120
4160
|
if (keyResult.issues.length) {
|
|
@@ -4181,6 +4221,7 @@ var require_schemas = __commonJS({
|
|
|
4181
4221
|
return Promise.all(proms).then(() => payload);
|
|
4182
4222
|
return payload;
|
|
4183
4223
|
};
|
|
4224
|
+
capSize2(inst, setSize2);
|
|
4184
4225
|
});
|
|
4185
4226
|
function handleSetResult2(result, final) {
|
|
4186
4227
|
if (result.issues.length) {
|
|
@@ -16285,9 +16326,15 @@ ${code2}
|
|
|
16285
16326
|
doc.write(`}`);
|
|
16286
16327
|
return outputVar;
|
|
16287
16328
|
}
|
|
16329
|
+
function generateSizeGate2(doc, schema, size) {
|
|
16330
|
+
for (const [max, check2] of util.sizeCaps(schema._zod.def.checks)) {
|
|
16331
|
+
doc.write(`if (${size} > ${numericOperand2(max, check2._zod.def.check)}) return INVALID;`);
|
|
16332
|
+
}
|
|
16333
|
+
}
|
|
16288
16334
|
function generateArrayCheck2(doc, ctx, schema, accessor, buildsValue = true) {
|
|
16289
16335
|
const def = schema._zod.def;
|
|
16290
16336
|
doc.write(`if (!Array.isArray(${accessor})) return INVALID;`);
|
|
16337
|
+
generateSizeGate2(doc, schema, `${accessor}.length`);
|
|
16291
16338
|
const outputVar = buildsValue ? newVar2(ctx) : null;
|
|
16292
16339
|
const iVar = newVar2(ctx);
|
|
16293
16340
|
const elemVar = newVar2(ctx);
|
|
@@ -16687,6 +16734,7 @@ ${code2}
|
|
|
16687
16734
|
function generateMapCheck2(doc, ctx, schema, accessor) {
|
|
16688
16735
|
const def = schema._zod.def;
|
|
16689
16736
|
doc.write(`if (!(${accessor} instanceof Map)) return INVALID;`);
|
|
16737
|
+
generateSizeGate2(doc, schema, `${accessor}.size`);
|
|
16690
16738
|
const outputVar = newVar2(ctx);
|
|
16691
16739
|
const kVar = newVar2(ctx);
|
|
16692
16740
|
const valVar = newVar2(ctx);
|
|
@@ -16703,6 +16751,7 @@ ${code2}
|
|
|
16703
16751
|
function generateSetCheck2(doc, ctx, schema, accessor) {
|
|
16704
16752
|
const def = schema._zod.def;
|
|
16705
16753
|
doc.write(`if (!(${accessor} instanceof Set)) return INVALID;`);
|
|
16754
|
+
generateSizeGate2(doc, schema, `${accessor}.size`);
|
|
16706
16755
|
const outputVar = newVar2(ctx);
|
|
16707
16756
|
const valVar = newVar2(ctx);
|
|
16708
16757
|
doc.write(`const ${outputVar} = new Set();`);
|
|
@@ -23308,6 +23357,17 @@ var storage = new AsyncLocalStorage();
|
|
|
23308
23357
|
function withCallSignal(signal, fn, request) {
|
|
23309
23358
|
return signal ? storage.run({ signal, ...request ? { request } : {} }, fn) : fn();
|
|
23310
23359
|
}
|
|
23360
|
+
function currentCallSignal() {
|
|
23361
|
+
return storage.getStore()?.signal;
|
|
23362
|
+
}
|
|
23363
|
+
function withAmbientCancellation(own2) {
|
|
23364
|
+
const ambient = currentCallSignal();
|
|
23365
|
+
if (!ambient)
|
|
23366
|
+
return own2;
|
|
23367
|
+
if (!own2)
|
|
23368
|
+
return ambient;
|
|
23369
|
+
return AbortSignal.any([own2, ambient]);
|
|
23370
|
+
}
|
|
23311
23371
|
|
|
23312
23372
|
// node_modules/@chrischall/mcp-utils/dist/caller/index.js
|
|
23313
23373
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
@@ -23400,7 +23460,7 @@ function declaredDialect(schema, remedy) {
|
|
|
23400
23460
|
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}`);
|
|
23401
23461
|
}
|
|
23402
23462
|
|
|
23403
|
-
// node_modules/@modelcontextprotocol/core/dist/auth-BNDyLTqp.mjs
|
|
23463
|
+
// node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/dist/auth-BNDyLTqp.mjs
|
|
23404
23464
|
var z = __toESM(require_v4(), 1);
|
|
23405
23465
|
var LATEST_PROTOCOL_VERSION = "2025-11-25";
|
|
23406
23466
|
var SUPPORTED_PROTOCOL_VERSIONS = [
|
|
@@ -38224,7 +38284,7 @@ var API_KEY_RE = new RegExp([
|
|
|
38224
38284
|
// webhook signing secret (Stripe-style)
|
|
38225
38285
|
].map((p) => `\\b${p}`).join("|"), "g");
|
|
38226
38286
|
var GOOGLE_OAUTH_TOKEN_RE = /(?<![A-Za-z0-9+/])(?:ya29\.|1\/\/)[A-Za-z0-9._-]{8,}/g;
|
|
38227
|
-
var QUERY_SECRET_RE = new RegExp(`([
|
|
38287
|
+
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");
|
|
38228
38288
|
var OAUTH_CODE_RE = /([?&]code=)(?=[^&#\s"'<>`]{16,})[^&#\s"'<>`]+/gi;
|
|
38229
38289
|
var FORM_PASSWORD_RE = /((?:^|[\s,;:"'(\[{])(?:password|passwd)=)[^&#\s"'<>`]+/gim;
|
|
38230
38290
|
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");
|
|
@@ -38235,6 +38295,8 @@ var JSON_SECRET_KEYS = [
|
|
|
38235
38295
|
"api[_-]?secret",
|
|
38236
38296
|
"(?:x[_-])?api[_-]?key",
|
|
38237
38297
|
"private[_-]?key",
|
|
38298
|
+
"aws[_-]?secret[_-]?access[_-]?key",
|
|
38299
|
+
// fleet-audit#1297
|
|
38238
38300
|
"code[_-]?verifier",
|
|
38239
38301
|
// PKCE; a bare `verifier` key is too generic for JSON
|
|
38240
38302
|
`x[_-]${HEADER_NAME_RUN}?(?:api[_-]?key|token|secret|auth)${HEADER_NAME_RUN}`,
|
|
@@ -38932,6 +38994,7 @@ __export(util_exports, {
|
|
|
38932
38994
|
required: () => required,
|
|
38933
38995
|
safeExtend: () => safeExtend,
|
|
38934
38996
|
shallowClone: () => shallowClone,
|
|
38997
|
+
sizeCaps: () => sizeCaps,
|
|
38935
38998
|
slugify: () => slugify,
|
|
38936
38999
|
stringifyPrimitive: () => stringifyPrimitive,
|
|
38937
39000
|
toZod: () => toZod,
|
|
@@ -39451,6 +39514,18 @@ function prefixIssues(path, issues) {
|
|
|
39451
39514
|
function unwrapMessage(message) {
|
|
39452
39515
|
return typeof message === "string" ? message : message?.message;
|
|
39453
39516
|
}
|
|
39517
|
+
function sizeCaps(defChecks) {
|
|
39518
|
+
const caps = [];
|
|
39519
|
+
for (const ch of defChecks ?? []) {
|
|
39520
|
+
const d = ch._zod.def;
|
|
39521
|
+
if (!/_(length|size)$|_equals$/.test(d.check))
|
|
39522
|
+
break;
|
|
39523
|
+
const max = d.maximum ?? d.length ?? d.size;
|
|
39524
|
+
if (max >= 0)
|
|
39525
|
+
caps.push([max, ch]);
|
|
39526
|
+
}
|
|
39527
|
+
return caps;
|
|
39528
|
+
}
|
|
39454
39529
|
function attachSchema(issues, start, inst) {
|
|
39455
39530
|
var _a3;
|
|
39456
39531
|
for (let i = start; i < issues.length; i++) {
|
|
@@ -40871,7 +40946,7 @@ ${content.join("\n")}
|
|
|
40871
40946
|
var version = {
|
|
40872
40947
|
major: 4,
|
|
40873
40948
|
minor: 6,
|
|
40874
|
-
patch:
|
|
40949
|
+
patch: 7
|
|
40875
40950
|
};
|
|
40876
40951
|
|
|
40877
40952
|
// node_modules/zod/v4/core/schemas.js
|
|
@@ -41627,6 +41702,31 @@ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
|
|
|
41627
41702
|
return payload;
|
|
41628
41703
|
};
|
|
41629
41704
|
});
|
|
41705
|
+
function capSize(inst, size) {
|
|
41706
|
+
const caps = sizeCaps(inst._zod.def.checks);
|
|
41707
|
+
if (!caps.length)
|
|
41708
|
+
return;
|
|
41709
|
+
const cap = Math.min(...caps.map((c) => c[0]));
|
|
41710
|
+
const parse3 = inst._zod.parse;
|
|
41711
|
+
inst._zod.parse = (payload, ctx) => {
|
|
41712
|
+
const n = size(payload.value);
|
|
41713
|
+
if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
|
|
41714
|
+
for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
|
|
41715
|
+
if (n > max && ch._zod.def.when(payload)) {
|
|
41716
|
+
const start = payload.issues.length;
|
|
41717
|
+
ch._zod.check(payload);
|
|
41718
|
+
payload.issues[start].continue = false;
|
|
41719
|
+
attachSchema(payload.issues, start, inst);
|
|
41720
|
+
return payload;
|
|
41721
|
+
}
|
|
41722
|
+
}
|
|
41723
|
+
}
|
|
41724
|
+
return parse3(payload, ctx);
|
|
41725
|
+
};
|
|
41726
|
+
}
|
|
41727
|
+
var arraySize = (input2) => Array.isArray(input2) ? input2.length : -1;
|
|
41728
|
+
var mapSize = (input2) => input2 instanceof Map ? input2.size : -1;
|
|
41729
|
+
var setSize = (input2) => input2 instanceof Set ? input2.size : -1;
|
|
41630
41730
|
function handleArrayResult(result, final, index) {
|
|
41631
41731
|
if (result.issues.length) {
|
|
41632
41732
|
final.issues.push(...prefixIssues(index, result.issues));
|
|
@@ -41670,6 +41770,7 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
|
|
|
41670
41770
|
}
|
|
41671
41771
|
return payload;
|
|
41672
41772
|
};
|
|
41773
|
+
capSize(inst, arraySize);
|
|
41673
41774
|
});
|
|
41674
41775
|
function handlePropertyResult(result, final, key, input2, optin, optout) {
|
|
41675
41776
|
const isPresent = key in input2;
|
|
@@ -42626,6 +42727,7 @@ var $ZodMap = /* @__PURE__ */ $constructor("$ZodMap", (inst, def) => {
|
|
|
42626
42727
|
return Promise.all(proms).then(() => payload);
|
|
42627
42728
|
return payload;
|
|
42628
42729
|
};
|
|
42730
|
+
capSize(inst, mapSize);
|
|
42629
42731
|
});
|
|
42630
42732
|
function handleMapResult(keyResult, valueResult, final, key, input2, inst, ctx) {
|
|
42631
42733
|
if (keyResult.issues.length) {
|
|
@@ -42692,6 +42794,7 @@ var $ZodSet = /* @__PURE__ */ $constructor("$ZodSet", (inst, def) => {
|
|
|
42692
42794
|
return Promise.all(proms).then(() => payload);
|
|
42693
42795
|
return payload;
|
|
42694
42796
|
};
|
|
42797
|
+
capSize(inst, setSize);
|
|
42695
42798
|
});
|
|
42696
42799
|
function handleSetResult(result, final) {
|
|
42697
42800
|
if (result.issues.length) {
|
|
@@ -52222,9 +52325,15 @@ function generateNullableCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
|
52222
52325
|
doc.write(`}`);
|
|
52223
52326
|
return outputVar;
|
|
52224
52327
|
}
|
|
52328
|
+
function generateSizeGate(doc, schema, size) {
|
|
52329
|
+
for (const [max, check2] of sizeCaps(schema._zod.def.checks)) {
|
|
52330
|
+
doc.write(`if (${size} > ${numericOperand(max, check2._zod.def.check)}) return INVALID;`);
|
|
52331
|
+
}
|
|
52332
|
+
}
|
|
52225
52333
|
function generateArrayCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
52226
52334
|
const def = schema._zod.def;
|
|
52227
52335
|
doc.write(`if (!Array.isArray(${accessor})) return INVALID;`);
|
|
52336
|
+
generateSizeGate(doc, schema, `${accessor}.length`);
|
|
52228
52337
|
const outputVar = buildsValue ? newVar(ctx) : null;
|
|
52229
52338
|
const iVar = newVar(ctx);
|
|
52230
52339
|
const elemVar = newVar(ctx);
|
|
@@ -52624,6 +52733,7 @@ function literalPropertyKey(ctx, key) {
|
|
|
52624
52733
|
function generateMapCheck(doc, ctx, schema, accessor) {
|
|
52625
52734
|
const def = schema._zod.def;
|
|
52626
52735
|
doc.write(`if (!(${accessor} instanceof Map)) return INVALID;`);
|
|
52736
|
+
generateSizeGate(doc, schema, `${accessor}.size`);
|
|
52627
52737
|
const outputVar = newVar(ctx);
|
|
52628
52738
|
const kVar = newVar(ctx);
|
|
52629
52739
|
const valVar = newVar(ctx);
|
|
@@ -52640,6 +52750,7 @@ function generateMapCheck(doc, ctx, schema, accessor) {
|
|
|
52640
52750
|
function generateSetCheck(doc, ctx, schema, accessor) {
|
|
52641
52751
|
const def = schema._zod.def;
|
|
52642
52752
|
doc.write(`if (!(${accessor} instanceof Set)) return INVALID;`);
|
|
52753
|
+
generateSizeGate(doc, schema, `${accessor}.size`);
|
|
52643
52754
|
const outputVar = newVar(ctx);
|
|
52644
52755
|
const valVar = newVar(ctx);
|
|
52645
52756
|
doc.write(`const ${outputVar} = new Set();`);
|
|
@@ -58830,10 +58941,34 @@ import { constants as fsConstants2, realpathSync } from "node:fs";
|
|
|
58830
58941
|
var O_NOFOLLOW2 = fsConstants2.O_NOFOLLOW ?? 0;
|
|
58831
58942
|
var O_NONBLOCK = fsConstants2.O_NONBLOCK ?? 0;
|
|
58832
58943
|
|
|
58944
|
+
// node_modules/@chrischall/mcp-utils/dist/internal/ascii.js
|
|
58945
|
+
function asciiLower(s) {
|
|
58946
|
+
return s.replace(/[A-Z]+/g, (m) => m.toLowerCase());
|
|
58947
|
+
}
|
|
58948
|
+
|
|
58833
58949
|
// node_modules/@chrischall/mcp-utils/dist/scrape/index.js
|
|
58834
58950
|
var NEXT_DATA_MAX_CHARS = 16 * 1024 * 1024;
|
|
58835
58951
|
function isCloudflareChallenge(html) {
|
|
58836
|
-
return
|
|
58952
|
+
return html.includes("_cf_chl_opt") || hasJustAMomentTitle(html);
|
|
58953
|
+
}
|
|
58954
|
+
var JUST_A_MOMENT = "just a moment";
|
|
58955
|
+
function hasJustAMomentTitle(html) {
|
|
58956
|
+
const lower = asciiLower(html);
|
|
58957
|
+
let i = 0;
|
|
58958
|
+
for (; ; ) {
|
|
58959
|
+
const open2 = lower.indexOf("<title", i);
|
|
58960
|
+
if (open2 < 0)
|
|
58961
|
+
return false;
|
|
58962
|
+
const gt = lower.indexOf(">", open2 + 6);
|
|
58963
|
+
if (gt < 0)
|
|
58964
|
+
return false;
|
|
58965
|
+
let j = gt + 1;
|
|
58966
|
+
while (j < lower.length && /\s/.test(lower[j]))
|
|
58967
|
+
j++;
|
|
58968
|
+
if (lower.startsWith(JUST_A_MOMENT, j))
|
|
58969
|
+
return true;
|
|
58970
|
+
i = gt + 1;
|
|
58971
|
+
}
|
|
58837
58972
|
}
|
|
58838
58973
|
|
|
58839
58974
|
// node_modules/@chrischall/mcp-utils/dist/http/index.js
|
|
@@ -59184,7 +59319,8 @@ var PickUpPatrolAuth = class {
|
|
|
59184
59319
|
}
|
|
59185
59320
|
}
|
|
59186
59321
|
async login() {
|
|
59187
|
-
const
|
|
59322
|
+
const deadline = AbortSignal.timeout(this.timeoutMs);
|
|
59323
|
+
const signal = withAmbientCancellation(deadline);
|
|
59188
59324
|
let res;
|
|
59189
59325
|
let text;
|
|
59190
59326
|
try {
|
|
@@ -59205,7 +59341,7 @@ var PickUpPatrolAuth = class {
|
|
|
59205
59341
|
return "";
|
|
59206
59342
|
});
|
|
59207
59343
|
} catch (err) {
|
|
59208
|
-
if (
|
|
59344
|
+
if (deadline.aborted) {
|
|
59209
59345
|
throw new McpToolError(
|
|
59210
59346
|
`PickUp Patrol did not answer the sign-in within ${this.timeoutMs / 1e3}s`,
|
|
59211
59347
|
{ hint: "The service may be slow or down. Try again shortly." }
|
|
@@ -59286,7 +59422,9 @@ var PickUpPatrolClient = class {
|
|
|
59286
59422
|
method,
|
|
59287
59423
|
headers: this.headers(session),
|
|
59288
59424
|
body: method === "GET" || args === void 0 ? void 0 : JSON.stringify(args),
|
|
59289
|
-
|
|
59425
|
+
// Deadline plus the running call's cancellation: a call the client gave
|
|
59426
|
+
// up on (e.g. a multi-date verify loop) stops issuing requests.
|
|
59427
|
+
signal: withAmbientCancellation(AbortSignal.timeout(REQUEST_TIMEOUT_MS))
|
|
59290
59428
|
})
|
|
59291
59429
|
);
|
|
59292
59430
|
return this.parse(res, method, dto);
|
|
@@ -59413,7 +59551,7 @@ var PickUpPatrolClient = class {
|
|
|
59413
59551
|
var client = new PickUpPatrolClient();
|
|
59414
59552
|
|
|
59415
59553
|
// src/version.ts
|
|
59416
|
-
var VERSION = "1.2.
|
|
59554
|
+
var VERSION = "1.2.2";
|
|
59417
59555
|
|
|
59418
59556
|
// node_modules/@chrischall/mcp-utils/dist/internal/edge-block.js
|
|
59419
59557
|
function objectField(value) {
|
|
@@ -59830,8 +59968,8 @@ function registerSchoolTools(server, client2) {
|
|
|
59830
59968
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
59831
59969
|
inputSchema: external_exports.object({
|
|
59832
59970
|
school_id: external_exports.number().int().describe("School id, from pup_list_students"),
|
|
59833
|
-
start_date:
|
|
59834
|
-
end_date:
|
|
59971
|
+
start_date: IsoDate.optional().describe("YYYY-MM-DD; with end_date, also return dates that differ from the default"),
|
|
59972
|
+
end_date: IsoDate.optional().describe("YYYY-MM-DD")
|
|
59835
59973
|
})
|
|
59836
59974
|
},
|
|
59837
59975
|
async ({ school_id, start_date, end_date }) => {
|
|
@@ -60087,8 +60225,8 @@ function registerPlanTools(server, client2) {
|
|
|
60087
60225
|
description: `Day-by-day dismissal plans across a date range for every student on the account: the option in force, its note, and the weekly default it overrides. Pass raw: true for the untouched API records. ${UNTRUSTED_DESCRIPTION_SUFFIX}`,
|
|
60088
60226
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
60089
60227
|
inputSchema: external_exports.object({
|
|
60090
|
-
start_date:
|
|
60091
|
-
end_date:
|
|
60228
|
+
start_date: IsoDate.describe("YYYY-MM-DD"),
|
|
60229
|
+
end_date: IsoDate.describe("YYYY-MM-DD"),
|
|
60092
60230
|
raw: rawParam
|
|
60093
60231
|
})
|
|
60094
60232
|
},
|
|
@@ -60107,7 +60245,7 @@ function registerPlanTools(server, client2) {
|
|
|
60107
60245
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
60108
60246
|
inputSchema: external_exports.object({
|
|
60109
60247
|
student_id: external_exports.number().int().describe("Student id, from pup_list_students"),
|
|
60110
|
-
date:
|
|
60248
|
+
date: IsoDate.describe("YYYY-MM-DD"),
|
|
60111
60249
|
raw: rawParam
|
|
60112
60250
|
})
|
|
60113
60251
|
},
|
package/dist/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { dirname, join } from 'path';
|
|
2
2
|
import { fileURLToPath } from 'url';
|
|
3
|
-
import { loadDotenvSafely, McpToolError, buildQueryString, EdgeBlockedError, detectEdgeBlock, } from '@chrischall/mcp-utils';
|
|
3
|
+
import { loadDotenvSafely, McpToolError, buildQueryString, EdgeBlockedError, detectEdgeBlock, withAmbientCancellation, } from '@chrischall/mcp-utils';
|
|
4
4
|
import { PickUpPatrolAuth, BASE_URL, BASE_PATH, REQUEST_TIMEOUT_MS, SERVICE, describeResponseStatus, } from './auth.js';
|
|
5
5
|
// Load .env for local dev; silently skip when dotenv is unavailable (the mcpb
|
|
6
6
|
// bundle externalises it). The try/catch guards a runtime where
|
|
@@ -45,7 +45,9 @@ export class PickUpPatrolClient {
|
|
|
45
45
|
method,
|
|
46
46
|
headers: this.headers(session),
|
|
47
47
|
body: method === 'GET' || args === undefined ? undefined : JSON.stringify(args),
|
|
48
|
-
|
|
48
|
+
// Deadline plus the running call's cancellation: a call the client gave
|
|
49
|
+
// up on (e.g. a multi-date verify loop) stops issuing requests.
|
|
50
|
+
signal: withAmbientCancellation(AbortSignal.timeout(REQUEST_TIMEOUT_MS)),
|
|
49
51
|
}));
|
|
50
52
|
return this.parse(res, method, dto);
|
|
51
53
|
}
|
package/dist/tools/plans.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { CONFIRM_FLOW_SENTENCE, confirmTokenParam, confirmWrite, McpToolError, minifiedResult, UNTRUSTED_DESCRIPTION_SUFFIX, untrustedResult, } from '@chrischall/mcp-utils';
|
|
2
|
+
import { CONFIRM_FLOW_SENTENCE, confirmTokenParam, confirmWrite, IsoDate, McpToolError, minifiedResult, UNTRUSTED_DESCRIPTION_SUFFIX, untrustedResult, } from '@chrischall/mcp-utils';
|
|
3
3
|
import { BASE_PATH } from '../auth.js';
|
|
4
4
|
import { buildPlanUpdates } from '../plans.js';
|
|
5
5
|
import { weekdayOf } from '../dates.js';
|
|
@@ -142,8 +142,8 @@ export function registerPlanTools(server, client) {
|
|
|
142
142
|
description: `Day-by-day dismissal plans across a date range for every student on the account: the option in force, its note, and the weekly default it overrides. Pass raw: true for the untouched API records. ${UNTRUSTED_DESCRIPTION_SUFFIX}`,
|
|
143
143
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
144
144
|
inputSchema: z.object({
|
|
145
|
-
start_date:
|
|
146
|
-
end_date:
|
|
145
|
+
start_date: IsoDate.describe('YYYY-MM-DD'),
|
|
146
|
+
end_date: IsoDate.describe('YYYY-MM-DD'),
|
|
147
147
|
raw: rawParam,
|
|
148
148
|
}),
|
|
149
149
|
}, async ({ start_date, end_date, raw }) => {
|
|
@@ -155,7 +155,7 @@ export function registerPlanTools(server, client) {
|
|
|
155
155
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
156
156
|
inputSchema: z.object({
|
|
157
157
|
student_id: z.number().int().describe('Student id, from pup_list_students'),
|
|
158
|
-
date:
|
|
158
|
+
date: IsoDate.describe('YYYY-MM-DD'),
|
|
159
159
|
raw: rawParam,
|
|
160
160
|
}),
|
|
161
161
|
}, async ({ student_id, date, raw }) => {
|
package/dist/tools/school.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { minifiedResult, UNTRUSTED_DESCRIPTION_SUFFIX, untrustedResult } from '@chrischall/mcp-utils';
|
|
2
|
+
import { IsoDate, minifiedResult, UNTRUSTED_DESCRIPTION_SUFFIX, untrustedResult } from '@chrischall/mcp-utils';
|
|
3
3
|
import { WEEKDAY_NAMES } from '../dates.js';
|
|
4
4
|
import { PUP_UNTRUSTED } from './untrusted.js';
|
|
5
5
|
/**
|
|
@@ -109,11 +109,10 @@ export function registerSchoolTools(server, client) {
|
|
|
109
109
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
110
110
|
inputSchema: z.object({
|
|
111
111
|
school_id: z.number().int().describe('School id, from pup_list_students'),
|
|
112
|
-
start_date:
|
|
113
|
-
.string()
|
|
112
|
+
start_date: IsoDate
|
|
114
113
|
.optional()
|
|
115
114
|
.describe('YYYY-MM-DD; with end_date, also return dates that differ from the default'),
|
|
116
|
-
end_date:
|
|
115
|
+
end_date: IsoDate.optional().describe('YYYY-MM-DD'),
|
|
117
116
|
}),
|
|
118
117
|
}, async ({ school_id, start_date, end_date }) => {
|
|
119
118
|
const invalidDates = await client.getInvalidPlanDates(school_id);
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrischall/pickuppatrol-mcp",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"mcpName": "io.github.chrischall/pickuppatrol-mcp",
|
|
6
6
|
"description": "PickUp Patrol MCP server for Claude — developed and maintained by AI (Claude Code)",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"test:watch": "vitest"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@chrischall/mcp-utils": "^3.0.
|
|
60
|
+
"@chrischall/mcp-utils": "^3.0.3",
|
|
61
61
|
"@modelcontextprotocol/server": "^2.3.0",
|
|
62
62
|
"dotenv": "^18.0.2",
|
|
63
63
|
"zod": "^4.6.5"
|
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/chrischall/pickuppatrol-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "1.2.
|
|
9
|
+
"version": "1.2.2",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@chrischall/pickuppatrol-mcp",
|
|
14
|
-
"version": "1.2.
|
|
14
|
+
"version": "1.2.2",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|