@chrischall/pickuppatrol-mcp 0.2.0 → 1.0.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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/bundle.js +55967 -29612
- package/dist/tools/_confirm.d.ts +1 -1
- package/dist/tools/account.d.ts +1 -1
- package/dist/tools/account.js +2 -2
- package/dist/tools/defaults.d.ts +1 -1
- package/dist/tools/defaults.js +6 -6
- package/dist/tools/plans.d.ts +1 -1
- package/dist/tools/plans.js +6 -6
- package/dist/tools/school.d.ts +1 -1
- package/dist/tools/school.js +8 -8
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -7
- package/server.json +2 -2
package/dist/tools/_confirm.d.ts
CHANGED
package/dist/tools/account.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/server';
|
|
2
2
|
import type { PickUpPatrolClient } from '../client.js';
|
|
3
3
|
import type { DefaultPlan, Student } from '../types.js';
|
|
4
4
|
/** Project a student down to the fields a parent actually asks about. */
|
package/dist/tools/account.js
CHANGED
|
@@ -63,13 +63,13 @@ export function registerAccountTools(server, client) {
|
|
|
63
63
|
server.registerTool('pup_get_student', {
|
|
64
64
|
description: 'One student in full, including the default dismissal plan for each weekday. Pass raw: true for the untouched API record.',
|
|
65
65
|
annotations: { readOnlyHint: true },
|
|
66
|
-
inputSchema: {
|
|
66
|
+
inputSchema: z.object({
|
|
67
67
|
student_id: z.number().int().describe('Student id, from pup_list_students'),
|
|
68
68
|
raw: z
|
|
69
69
|
.boolean()
|
|
70
70
|
.optional()
|
|
71
71
|
.describe('Return the unprojected API record instead of the summary'),
|
|
72
|
-
},
|
|
72
|
+
}),
|
|
73
73
|
}, async ({ student_id, raw }) => {
|
|
74
74
|
const student = await client.getStudent(student_id);
|
|
75
75
|
return minifiedResult(raw === true ? student : summarizeStudent(student));
|
package/dist/tools/defaults.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/server';
|
|
2
2
|
import type { PickUpPatrolClient } from '../client.js';
|
|
3
3
|
/**
|
|
4
4
|
* Accept weekdays as names ("Monday") or ids (1 = Sunday … 7 = Saturday).
|
package/dist/tools/defaults.js
CHANGED
|
@@ -34,9 +34,9 @@ export function registerDefaultPlanTools(server, client) {
|
|
|
34
34
|
server.registerTool('pup_get_default_plans', {
|
|
35
35
|
description: "A student's weekly default dismissal plan — how they normally leave school on each day of the week — and whether the defaults still need a parent review.",
|
|
36
36
|
annotations: { readOnlyHint: true },
|
|
37
|
-
inputSchema: {
|
|
37
|
+
inputSchema: z.object({
|
|
38
38
|
student_id: z.number().int().describe('Student id, from pup_list_students'),
|
|
39
|
-
},
|
|
39
|
+
}),
|
|
40
40
|
}, async ({ student_id }) => {
|
|
41
41
|
const [student, review] = await Promise.all([
|
|
42
42
|
client.getStudent(student_id),
|
|
@@ -55,7 +55,7 @@ export function registerDefaultPlanTools(server, client) {
|
|
|
55
55
|
});
|
|
56
56
|
server.registerTool('pup_set_default_plans', {
|
|
57
57
|
description: "Change a student's weekly default dismissal plan for one or more weekdays, or clear every default. This is how the child leaves school on any date without a specific plan, so it requires confirm: true; without it you get a dry-run. Read pup_list_transportations first.",
|
|
58
|
-
inputSchema: {
|
|
58
|
+
inputSchema: z.object({
|
|
59
59
|
student_id: z.number().int().describe('Student id, from pup_list_students'),
|
|
60
60
|
days: z
|
|
61
61
|
.array(z.union([z.string(), z.number().int()]))
|
|
@@ -76,7 +76,7 @@ export function registerDefaultPlanTools(server, client) {
|
|
|
76
76
|
.optional()
|
|
77
77
|
.describe('Remove every weekday default instead of setting one (days is ignored)'),
|
|
78
78
|
confirm: schemaConfirm,
|
|
79
|
-
},
|
|
79
|
+
}),
|
|
80
80
|
}, (async ({ student_id, days, transportation_id, note, early_dismissal_time, clear_all, confirm }) => {
|
|
81
81
|
// Read-modify-write: PickUp Patrol has no default-plans endpoint, so the
|
|
82
82
|
// whole student record round-trips. Reading it here (before the confirm
|
|
@@ -152,11 +152,11 @@ export function registerDefaultPlanTools(server, client) {
|
|
|
152
152
|
}));
|
|
153
153
|
server.registerTool('pup_mark_defaults_reviewed', {
|
|
154
154
|
description: "Mark a student's default plans as reviewed, clearing the school's 'needs review' prompt. Requires confirm: true.",
|
|
155
|
-
inputSchema: {
|
|
155
|
+
inputSchema: z.object({
|
|
156
156
|
student_id: z.number().int().describe('Student id, from pup_list_students'),
|
|
157
157
|
reviewed: z.boolean().optional().describe('Defaults to true'),
|
|
158
158
|
confirm: schemaConfirm,
|
|
159
|
-
},
|
|
159
|
+
}),
|
|
160
160
|
}, async ({ student_id, reviewed, confirm }) => {
|
|
161
161
|
const value = reviewed ?? true;
|
|
162
162
|
const gate = previewUnlessConfirmed(confirm, `Mark student ${student_id}'s defaults as ${value ? 'reviewed' : 'not reviewed'}`, 'PUT', 'SetDefaultsReviewed', { StudentId: student_id, Reviewed: value });
|
package/dist/tools/plans.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/server';
|
|
2
2
|
import type { PickUpPatrolClient } from '../client.js';
|
|
3
3
|
import type { Transportation } from '../types.js';
|
|
4
4
|
/** The fields whose change proves a plan write actually landed. */
|
package/dist/tools/plans.js
CHANGED
|
@@ -41,22 +41,22 @@ export function registerPlanTools(server, client) {
|
|
|
41
41
|
server.registerTool('pup_list_plans', {
|
|
42
42
|
description: 'Day-by-day dismissal plans across a date range for every student on the account, as PickUp Patrol returns them.',
|
|
43
43
|
annotations: { readOnlyHint: true },
|
|
44
|
-
inputSchema: {
|
|
44
|
+
inputSchema: z.object({
|
|
45
45
|
start_date: z.string().describe('YYYY-MM-DD'),
|
|
46
46
|
end_date: z.string().describe('YYYY-MM-DD'),
|
|
47
|
-
},
|
|
47
|
+
}),
|
|
48
48
|
}, async ({ start_date, end_date }) => minifiedResult(await client.getParentPlans(start_date, end_date)));
|
|
49
49
|
server.registerTool('pup_get_plan', {
|
|
50
50
|
description: 'The dismissal plan for one student on one date — the option in force, any note, the early-dismissal time, and whether the date is locked because the cutoff has passed.',
|
|
51
51
|
annotations: { readOnlyHint: true },
|
|
52
|
-
inputSchema: {
|
|
52
|
+
inputSchema: z.object({
|
|
53
53
|
student_id: z.number().int().describe('Student id, from pup_list_students'),
|
|
54
54
|
date: z.string().describe('YYYY-MM-DD'),
|
|
55
|
-
},
|
|
55
|
+
}),
|
|
56
56
|
}, async ({ student_id, date }) => minifiedResult(await client.getPlanEdit(date, student_id)));
|
|
57
57
|
server.registerTool('pup_set_plan', {
|
|
58
58
|
description: "Change how a student is dismissed on one or more specific dates, or clear those dates back to the student's weekly default. This changes how a child actually leaves school, so it requires confirm: true; without it you get a dry-run of the exact payload. Read pup_list_transportations first — options differ in whether they require a note, a car number or an early-dismissal time.",
|
|
59
|
-
inputSchema: {
|
|
59
|
+
inputSchema: z.object({
|
|
60
60
|
student_id: z.number().int().describe('Student id, from pup_list_students'),
|
|
61
61
|
dates: z
|
|
62
62
|
.array(z.string())
|
|
@@ -77,7 +77,7 @@ export function registerPlanTools(server, client) {
|
|
|
77
77
|
.optional()
|
|
78
78
|
.describe('Car number, for options where usesCarNumbers is true'),
|
|
79
79
|
confirm: schemaConfirm,
|
|
80
|
-
},
|
|
80
|
+
}),
|
|
81
81
|
}, (async ({ student_id, dates, transportation_id, note, early_dismissal_time, car_number, confirm }) => {
|
|
82
82
|
// The reads below resolve and validate the payload; they mutate nothing.
|
|
83
83
|
// Running them before the confirm gate is deliberate: it makes the
|
package/dist/tools/school.d.ts
CHANGED
package/dist/tools/school.js
CHANGED
|
@@ -22,13 +22,13 @@ export function registerSchoolTools(server, client) {
|
|
|
22
22
|
server.registerTool('pup_list_transportations', {
|
|
23
23
|
description: 'The dismissal options a school offers (bus, car pickup, walker, absent …) with the rules each one imposes: whether a note is required, whether it takes a car number, whether it is an early dismissal, and the daily cutoff time. Read this before setting a plan.',
|
|
24
24
|
annotations: { readOnlyHint: true },
|
|
25
|
-
inputSchema: {
|
|
25
|
+
inputSchema: z.object({
|
|
26
26
|
school_id: z.number().int().describe('School id, from pup_list_students'),
|
|
27
27
|
include_inactive: z
|
|
28
28
|
.boolean()
|
|
29
29
|
.optional()
|
|
30
30
|
.describe('Include options the school has deactivated (default false)'),
|
|
31
|
-
},
|
|
31
|
+
}),
|
|
32
32
|
}, async ({ school_id, include_inactive }) => {
|
|
33
33
|
const options = await client.getTransportations(school_id);
|
|
34
34
|
const visible = include_inactive === true ? options : options.filter((o) => o.IsActive !== false);
|
|
@@ -37,9 +37,9 @@ export function registerSchoolTools(server, client) {
|
|
|
37
37
|
server.registerTool('pup_get_school', {
|
|
38
38
|
description: 'A school profile together with its per-weekday notify times and plan cutoff times, and the settings that decide whether parents may set plans at all.',
|
|
39
39
|
annotations: { readOnlyHint: true },
|
|
40
|
-
inputSchema: {
|
|
40
|
+
inputSchema: z.object({
|
|
41
41
|
school_id: z.number().int().describe('School id, from pup_list_students'),
|
|
42
|
-
},
|
|
42
|
+
}),
|
|
43
43
|
}, async ({ school_id }) => {
|
|
44
44
|
const [school, notifyTimes, settings] = await Promise.all([
|
|
45
45
|
client.getSchool(school_id),
|
|
@@ -51,14 +51,14 @@ export function registerSchoolTools(server, client) {
|
|
|
51
51
|
server.registerTool('pup_list_non_school_days', {
|
|
52
52
|
description: 'Dates a plan cannot be set for at a school (holidays, closures, weekends), and optionally the dates in a range that already differ from the student defaults.',
|
|
53
53
|
annotations: { readOnlyHint: true },
|
|
54
|
-
inputSchema: {
|
|
54
|
+
inputSchema: z.object({
|
|
55
55
|
school_id: z.number().int().describe('School id, from pup_list_students'),
|
|
56
56
|
start_date: z
|
|
57
57
|
.string()
|
|
58
58
|
.optional()
|
|
59
59
|
.describe('YYYY-MM-DD; with end_date, also return dates that differ from the default'),
|
|
60
60
|
end_date: z.string().optional().describe('YYYY-MM-DD'),
|
|
61
|
-
},
|
|
61
|
+
}),
|
|
62
62
|
}, async ({ school_id, start_date, end_date }) => {
|
|
63
63
|
const invalidDates = await client.getInvalidPlanDates(school_id);
|
|
64
64
|
if (start_date === undefined || end_date === undefined) {
|
|
@@ -70,8 +70,8 @@ export function registerSchoolTools(server, client) {
|
|
|
70
70
|
server.registerTool('pup_list_car_numbers', {
|
|
71
71
|
description: 'The car numbers a school has issued to this account, for dismissal options where usesCarNumbers is true.',
|
|
72
72
|
annotations: { readOnlyHint: true },
|
|
73
|
-
inputSchema: {
|
|
73
|
+
inputSchema: z.object({
|
|
74
74
|
school_id: z.number().int().describe('School id, from pup_list_students'),
|
|
75
|
-
},
|
|
75
|
+
}),
|
|
76
76
|
}, async ({ school_id }) => minifiedResult(await client.getCarNumbers(school_id)));
|
|
77
77
|
}
|
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": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
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)",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
],
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "tsc && npm run bundle",
|
|
52
|
-
"bundle": "esbuild src/index.ts --bundle --platform=node --format=esm --external:dotenv --outfile=dist/bundle.js",
|
|
52
|
+
"bundle": "esbuild src/index.ts --bundle --alias:zod/v4=./node_modules/zod/v4/index.cjs --platform=node --format=esm --external:dotenv --outfile=dist/bundle.js",
|
|
53
53
|
"dev": "node dist/index.js",
|
|
54
54
|
"typecheck": "tsc --noEmit",
|
|
55
55
|
"test": "npm run typecheck && vitest run",
|
|
@@ -57,16 +57,17 @@
|
|
|
57
57
|
"test:watch": "vitest"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@chrischall/mcp-utils": "^0.
|
|
61
|
-
"@modelcontextprotocol/
|
|
60
|
+
"@chrischall/mcp-utils": "^1.0.0",
|
|
61
|
+
"@modelcontextprotocol/server": "^2.0.0",
|
|
62
62
|
"dotenv": "^17.4.0",
|
|
63
|
-
"zod": "^4.
|
|
63
|
+
"zod": "^4.6.2"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
+
"@modelcontextprotocol/client": "^2.0.0",
|
|
66
67
|
"@types/node": "^26.1.1",
|
|
67
|
-
"@vitest/coverage-v8": "^
|
|
68
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
68
69
|
"esbuild": "^0.28.0",
|
|
69
70
|
"typescript": "^7.0.2",
|
|
70
|
-
"vitest": "^
|
|
71
|
+
"vitest": "^5.0.0"
|
|
71
72
|
}
|
|
72
73
|
}
|
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": "0.
|
|
9
|
+
"version": "1.0.0",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@chrischall/pickuppatrol-mcp",
|
|
14
|
-
"version": "0.
|
|
14
|
+
"version": "1.0.0",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
}
|