wicker-study-mcp 2.13.0 → 2.14.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/README.md CHANGED
@@ -7,17 +7,92 @@ with an admin key — the whole editorial content workflow.
7
7
 
8
8
  Runs from anywhere. Nothing here needs a checkout of the application.
9
9
 
10
- ## Use it
10
+ ## Connect over HTTPS (recommended)
11
11
 
12
- The authenticated **Docs** page in Wicker Study can mint a scoped key and place it directly inside
13
- one copy-ready Codex or Claude Code installation block. There is no separate credential field to
14
- copy. The first line stores the embedded key with owner-only permissions and the second registers
15
- the MCP server.
12
+ For local agents and other compatible services, use **https://study.wicker.life/api/mcp**
13
+ with Streamable HTTP and OAuth. No Wicker package, Node.js or separately downloaded skill
14
+ is needed. The client manages credentials after the user signs in and approves access.
15
+
16
+ ### Codex
17
+
18
+ ```sh
19
+ codex mcp add wicker-study --url https://study.wicker.life/api/mcp
20
+ codex mcp login wicker-study --scopes read,write
21
+ ```
22
+
23
+ Complete browser approval, then restart the agent session (or reopen the app/reload the IDE window).
24
+
25
+ ### Claude Code
26
+
27
+ ```sh
28
+ claude mcp add --scope user --transport http wicker-study https://study.wicker.life/api/mcp
29
+ ```
30
+
31
+ Open Claude Code, run `/mcp`, select `wicker-study` and authenticate in the browser.
32
+
33
+ ### Replace an existing package registration
34
+
35
+ Before running the hosted commands above, remove the existing entry:
36
+
37
+ ```sh
38
+ # Codex
39
+ codex mcp remove wicker-study
40
+
41
+ # Claude Code: use the scope where the old entry was installed
42
+ claude mcp remove --scope user wicker-study
43
+ ```
44
+
45
+ For Claude project/local installations, use that same scope when removing and adding the
46
+ connection. Preserve any custom settings still needed and check project overrides.
47
+ This changes client configuration, not account data. Old package keys are not used by OAuth
48
+ and are not automatically revoked; revoke unused keys in Settings → API access.
49
+
50
+ Verify with `wicker_status`, `wicker_guidance` and `list_courses`. Hosted updates require a
51
+ reconnection to refresh tools and guidance, not an npm or separate skill update. An optional
52
+ installed skill is only a discovery hint. Revoke OAuth access at
53
+ [Connected services](https://study.wicker.life/connect/remote).
54
+
55
+ Other clients need Streamable HTTP and OAuth dynamic registration with PKCE, or support for
56
+ an existing scoped key in `Authorization: Bearer wsk_…`. Keep credentials out of URLs and chat.
57
+ See [the hosted MCP guide](../docs/REMOTE_MCP.md) for protocol details and limits, and the official
58
+ [Codex](https://developers.openai.com/codex/mcp) and
59
+ [Claude Code](https://code.claude.com/docs/en/mcp) client instructions.
60
+
61
+ ### Does local work require the package?
62
+
63
+ No. An agent with shell/file access can inspect folders, extract PDFs, render slides, verify
64
+ hashes and generate content using its own tools. Hosted `study_generation_*` tools provide
65
+ current prompts, evidence and schemas, and accept locally computed results. The transport
66
+ does not decide where model computation runs.
67
+
68
+ Keep the package as the optional **admin toolkit**: it retains editorial operations,
69
+ course-folder inventory/sync and bulk Canvas imports. Existing helper users remain supported.
70
+ Students and ordinary agents should use hosted MCP and their native file/processing tools.
71
+
72
+ For complete originals, call `prepare_original_download` with an asset ID from
73
+ `canvas_course_materials`. It returns the direct HTTPS URL, a short-lived file-scoped header,
74
+ size, SHA-256 and expiry. Stream the response with native HTTP/file tools into a new temporary
75
+ file, verify its complete size/hash, then rename it to a safe chosen path. Resume with Range
76
+ and the supplied If-Match; request a new descriptor for the same asset/hash after expiry.
77
+ This works without the npm helper and keeps binary bytes outside MCP text-token budgets.
78
+
79
+ The temporary header authorizes only that original, not other files or account actions.
80
+ Keep it out of chat, logs and shell history; do not follow redirects or forward it elsewhere.
81
+ Do not extract the client’s OAuth token or request Canvas credentials. A native file tool
82
+ alone does not supply authenticated access; the server supplies the narrowly scoped transfer.
83
+ `read_original_chunk` remains a fallback for clients unable to perform direct downloads.
84
+ Direct transfers have their own request, concurrency and byte limits.
85
+
86
+ ## Optional local package setup
87
+
88
+ Use the package for the helper workflows described above. It requires Node.js 20.11 or newer.
89
+ Register it as a stdio server below, then let `wicker_authorize` open browser approval when no
90
+ saved key exists. No key needs to be pasted into the agent conversation.
16
91
 
17
92
  For a manually supplied key, the same secure bootstrap is available as:
18
93
 
19
94
  ```sh
20
- WICKER_STUDY_URL='https://study.wicker.life' WICKER_STUDY_API_KEY='wsk_…' npx -y wicker-study-mcp@2.13.0 configure
95
+ WICKER_STUDY_URL='https://study.wicker.life' WICKER_STUDY_API_KEY='wsk_…' npx -y wicker-study-mcp@2.14.0 configure
21
96
  ```
22
97
 
23
98
  ```jsonc
@@ -100,13 +175,15 @@ authoritative list of endpoints and scopes.
100
175
 
101
176
  Direct context reads do not call the model. `tutor_ask` uses the student's AI allowance and can prepare attendance changes, assignment/catch-up trackers, group milestones, focused practice, diagnostics and rubric-based draft reviews. Reuse conversation IDs. Approve only the exact proposal the student reviewed; receipts prevent double application. No tool sends email or submits assignments to Canvas. Personal completion is separate from Canvas submission status.
102
177
 
103
- Update an installed client to `wicker-study-mcp@2.13.0` and restart its MCP connection to discover the new tools. The matching workflow guide is served by `wicker_guidance` and `wicker://guidance/current`. No separate skill update is needed.
178
+ Hosted users reconnect to discover the current tools. Optional package users update to `wicker-study-mcp@2.14.0` and restart their local MCP process. The matching workflow guide is served by `wicker_guidance` and `wicker://guidance/current`. No separate skill update is needed.
104
179
 
105
180
  ### Complete original downloads and remembered context
106
181
 
182
+ Prefer `prepare_original_download` with native HTTP/file tools on either connection. It provides a resumable direct transfer without exposing account credentials or putting binary bytes into MCP results. The helper below remains available for existing local clients.
183
+
107
184
  Use `canvas_course_materials` to choose an exact asset/course/year, then call `download_course_original({assetId, courseCode, academicYear, outputFolder})`. The MCP streams the full stored original to a new private local subfolder and returns its path, size and SHA-256 only after verifying the complete file. PDFs, slide decks, images, spreadsheets and archives retain their original bytes. Existing files are never overwritten. Failed or incomplete downloads are removed. The maximum is 1 GB per file; larger files remain available through the authenticated web download. A remote MCP's filesystem may not be accessible to its client. This tool uses read scope and never scrapes Canvas or sends file bytes into the chat.
108
185
 
109
- The companion skill now proactively notices lasting preferences, project decisions, constraints and availability during normal discussions. It reads `tutor_sources` to avoid duplicates, prepares the exact new context, and asks for confirmation before saving with `tutor_confirm_update`. The agent reports a successful receipt instead of treating a draft or an ordinary chat reply as saved memory. Transient remarks and speculation are not stored, and tasks/attendance continue using their dedicated workflows.
186
+ The server-supplied workflow guide instructs the agent to notice lasting preferences, project decisions, constraints and availability during normal discussions. It reads `tutor_sources` to avoid duplicates, prepares the exact new context, and asks for confirmation before saving with `tutor_confirm_update`. The agent reports a successful receipt instead of treating a draft or an ordinary chat reply as saved memory. Transient remarks and speculation are not stored, and tasks/attendance continue using their dedicated workflows.
110
187
 
111
188
  ## Licence
112
189
 
@@ -152,15 +229,15 @@ Students can follow reports and withdraw evidence at `/app/feedback`; authorized
152
229
 
153
230
  Contact sharing is optional per report: use `shareContactEmail:true` only when the student chooses it and show the returned address in the preview. `feedback_withdraw_contact` stops sharing it after fresh confirmation. Reports show receipt, investigation and completion updates with public comments; AI-assisted replies are labeled and reviewed by the team.
154
231
 
155
- ## Updating an existing installation
232
+ ## Updating the optional package
156
233
 
157
- The in-app guide at [Docs → Update your MCP](https://study.wicker.life/app/docs#update) has copyable commands for both clients. For the standard installation, reuse your saved credentials; do not generate a new API key or run `configure` again.
234
+ Most users can switch to hosted MCP using the instructions above. If keeping the package, [Docs → Optional local helper](https://study.wicker.life/app/docs#local-tools) has its setup instructions. Reuse your saved credentials; do not generate a new API key or run `configure` again.
158
235
 
159
236
  ### Codex
160
237
 
161
238
  ```sh
162
239
  codex mcp remove wicker-study
163
- codex mcp add wicker-study -- npx -y wicker-study-mcp@2.13.0
240
+ codex mcp add wicker-study -- npx -y wicker-study-mcp@2.14.0
164
241
  ```
165
242
 
166
243
  Quit and reopen the Codex app, restart the CLI session, or reload the IDE extension window so the local MCP process restarts.
@@ -169,14 +246,14 @@ Quit and reopen the Codex app, restart the CLI session, or reload the IDE extens
169
246
 
170
247
  ```sh
171
248
  claude mcp remove --scope user wicker-study
172
- claude mcp add --scope user wicker-study -- npx -y wicker-study-mcp@2.13.0
249
+ claude mcp add --scope user wicker-study -- npx -y wicker-study-mcp@2.14.0
173
250
  ```
174
251
 
175
252
  Exit and restart Claude Code, then check `/mcp`. `claude mcp add` does not overwrite an existing registration. If you originally installed with `project` or `local` scope, use that same scope in both commands.
176
253
 
177
254
  ### Claude Desktop and custom configurations
178
255
 
179
- In Claude Desktop, use Settings → Developer → Edit Config. Change only the package argument in the existing `wicker-study` entry to `wicker-study-mcp@2.13.0`, preserve its other settings, then fully quit and reopen Claude Desktop. For custom Codex/Claude Code configurations with environment variables or a server URL, update the package argument in place instead of replacing the registration. Check project overrides if an older version still loads.
256
+ In Claude Desktop, use Settings → Developer → Edit Config. Change only the package argument in the existing `wicker-study` entry to `wicker-study-mcp@2.14.0`, preserve its other settings, then fully quit and reopen Claude Desktop. For custom Codex/Claude Code configurations with environment variables or a server URL, update the package argument in place instead of replacing the registration. Check project overrides if an older version still loads.
180
257
 
181
258
  The standard helper credentials stay in `~/.config/wicker-study/config.json`. These registration commands do not delete that file. After restarting, ask the agent to call `wicker_status` and `wicker_guidance` to verify connectivity and availability of the new tools. The optional companion skill is a stable discovery hint; the current guide comes from MCP.
182
259
 
@@ -184,9 +261,9 @@ Official client references: [Codex MCP configuration](https://developers.openai.
184
261
 
185
262
  ## Local study generation
186
263
 
187
- The 2.13.0 source adds `study_generation_contract`, `study_generation_sources`, `study_generation_start`, `study_generation_next`, `study_generation_submit`, `study_generation_refresh`, `study_generation_stop`, and `study_generation_add_notes`. Install `wicker-study-mcp@2.13.0` using the update instructions above.
264
+ Both hosted MCP and package 2.14.0 expose `study_generation_contract`, `study_generation_sources`, `study_generation_start`, `study_generation_next`, `study_generation_submit`, `study_generation_refresh`, `study_generation_stop`, and `study_generation_add_notes`. The package is not required for this workflow; an agent can use its own model and file tools with the hosted connection.
188
265
 
189
- 1. Read the current contract and list the course edition’s sources. If needed, download originals with `canvas_import_remote_course`; inspect graphics and preserve page numbers. Add supplementary extraction as explicitly labelled local notes.
266
+ 1. Read the current contract and list the course edition’s sources. If needed, obtain originals through `prepare_original_download` and stream/verify them with the client’s file tools, or use the optional package’s download/import helpers. Inspect graphics and preserve page numbers. Add supplementary extraction as explicitly labelled local notes.
190
267
  2. Start the student-requested private run with its exact source selection, or continue a version prepared in the web UI.
191
268
  3. Fetch `study_generation_next`. Use its exact evidence, prompt and response schema to compute one complete response locally. Use a fresh critique context for review steps and report real findings.
192
269
  4. Submit with its `requestId` and `contractId`. Retry network failures with the identical payload. Fetch next again until complete. Failed content can be corrected with `retry:true`; ready chapters remain saved.
@@ -197,6 +274,6 @@ Prompts and schemas are fetched from the deployed platform every step. An implem
197
274
 
198
275
  Connect to **https://study.wicker.life/api/mcp** using Streamable HTTP. Choose OAuth in your MCP client, sign in and review the service name, callback origin and scopes. Discovery, dynamic client registration, S256 PKCE, resource-bound authorization codes, one-hour access tokens, rotating refresh tokens (30-day connection lifetime), and revocation are supported. Existing API keys also work in `Authorization: Bearer wsk_…`. OAuth is authorization-code based; client-credentials grants and anonymous account access are not supported.
199
276
 
200
- Hosted tools share their schemas and implementations with this package. Filesystem imports and clipboard operations remain local. Hosted consumers can assemble complete originals using `read_original_chunk`; verify against inventory SHA-256 and byte size. Only use tools listed by your connection. Guidance is served by MCP, so hosted clients reconnect to refresh it without npm or skill downloads.
277
+ Hosted tools share their schemas and implementations with this package. Filesystem imports and clipboard operations remain local. Hosted consumers can stream complete originals using `prepare_original_download` and native HTTP/file tools; verify the returned SHA-256 and byte size. `read_original_chunk` is a fallback. Only use tools listed by your connection. Guidance is served by MCP, so hosted clients reconnect to refresh it without npm or skill downloads.
201
278
 
202
279
  See [remote MCP operations](../docs/REMOTE_MCP.md) for limits and configuration. Disconnect OAuth services under [Connected services](https://study.wicker.life/connect/remote). Revoke API keys separately in Settings → API access.
package/guidance.md CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  This guide ships with the MCP server and is available through `wicker_guidance` and `wicker://guidance/current`. Read it once per connection/version. Hosted MCP at `/api/mcp` updates with Wicker Study; local stdio updates with the npm package. Only use tools advertised by the connected server.
4
4
 
5
- Hosted connections use OAuth approval or a Bearer API key. OAuth discovery supplies registration, S256 PKCE, resource-bound tokens and refresh rotation. Do not ask users to paste credentials in chat. If a hosted connection expires, use the client’s reconnect/authorization flow. `wicker_authorize`, local folder imports, clipboard access and `download_course_original` are local stdio capabilities. Hosted clients can assemble complete originals using `read_original_chunk`, the inventory size/SHA-256 and Content-Range. Never put binary chunks in a conversation.
5
+ Hosted connections use OAuth approval or a Bearer API key. OAuth discovery supplies registration, S256 PKCE, resource-bound tokens and refresh rotation. Do not ask users to paste credentials in chat. If a hosted connection expires, use the client’s reconnect/authorization flow. `wicker_authorize`, local folder imports, clipboard access and `download_course_original` are local stdio capabilities. Prefer `prepare_original_download` for complete originals. It returns a small descriptor: direct HTTPS URL, a temporary file-scoped Authorization header, original size/SHA-256, expiry and If-Match. Use native HTTP/file tools to stream bytes into a fresh temporary file outside MCP, verify full size/hash, then rename to a safe chosen path. Never treat the remote filename as a local path or execute downloaded content. Keep the file capability out of chat, logs and shell history; never follow redirects with it or forward it to another host. It is not the client’s OAuth token and cannot access other files or API tools. Resume with Range and If-Match; after expiry request a new descriptor for the same asset/hash. Binary transfer uses separate byte/request limits, not MCP text-token budgets. Hosted clients unable to perform direct transfers may use `read_original_chunk` as a small-file fallback. Never put binary chunks in a conversation. The package remains useful for editorial administration and bulk Canvas import helpers; it is not required for ordinary local analysis or generation.
6
6
 
7
7
  Call `wicker_status` for request/response limits. On 429 respect Retry-After; do not repeatedly retry, create extra connections, or split calls to circumvent budgets. Narrow oversized reads. For interrupted writes inspect saved state before retrying. Wicker Study limits its own hosted AI usage; a consumer’s own model has separate billing and limits.
8
8
 
9
9
  # Wicker Study
10
10
 
11
11
  Wicker Study exposes one HTTP API for the web app, agents, and administrators.
12
- Everything is scoped by a personal API key. The MCP server wraps that API and
13
- runs from anywhere it needs no checkout of the application.
12
+ Access is scoped by the approved OAuth connection or personal API key. Hosted MCP
13
+ wraps the same API; the optional local package adds admin and import helpers.
14
14
 
15
15
  **Each write requires fresh, explicit confirmation of its exact effect.** Read first, show the change, then pass `confirmed:true` only after approval. Connecting an account is not blanket write permission. For attendance or memory, use the direct prepare/confirm workflow below without a hosted model call. A student-requested local study-generation run authorises its successive next/submit steps through completion; it does not authorise sharing, changing source selection, or unrelated record writes.
16
16
 
@@ -18,7 +18,7 @@ runs from anywhere — it needs no checkout of the application.
18
18
 
19
19
  Use when the student asks to process course materials with their local agent and return a study guide to Wicker Study. Requires MCP 2.11.0 or newer with read/write access.
20
20
 
21
- - Fetch `study_generation_contract` and `study_generation_sources` for the exact course/year. Choose the student's sources. For deeper local processing use `canvas_import_remote_course` to obtain originals; inspect relevant graphs, tables, diagrams and speaker notes. Save supplementary extraction with `study_generation_add_notes`, retaining filenames/page numbers and distinguishing observations from interpretation. Original Canvas files are not overwritten.
21
+ - Fetch `study_generation_contract` and `study_generation_sources` for the exact course/year. Choose the student's sources. For deeper local processing use `prepare_original_download` and your own file tools to obtain originals (or the optional package’s `canvas_import_remote_course` for bulk imports); inspect relevant graphs, tables, diagrams and speaker notes. Save supplementary extraction with `study_generation_add_notes`, retaining filenames/page numbers and distinguishing observations from interpretation. Original Canvas files are not overwritten.
22
22
  - Start `study_generation_start` for the authorised selection, or use the version ID prepared in the web interface. This starts no hosted model work and spends no platform AI allowance.
23
23
  - Call `study_generation_next` for each step. Follow the returned prompt, evidence and JSON schema exactly; do not maintain a separate schema or teaching prompt. For review steps use a fresh critique context against the supplied evidence and report genuine findings, never a fabricated pass.
24
24
  - Submit one complete response with `study_generation_submit`, preserving `requestId` and `contractId`. On transport failure repeat the identical submission. A changed contract or stale request requires fetching next again. Continue until complete. Corrections preserve useful content and use the same platform acceptance pipeline.
package/guidance.mjs CHANGED
@@ -5,7 +5,7 @@ export const guidance = readFileSync(new URL('./guidance.md', import.meta.url),
5
5
  export const mcpVersion = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8')).version
6
6
  export const guidanceUri = 'wicker://guidance/current'
7
7
  export const guidanceInfo = Object.freeze({ version: mcpVersion, sha256: createHash('sha256').update(guidance).digest('hex'), tool: 'wicker_guidance', resource: guidanceUri })
8
- export const guidanceInstructions = `Wicker Study supplies its workflow guidance through this MCP connection. Call wicker_status and wicker_guidance once at the start of a Wicker Study session before selecting study tools; fetch guidance again when the MCP version changes. No separate skill download is needed. wicker_guidance is a read of the guide bundled with this exact MCP release, not a hosted model call. Use this release's guide and tool schemas instead of older copied workflow documentation; preserve the user's instructions and confirmation requirements for writes. Notice lasting student preferences, project decisions and availability during conversations: check tutor_sources, proactively prepare a concise context update, and save only after the required approval. A draft is not saved memory. Prefer focused source reads and download_course_original when the complete file is needed. Never request credentials in chat.`
8
+ export const guidanceInstructions = `Wicker Study supplies its workflow guidance through this MCP connection. Call wicker_status and wicker_guidance once at the start of a Wicker Study session before selecting study tools; fetch guidance again when the MCP version changes. No separate skill download is needed. wicker_guidance is a read of the guide bundled with this exact MCP release, not a hosted model call. Use this release's guide and tool schemas instead of older copied workflow documentation; preserve the user's instructions and confirmation requirements for writes. Notice lasting student preferences, project decisions and availability during conversations: check tutor_sources, proactively prepare a concise context update, and save only after the required approval. A draft is not saved memory. Prefer focused source reads and prepare_original_download with native HTTP/file tools when a complete original is needed; keep its temporary file capability out of chat/logs and verify size/hash. The local package adds optional admin and bulk-import helpers. Never request credentials in chat.`
9
9
 
10
10
  export function registerGuidance(server) {
11
11
  server.registerResource('wicker-guidance', guidanceUri, { title: 'Wicker Study workflow guide', description: `Workflow guidance bundled with MCP ${mcpVersion}. Also available through wicker_guidance.`, mimeType: 'text/markdown' }, async () => ({ contents: [{ uri: guidanceUri, mimeType: 'text/markdown', text: guidance }] }))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wicker-study-mcp",
3
- "version": "2.13.0",
3
+ "version": "2.14.0",
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",
package/study-tools.mjs CHANGED
@@ -19,7 +19,8 @@ export function registerStudyTools(server, { z, run, api, defaultCanvasUrl }) {
19
19
  tool('study_generation_stop', 'Pause the student’s local run. Completed steps and published-to-self revisions are preserved; an outstanding local result can no longer be submitted.', { versionId: id }, ({versionId}) => api(`/api/study-versions/${encodeURIComponent(versionId)}/local/stop`, { method: 'POST', body: {} }))
20
20
  tool('study_generation_add_notes', 'Save student-authorised local extraction or notes as a clearly labelled private source. Preserve original page numbers and identify source filenames in text. Describe relevant graphs, tables, diagrams and relationships accurately; distinguish inference from source facts. Does not alter the original Canvas document. Use its returned id in sourceKeys.', { ...courseIdentity, title: z.string().max(150), pages: z.array(z.object({page: z.number().int().positive().nullable(), text: z.string().max(300000)})).min(1).max(500), confirmed: z.literal(true) }, body => api('/api/study-versions/local/notes', { method: 'POST', body }))
21
21
  tool('read_course_source', 'Read 12 indexed passages from an authorised Canvas document returned by search_course. Follow nextOffset to read beyond the snippet, including later paper-list pages. Retains edition, path and page citations; never widens source access.', { assetId: id, courseCode: z.string().min(1).max(40), offset: z.number().int().min(0).max(100000).optional() }, args => api('/api/retrieve/source', { query: args }))
22
- tool('canvas_course_materials', 'List indexed originals and source editions for one course. Select an exact academic year for a retake; use read_course_source for extracted text or download_course_original for the complete unchanged file.', { courseCode: z.string().min(1).max(40), academicYear: z.string().max(20).optional() }, args => api('/api/corpus/materials', { query: args }))
22
+ tool('prepare_original_download', 'Prepare a short-lived direct HTTP download for one exact asset from canvas_course_materials. Returns a URL, file-scoped header, expiry, original size and SHA-256. Use your own HTTP/file tools to stream it to disk outside MCP and verify the complete file; no npm helper is required. The header is sensitive: keep it out of chat/logs/history and never forward it to another host. Supports resumable Range requests; does not execute or change material.', { assetId: z.string().min(1).max(160) }, ({ assetId }) => api(`/api/corpus/assets/${encodeURIComponent(assetId)}/download-ticket`))
23
+ tool('canvas_course_materials', 'List indexed originals and source editions for one course. Select an exact academic year for a retake; use read_course_source for extracted text or prepare_original_download for a direct transfer of the complete unchanged file.', { courseCode: z.string().min(1).max(40), academicYear: z.string().max(20).optional() }, args => api('/api/corpus/materials', { query: args }))
23
24
  tool('canvas_groups', 'Read your Canvas group memberships across courses and global groups. Filter by courseCode and academicYear to keep retake teams separate. Pass a groupId from these memberships to read teammates; include its canvasUrl if several Canvas hosts are connected. A failed roster is unknown, not an empty team. Read-only: never joins or changes groups.', {canvasUrl,courseCode:code,academicYear:z.string().max(20).optional(),scope:z.enum(['all','course','global']).optional(),groupId:z.string().regex(/^\d{1,20}$/).optional(),refresh:z.boolean().optional()}, ({refresh,...args}) => api('/api/integrations/canvas/groups',{query:{...args,refresh:refresh?'1':undefined}}))
24
25
  tool('canvas_assignment_detail', 'Read the full assignment brief, due/unlock/lock dates, own submission status, grade, rubric and submission comments. Use Canvas numeric course and assignment IDs from canvas_updates. Direct the student to /app/updates?tab=assignments&assignment=COURSE_ID%3AASSIGNMENT_ID; Canvas remains a secondary link.', { canvasUrl, courseId: z.string().regex(/^\d+$/), assignmentId: z.string().regex(/^\d+$/), refresh: z.boolean().optional() }, ({ refresh, ...args }) => api('/api/integrations/canvas/assignment', { query: { ...args, canvasUrl: args.canvasUrl || defaultCanvasUrl, refresh: refresh ? '1' : undefined } }))
25
26
  tool('canvas_sync_logs', 'Inspect durable progress for one sync job, optionally filtered by stage or severity. before is the next cursor returned by an earlier page. Last progress and worker checkpoints are distinct; do not claim a task is advancing from its heartbeat alone.', { job: id, before: z.string().max(160).optional(), stage: z.string().max(40).optional(), level: z.enum(['info','warning','error']).optional() }, args => api('/api/account/integrations/canvas/corpus/logs', { query: args }))