wicker-study-mcp 2.14.2 → 2.14.3
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/calendar-result.mjs +21 -0
- package/core-tools.mjs +3 -2
- package/package.json +3 -2
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// The web calendar includes reconciliation proposals and whole-term analytics.
|
|
2
|
+
// They are not evidence for a bounded calendar lookup and can bury its events.
|
|
3
|
+
export function calendarToolResult(data, { from, to } = {}) {
|
|
4
|
+
if (from && to && from > to) throw new Error('from must be on or before to')
|
|
5
|
+
const inRange = (day) => (!from || day >= from) && (!to || day <= to)
|
|
6
|
+
const events = (data.events || []).filter((event) => inRange(String(event.start).slice(0, 10)))
|
|
7
|
+
// Existing notices keep the original date in their server-generated detail.
|
|
8
|
+
// Include moves both away from and into the requested day.
|
|
9
|
+
const changes = (data.changes || []).filter((change) =>
|
|
10
|
+
[change.date, ...(String(change.detail || '').match(/\b\d{4}-\d{2}-\d{2}\b/g) || [])]
|
|
11
|
+
.filter(Boolean).some(inRange))
|
|
12
|
+
return {
|
|
13
|
+
events,
|
|
14
|
+
changes,
|
|
15
|
+
range: { from: from || null, to: to || null, inclusive: true },
|
|
16
|
+
eventCount: events.length,
|
|
17
|
+
feeds: data.feeds || [],
|
|
18
|
+
canvas: data.canvas || { connected: false },
|
|
19
|
+
problems: data.problems || [],
|
|
20
|
+
}
|
|
21
|
+
}
|
package/core-tools.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { calendarToolResult } from './calendar-result.mjs'
|
|
1
2
|
import { searchCourseSchema } from './search-course-schema.mjs'
|
|
2
3
|
// Shared by stdio and Streamable HTTP. Keep schemas and behavior in one place.
|
|
3
4
|
export function registerCoreTools(server, { z, run, api, defaultCanvasUrl: DEFAULT_CANVAS_URL }) {
|
|
@@ -43,8 +44,8 @@ server.tool('get_mock_session', 'One mock session with every answer and correcti
|
|
|
43
44
|
server.tool('get_academic_plan', 'Active academic programme: courses, attempts, exam dates, events, gates, summary.', {}, run(() => api('/api/academics')))
|
|
44
45
|
server.tool('get_planning_context', 'Read the student’s saved exam scenario as a compact planning model. Recorded attempts and grades are explicitly separated from private choices such as a resit, following-year deferral, expected grade, or what-if outcome. Actual academic-calendar records are grouped into dated examination windows, so one window can contain a period’s primary exams and another period’s resits. Each course includes allowed session ids and course-specific roles derived from its teaching period, calendar, transcript fallback, and verified resit rules. Returns stable session ids and a revision; call this before suggesting or changing the plan.', {}, run(() => api('/api/planning/context')))
|
|
45
46
|
server.tool('list_known_programmes', 'The catalogue of known bachelor programmes.', {}, run(() => api('/api/editorial-programmes')))
|
|
46
|
-
server.tool('get_calendar', 'Unified calendar in one call: exam attempts, personal events, registration windows, the institution calendar, saved timetable feeds (lectures, tutorials, labs), and — when Canvas is connected — Canvas assignment deadlines and Canvas course events. This is the tool for "when is my next lecture", "where do I need to be", and "what is due this week". Events carry `category`, `courseCode`, and for Canvas items a `canvasStatus`; `problems` names any source that could not be read, which is how you tell an empty week from a missing timetable feed.', { from: z.string().optional().describe('
|
|
47
|
-
run(async ({ from, to }) => { const data = await api('/api/calendar/events');
|
|
47
|
+
server.tool('get_calendar', 'Unified calendar in one call: exam attempts, personal events, registration windows, the institution calendar, saved timetable feeds (lectures, tutorials, labs), and — when Canvas is connected — Canvas assignment deadlines and Canvas course events. This is the tool for "when is my next lecture", "where do I need to be", and "what is due this week". Events carry `category`, `courseCode`, and for Canvas items a `canvasStatus`; `problems` names any source that could not be read, which is how you tell an empty week from a missing timetable feed.', { from: z.string().date().optional().describe('Inclusive first calendar date (YYYY-MM-DD); omit for no lower bound.'), to: z.string().date().optional().describe('Inclusive last calendar date (YYYY-MM-DD). Use the same date as from for one full day.') },
|
|
48
|
+
run(async ({ from, to }) => { const data = await api('/api/calendar/events'); return calendarToolResult(data, { from, to }) }))
|
|
48
49
|
server.tool('get_activity', 'Study activity series, streak, weekly totals, recent events.', { days: z.number().int().min(7).max(120).optional() }, run(({ days }) => api('/api/activity', { query: { days } })))
|
|
49
50
|
server.tool('get_account_summary', 'What is stored for the account, per record family.', {}, run(() => api('/api/account/summary')))
|
|
50
51
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wicker-study-mcp",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.3",
|
|
4
4
|
"description": "MCP server for Wicker Study: read course material and a student's academic record, study on their behalf, collect a private Canvas course snapshot, and \u2014 with an admin key \u2014 run the editorial workflow.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"README.md",
|
|
43
43
|
"core-tools.mjs",
|
|
44
44
|
"tool-annotations.mjs",
|
|
45
|
-
"search-course-schema.mjs"
|
|
45
|
+
"search-course-schema.mjs",
|
|
46
|
+
"calendar-result.mjs"
|
|
46
47
|
],
|
|
47
48
|
"dependencies": {
|
|
48
49
|
"@modelcontextprotocol/sdk": "^1.30.0",
|