canvas-lms-mcp 1.32.0 → 1.33.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/bin/canvas-lms-mcp.js +24 -1
- package/dist/canvas/id.d.ts +92 -0
- package/dist/canvas/id.d.ts.map +1 -0
- package/dist/canvas/index.cjs +3 -3
- package/dist/canvas/index.js +2 -2
- package/dist/{chunk-KS6CBFHY.cjs → chunk-3KSWLZGH.cjs} +42 -42
- package/dist/{chunk-KS6CBFHY.cjs.map → chunk-3KSWLZGH.cjs.map} +1 -1
- package/dist/{chunk-DELZA7F6.cjs → chunk-7YQIQJKE.cjs} +4 -4
- package/dist/{chunk-DELZA7F6.cjs.map → chunk-7YQIQJKE.cjs.map} +1 -1
- package/dist/{chunk-LYNXEFQN.js → chunk-BH4GRKHJ.js} +2 -2
- package/dist/{chunk-LYNXEFQN.js.map → chunk-BH4GRKHJ.js.map} +1 -1
- package/dist/{chunk-26UC2T3R.cjs → chunk-CZWLLOQC.cjs} +2 -2
- package/dist/{chunk-26UC2T3R.cjs.map → chunk-CZWLLOQC.cjs.map} +1 -1
- package/dist/{chunk-5WTLGWRA.js → chunk-GBCV63E2.js} +3 -3
- package/dist/{chunk-H3LDGHYB.js → chunk-NLAZQ4VW.js} +2 -2
- package/dist/http.cjs +6 -6
- package/dist/http.js +3 -3
- package/dist/init.cjs +3 -3
- package/dist/init.js +1 -1
- package/dist/server.cjs +4 -4
- package/dist/server.js +3 -3
- package/dist/stdio.cjs +4 -4
- package/dist/stdio.js +3 -3
- package/package.json +1 -1
- /package/dist/{chunk-5WTLGWRA.js.map → chunk-GBCV63E2.js.map} +0 -0
- /package/dist/{chunk-H3LDGHYB.js.map → chunk-NLAZQ4VW.js.map} +0 -0
package/bin/canvas-lms-mcp.js
CHANGED
|
@@ -2,7 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
const sub = process.argv[2]
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// Handled before any import so help works without Canvas credentials and never
|
|
6
|
+
// starts the stdio or HTTP transport.
|
|
7
|
+
const USAGE = `Usage: canvas-lms-mcp [command] [options]
|
|
8
|
+
|
|
9
|
+
Canvas LMS MCP server. With no command, starts the stdio transport.
|
|
10
|
+
|
|
11
|
+
Commands:
|
|
12
|
+
(none) Start the stdio MCP server (Claude Desktop, Cursor, VS Code)
|
|
13
|
+
serve Start the HTTP MCP server (--port <n>, default 3001; --host <addr>)
|
|
14
|
+
init Configure MCP clients (run \`canvas-lms-mcp init --help\` for options)
|
|
15
|
+
doctor Check setup without starting the server
|
|
16
|
+
auth status Same as doctor
|
|
17
|
+
|
|
18
|
+
Credentials (required by stdio and serve, not by help or init --help):
|
|
19
|
+
--token <t> Canvas API token (or CANVAS_API_TOKEN)
|
|
20
|
+
--base-url <u> Canvas base URL, origin only (or CANVAS_BASE_URL)
|
|
21
|
+
|
|
22
|
+
Options:
|
|
23
|
+
-h, --help Show this help and exit
|
|
24
|
+
`
|
|
25
|
+
|
|
26
|
+
if (sub === '--help' || sub === '-h') {
|
|
27
|
+
console.log(USAGE)
|
|
28
|
+
} else if (sub === 'init') {
|
|
6
29
|
await import('../dist/init.js')
|
|
7
30
|
} else if (sub === 'serve') {
|
|
8
31
|
await import('../dist/http.js')
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The canonical Canvas identifier input type.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1, PR 1a of the 64-bit identifier design
|
|
5
|
+
* (`docs/superpowers/specs/2026-10-05-bru-2730-canvas-64bit-identifiers.md`,
|
|
6
|
+
* BRU-2730 / BRU-2816). This module adds the type and nothing else: no call
|
|
7
|
+
* site adopts it yet, which is PR 1b.
|
|
8
|
+
*
|
|
9
|
+
* The defect it exists to fix is that a Canvas object whose global ID exceeds
|
|
10
|
+
* `Number.MAX_SAFE_INTEGER` — every object on shard >= 901 — cannot be
|
|
11
|
+
* addressed at all today. `JSON.parse('{"course_id":9007199254740993}')`,
|
|
12
|
+
* which is what every MCP transport does to wire bytes, silently yields
|
|
13
|
+
* `…992` and the request succeeds against the wrong object; the string form
|
|
14
|
+
* that *would* carry the value exactly is rejected, because the schema is
|
|
15
|
+
* `z.number()`.
|
|
16
|
+
*
|
|
17
|
+
* ## Why a string and not `string | number`
|
|
18
|
+
*
|
|
19
|
+
* Per §4.1: with `type CanvasId = string | number` on **both** sides of a
|
|
20
|
+
* comparison, `a === b` is legal TypeScript and `false` at runtime whenever
|
|
21
|
+
* the two representations differ. The compiler catches only the asymmetric
|
|
22
|
+
* cases, and this codebase has 14 ID-to-ID comparisons in `src/tools/**`
|
|
23
|
+
* plus 18 `Map<number, …>` / `Set<number>` occurrences — exactly where the
|
|
24
|
+
* union would go blind. One canonical representation makes those correct by
|
|
25
|
+
* construction and makes the arithmetic sites fail to compile, which is
|
|
26
|
+
* where a human decision is wanted.
|
|
27
|
+
*
|
|
28
|
+
* ## Why the checks are composed the way they are
|
|
29
|
+
*
|
|
30
|
+
* Every departure from the obvious composition is load-bearing and has a
|
|
31
|
+
* measurement behind it (§4.2.1): the `{ abort: true }` on the pattern check
|
|
32
|
+
* (N1), the per-member error messages rather than one union-level message
|
|
33
|
+
* (N3), and the fact that the `.transform()` makes the emitted JSON Schema
|
|
34
|
+
* available only under `io: 'input'` (N2). `tests/canvas/id-input-wire.test.ts`
|
|
35
|
+
* holds the wire-level assertion for each; reverting any one of them fails a
|
|
36
|
+
* named, disjoint set of tests.
|
|
37
|
+
*/
|
|
38
|
+
import { z } from 'zod';
|
|
39
|
+
/**
|
|
40
|
+
* Canvas's own ceiling, not a value chosen here: `MAX_ID = 2**63 - 1` in
|
|
41
|
+
* `lib/api.rb`, alongside `MAX_ID_LENGTH = 19` and
|
|
42
|
+
* `ID_REGEX = /\A\d{1,19}\z/`.
|
|
43
|
+
*/
|
|
44
|
+
export declare const CANVAS_MAX_ID = 9223372036854775807n;
|
|
45
|
+
/**
|
|
46
|
+
* The largest ID a JSON **number** can carry without ambiguity. Above this,
|
|
47
|
+
* the value and its neighbour are the same double, so a number is no longer
|
|
48
|
+
* a faithful representation and the string form is the only one that works.
|
|
49
|
+
*/
|
|
50
|
+
export declare const MAX_SAFE_CANVAS_NUMBER_ID: number;
|
|
51
|
+
/** A Canvas identifier in canonical form: a decimal string, no sign, no leading zeros. */
|
|
52
|
+
export type CanvasId = string;
|
|
53
|
+
/**
|
|
54
|
+
* What the **wire** may carry, for use in `src/canvas/types.ts` before
|
|
55
|
+
* normalization. Never let this escape the HTTP client boundary (§4.1).
|
|
56
|
+
*/
|
|
57
|
+
export type CanvasWireId = string | number;
|
|
58
|
+
export interface CanvasIdInputOptions {
|
|
59
|
+
/**
|
|
60
|
+
* Non-ID literals this call site accepts in an ID position — Canvas's
|
|
61
|
+
* `"self"` and `"all"`. Only the literals a call site explicitly declares
|
|
62
|
+
* are accepted; declaring one does not open the field to arbitrary strings.
|
|
63
|
+
*/
|
|
64
|
+
readonly sentinels?: readonly string[];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* A required Canvas identifier input. Accepts a safe positive integer or a
|
|
68
|
+
* canonical decimal string, and always yields the canonical decimal string.
|
|
69
|
+
*
|
|
70
|
+
* ```ts
|
|
71
|
+
* course_id: canvasIdInput()
|
|
72
|
+
* user_id: canvasIdInput({ sentinels: ['self'] }).optional()
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare function canvasIdInput(options?: CanvasIdInputOptions): z.ZodType<CanvasId, unknown>;
|
|
76
|
+
/**
|
|
77
|
+
* A list of Canvas identifiers. Sentinels are **per element**, which is how
|
|
78
|
+
* Canvas takes them (`student_ids[]=all`), so a declared sentinel may appear
|
|
79
|
+
* alongside real IDs in the same list.
|
|
80
|
+
*/
|
|
81
|
+
export declare function canvasIdList(options?: CanvasIdInputOptions): z.ZodType<CanvasId[], unknown>;
|
|
82
|
+
/**
|
|
83
|
+
* The same §4.2 rules, callable outside a Zod parse — for code that receives
|
|
84
|
+
* an identifier from somewhere other than a tool input schema.
|
|
85
|
+
*
|
|
86
|
+
* Returns the canonical decimal string, or throws a `TypeError` carrying the
|
|
87
|
+
* same message the schema would publish. Throws rather than returning a
|
|
88
|
+
* result object so that a caller cannot accidentally thread a non-canonical
|
|
89
|
+
* value onward, which is the failure §4.1 exists to prevent.
|
|
90
|
+
*/
|
|
91
|
+
export declare function normalizeCanvasIdInput(value: unknown, options?: CanvasIdInputOptions): CanvasId;
|
|
92
|
+
//# sourceMappingURL=id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/canvas/id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;GAIG;AACH,eAAO,MAAM,aAAa,uBAAuB,CAAA;AAEjD;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,QAA0B,CAAA;AAUhE,0FAA0F;AAC1F,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAA;AAE7B;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAA;AAE1C,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACvC;AAiGD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAS1F;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,OAAO,CAAC,CAE3F;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,QAAQ,CAmB/F"}
|
package/dist/canvas/index.cjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunk7YQIQJKEcjs = require('../chunk-7YQIQJKE.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
var
|
|
9
|
+
var _chunkCZWLLOQCcjs = require('../chunk-CZWLLOQC.cjs');
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
exports.CanvasApiError =
|
|
16
|
+
exports.CanvasApiError = _chunkCZWLLOQCcjs.CanvasApiError; exports.CanvasClient = _chunk7YQIQJKEcjs.CanvasClient; exports.CanvasHttpClient = _chunkCZWLLOQCcjs.CanvasHttpClient; exports.appendCanvasQuery = _chunkCZWLLOQCcjs.appendCanvasQuery; exports.toCanvasQuery = _chunkCZWLLOQCcjs.toCanvasQuery;
|
|
17
17
|
//# sourceMappingURL=index.cjs.map
|
package/dist/canvas/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CanvasClient
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-NLAZQ4VW.js";
|
|
4
4
|
import {
|
|
5
5
|
CanvasApiError,
|
|
6
6
|
CanvasHttpClient,
|
|
7
7
|
appendCanvasQuery,
|
|
8
8
|
toCanvasQuery
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-BH4GRKHJ.js";
|
|
10
10
|
export {
|
|
11
11
|
CanvasApiError,
|
|
12
12
|
CanvasClient,
|
|
@@ -21,11 +21,11 @@ var _chunkQCEGMTXWcjs = require('./chunk-QCEGMTXW.cjs');
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
var
|
|
24
|
+
var _chunk7YQIQJKEcjs = require('./chunk-7YQIQJKE.cjs');
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
var
|
|
28
|
+
var _chunkCZWLLOQCcjs = require('./chunk-CZWLLOQC.cjs');
|
|
29
29
|
|
|
30
30
|
// src/server.ts
|
|
31
31
|
var _mcpjs = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
@@ -989,7 +989,7 @@ function assignmentSubmissionTools(canvas) {
|
|
|
989
989
|
|
|
990
990
|
// src/tools/errors.ts
|
|
991
991
|
function formatError(error) {
|
|
992
|
-
if (error instanceof
|
|
992
|
+
if (error instanceof _chunkCZWLLOQCcjs.CanvasApiError) {
|
|
993
993
|
const status = error.status;
|
|
994
994
|
const message = error.message;
|
|
995
995
|
const ltiMarkers = ["Tool not configured", "tool is not configured"];
|
|
@@ -1043,7 +1043,7 @@ function analyticsTools(canvas) {
|
|
|
1043
1043
|
inputSchema: {
|
|
1044
1044
|
course_id: _zod.z.number().describe("The Canvas course ID"),
|
|
1045
1045
|
search_term: _zod.z.string().describe("The keyword or phrase to search for"),
|
|
1046
|
-
content_types: _zod.z.array(_zod.z.enum(
|
|
1046
|
+
content_types: _zod.z.array(_zod.z.enum(_chunk7YQIQJKEcjs.SEARCH_CONTENT_TYPES)).optional().describe(
|
|
1047
1047
|
"Content types to search. Defaults to all types: pages, discussions, assignments, announcements."
|
|
1048
1048
|
)
|
|
1049
1049
|
},
|
|
@@ -1055,7 +1055,7 @@ function analyticsTools(canvas) {
|
|
|
1055
1055
|
const courseId = params.course_id;
|
|
1056
1056
|
const searchTerm = params.search_term;
|
|
1057
1057
|
const types = _nullishCoalesce(params.content_types, () => ( [
|
|
1058
|
-
...
|
|
1058
|
+
..._chunk7YQIQJKEcjs.SEARCH_CONTENT_TYPES
|
|
1059
1059
|
]));
|
|
1060
1060
|
if (types.length === 0) return { results: [] };
|
|
1061
1061
|
const settled = await Promise.allSettled(
|
|
@@ -1308,7 +1308,7 @@ function attentionTools(canvas, pseudonymizer) {
|
|
|
1308
1308
|
summaryMap.set(s.id, s);
|
|
1309
1309
|
}
|
|
1310
1310
|
} catch (err) {
|
|
1311
|
-
if (err instanceof
|
|
1311
|
+
if (err instanceof _chunkCZWLLOQCcjs.CanvasApiError && err.status === 404) {
|
|
1312
1312
|
analyticsAvailable = false;
|
|
1313
1313
|
} else {
|
|
1314
1314
|
throw err;
|
|
@@ -1662,7 +1662,7 @@ async function fanOut(config) {
|
|
|
1662
1662
|
skipped.push(outcome.result);
|
|
1663
1663
|
}
|
|
1664
1664
|
} catch (err) {
|
|
1665
|
-
if (!(err instanceof
|
|
1665
|
+
if (!(err instanceof _chunkCZWLLOQCcjs.CanvasApiError)) {
|
|
1666
1666
|
console.error(`Unexpected error ${config.errorContext(item)}:`, err);
|
|
1667
1667
|
}
|
|
1668
1668
|
const message = err instanceof Error ? err.message : "Unknown error";
|
|
@@ -2654,7 +2654,7 @@ function discussionTools(canvas) {
|
|
|
2654
2654
|
try {
|
|
2655
2655
|
return await canvas.discussions.get(course_id, topic_id);
|
|
2656
2656
|
} catch (error) {
|
|
2657
|
-
if (!(error instanceof
|
|
2657
|
+
if (!(error instanceof _chunkCZWLLOQCcjs.CanvasApiError) || error.status !== 404) throw error;
|
|
2658
2658
|
const description = await describeAnonymityFromList(canvas, course_id, topic_id);
|
|
2659
2659
|
if (description === void 0) throw error;
|
|
2660
2660
|
throw new Error(anonymousTopicMessage(course_id, topic_id, description), {
|
|
@@ -3997,9 +3997,9 @@ function gradingPolicyTools(canvas) {
|
|
|
3997
3997
|
latePolicySource = "api";
|
|
3998
3998
|
} else {
|
|
3999
3999
|
const err = latePolicyResult.reason;
|
|
4000
|
-
if (err instanceof
|
|
4000
|
+
if (err instanceof _chunkCZWLLOQCcjs.CanvasApiError && err.status === 403) {
|
|
4001
4001
|
policyUnavailable = true;
|
|
4002
|
-
} else if (err instanceof
|
|
4002
|
+
} else if (err instanceof _chunkCZWLLOQCcjs.CanvasApiError && err.status === 404) {
|
|
4003
4003
|
latePolicySource = "default";
|
|
4004
4004
|
} else {
|
|
4005
4005
|
throw err;
|
|
@@ -4029,7 +4029,7 @@ function gradingPolicyTools(canvas) {
|
|
|
4029
4029
|
}
|
|
4030
4030
|
}
|
|
4031
4031
|
} catch (err) {
|
|
4032
|
-
if (!(err instanceof
|
|
4032
|
+
if (!(err instanceof _chunkCZWLLOQCcjs.CanvasApiError)) throw err;
|
|
4033
4033
|
if (err.status !== 403 && err.status !== 404) throw err;
|
|
4034
4034
|
}
|
|
4035
4035
|
if (standardTitle === null) {
|
|
@@ -4159,7 +4159,7 @@ function gradingStandardsTools(canvas) {
|
|
|
4159
4159
|
}
|
|
4160
4160
|
throw new Error("Provide either course_id or account_id.");
|
|
4161
4161
|
} catch (error) {
|
|
4162
|
-
if (error instanceof
|
|
4162
|
+
if (error instanceof _chunkCZWLLOQCcjs.CanvasApiError && error.status === 403 && courseId === void 0 && accountId !== void 0 && !error.message.toLowerCase().includes("rate limit exceeded")) {
|
|
4163
4163
|
throw new Error(
|
|
4164
4164
|
"Creating grading standards at the account level requires Canvas admin permissions. Try creating the standard in a course context instead (use course_id).",
|
|
4165
4165
|
{ cause: error }
|
|
@@ -4519,7 +4519,7 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4519
4519
|
title: "Get Root Outcome Group",
|
|
4520
4520
|
description: "Get the root outcome group for an account or course context.",
|
|
4521
4521
|
inputSchema: {
|
|
4522
|
-
context_type: _zod.z.enum(
|
|
4522
|
+
context_type: _zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcomes from an account or course context."),
|
|
4523
4523
|
context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context.")
|
|
4524
4524
|
},
|
|
4525
4525
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
@@ -4533,7 +4533,7 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4533
4533
|
title: "List Outcome Groups",
|
|
4534
4534
|
description: "List all outcome groups for an account or course context.",
|
|
4535
4535
|
inputSchema: {
|
|
4536
|
-
context_type: _zod.z.enum(
|
|
4536
|
+
context_type: _zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcome groups from an account or course context."),
|
|
4537
4537
|
context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context.")
|
|
4538
4538
|
},
|
|
4539
4539
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
@@ -4547,10 +4547,10 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4547
4547
|
title: "List Outcome Group Links",
|
|
4548
4548
|
description: "List all outcome links in an account or course context.",
|
|
4549
4549
|
inputSchema: {
|
|
4550
|
-
context_type: _zod.z.enum(
|
|
4550
|
+
context_type: _zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcome links from an account or course context."),
|
|
4551
4551
|
context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context."),
|
|
4552
|
-
outcome_style: _zod.z.enum(
|
|
4553
|
-
outcome_group_style: _zod.z.enum(
|
|
4552
|
+
outcome_style: _zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_DETAIL_LEVELS).optional().describe('Outcome detail level. Use "full" to include expanded outcome fields.'),
|
|
4553
|
+
outcome_group_style: _zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_DETAIL_LEVELS).optional().describe(
|
|
4554
4554
|
'Outcome group detail level. Use "full" to include expanded outcome group fields.'
|
|
4555
4555
|
)
|
|
4556
4556
|
},
|
|
@@ -4569,7 +4569,7 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4569
4569
|
title: "Get Outcome Group",
|
|
4570
4570
|
description: "Get details for a specific outcome group in an account or course context.",
|
|
4571
4571
|
inputSchema: {
|
|
4572
|
-
context_type: _zod.z.enum(
|
|
4572
|
+
context_type: _zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
|
|
4573
4573
|
context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context."),
|
|
4574
4574
|
outcome_group_id: _zod.z.number().describe("The Canvas outcome group ID.")
|
|
4575
4575
|
},
|
|
@@ -4585,10 +4585,10 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4585
4585
|
title: "List Outcome Group Outcomes",
|
|
4586
4586
|
description: "List the linked outcomes directly under a specific outcome group.",
|
|
4587
4587
|
inputSchema: {
|
|
4588
|
-
context_type: _zod.z.enum(
|
|
4588
|
+
context_type: _zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
|
|
4589
4589
|
context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context."),
|
|
4590
4590
|
outcome_group_id: _zod.z.number().describe("The Canvas outcome group ID."),
|
|
4591
|
-
outcome_style: _zod.z.enum(
|
|
4591
|
+
outcome_style: _zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_DETAIL_LEVELS).optional().describe('Outcome detail level. Use "full" to include expanded outcome fields.')
|
|
4592
4592
|
},
|
|
4593
4593
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
4594
4594
|
handler: async (params) => canvas.outcomes.listGroupOutcomes(
|
|
@@ -4605,7 +4605,7 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4605
4605
|
title: "List Outcome Group Subgroups",
|
|
4606
4606
|
description: "List the immediate child outcome groups under a specific outcome group.",
|
|
4607
4607
|
inputSchema: {
|
|
4608
|
-
context_type: _zod.z.enum(
|
|
4608
|
+
context_type: _zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
|
|
4609
4609
|
context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context."),
|
|
4610
4610
|
outcome_group_id: _zod.z.number().describe("The Canvas outcome group ID.")
|
|
4611
4611
|
},
|
|
@@ -4675,14 +4675,14 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4675
4675
|
inputSchema: {
|
|
4676
4676
|
course_id: _zod.z.number().describe("The Canvas course ID."),
|
|
4677
4677
|
aggregate: _zod.z.enum(["course"]).optional().describe("Aggregate all student rollups into a single course-level rollup."),
|
|
4678
|
-
aggregate_stat: _zod.z.enum(
|
|
4678
|
+
aggregate_stat: _zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_ROLLUP_AGGREGATE_STATS).optional().describe('Statistic to use when aggregate="course".'),
|
|
4679
4679
|
user_ids: _zod.z.array(_zod.z.union([_zod.z.number(), _zod.z.string()])).optional().describe('Optional Canvas user IDs or SIS user IDs prefixed with "sis_user_id:".'),
|
|
4680
4680
|
outcome_ids: _zod.z.array(_zod.z.number()).optional().describe("Optional outcome IDs to restrict the rollups."),
|
|
4681
4681
|
include_courses: _zod.z.boolean().optional().describe("Include linked course details in the response payload."),
|
|
4682
|
-
exclude: _zod.z.array(_zod.z.enum(
|
|
4683
|
-
sort_by: _zod.z.enum(
|
|
4682
|
+
exclude: _zod.z.array(_zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_EXCLUDE_OPTIONS)).optional().describe("Optional rollup exclusions for missing users or missing outcome results."),
|
|
4683
|
+
sort_by: _zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_ROLLUP_SORT_BY).optional().describe("Sort rollups by student name or by a specific outcome score."),
|
|
4684
4684
|
sort_outcome_id: _zod.z.number().optional().describe('Outcome ID to sort by when sort_by="outcome".'),
|
|
4685
|
-
sort_order: _zod.z.enum(
|
|
4685
|
+
sort_order: _zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_SORT_ORDER).optional().describe("Sort order to apply when sorting rollups."),
|
|
4686
4686
|
add_defaults: _zod.z.boolean().optional().describe("Include default mastery colors and levels when Canvas supports it.")
|
|
4687
4687
|
},
|
|
4688
4688
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
@@ -4732,7 +4732,7 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4732
4732
|
description: "Get mastery distribution analytics for outcomes in a course, optionally filtered by students or outcomes.",
|
|
4733
4733
|
inputSchema: {
|
|
4734
4734
|
course_id: _zod.z.number().describe("The Canvas course ID."),
|
|
4735
|
-
exclude: _zod.z.array(_zod.z.enum(
|
|
4735
|
+
exclude: _zod.z.array(_zod.z.enum(_chunk7YQIQJKEcjs.OUTCOME_EXCLUDE_OPTIONS)).optional().describe("Optional exclusions for missing users or missing outcome results."),
|
|
4736
4736
|
outcome_ids: _zod.z.array(_zod.z.number()).optional().describe("Optional outcome IDs to restrict the distribution results."),
|
|
4737
4737
|
student_ids: _zod.z.array(_zod.z.union([_zod.z.number(), _zod.z.string()])).optional().describe('Optional Canvas student IDs or SIS user IDs prefixed with "sis_user_id:".'),
|
|
4738
4738
|
include_alignment_distributions: _zod.z.boolean().optional().describe("Include contributing score distributions for alignments."),
|
|
@@ -5582,7 +5582,7 @@ function newQuizAccommodationTools(canvas) {
|
|
|
5582
5582
|
extra_attempts: record.extra_attempts
|
|
5583
5583
|
});
|
|
5584
5584
|
} catch (err) {
|
|
5585
|
-
const message = err instanceof
|
|
5585
|
+
const message = err instanceof _chunkCZWLLOQCcjs.CanvasApiError ? err.message : "Unknown error";
|
|
5586
5586
|
failed.push({
|
|
5587
5587
|
assignment_id: assignmentId,
|
|
5588
5588
|
time_multiplier: null,
|
|
@@ -6122,8 +6122,8 @@ function studentTools(canvas, pseudonymizer) {
|
|
|
6122
6122
|
} else {
|
|
6123
6123
|
coursesFailed.push({
|
|
6124
6124
|
course_id: result.courseId,
|
|
6125
|
-
status: result.err instanceof
|
|
6126
|
-
message: result.err instanceof
|
|
6125
|
+
status: result.err instanceof _chunkCZWLLOQCcjs.CanvasApiError ? result.err.status : null,
|
|
6126
|
+
message: result.err instanceof _chunkCZWLLOQCcjs.CanvasApiError ? result.err.message : String(result.err)
|
|
6127
6127
|
});
|
|
6128
6128
|
}
|
|
6129
6129
|
}
|
|
@@ -6263,7 +6263,7 @@ function studentSearchTools(canvas, pseudonymizer) {
|
|
|
6263
6263
|
const coursesToScan = truncated ? sorted.slice(0, maxCourses) : sorted;
|
|
6264
6264
|
const coursesFailed = [];
|
|
6265
6265
|
const perCourseMatches = [];
|
|
6266
|
-
const scanResults = await
|
|
6266
|
+
const scanResults = await _chunk7YQIQJKEcjs.mapWithConcurrency.call(void 0,
|
|
6267
6267
|
coursesToScan,
|
|
6268
6268
|
CONCURRENT_COURSE_LIMIT,
|
|
6269
6269
|
async (course) => {
|
|
@@ -6286,8 +6286,8 @@ function studentSearchTools(canvas, pseudonymizer) {
|
|
|
6286
6286
|
} else {
|
|
6287
6287
|
coursesFailed.push({
|
|
6288
6288
|
course_id: r.course.id,
|
|
6289
|
-
status: r.err instanceof
|
|
6290
|
-
message: r.err instanceof
|
|
6289
|
+
status: r.err instanceof _chunkCZWLLOQCcjs.CanvasApiError ? r.err.status : null,
|
|
6290
|
+
message: r.err instanceof _chunkCZWLLOQCcjs.CanvasApiError ? r.err.message : String(r.err)
|
|
6291
6291
|
});
|
|
6292
6292
|
}
|
|
6293
6293
|
}
|
|
@@ -6965,7 +6965,7 @@ async function scanQuizzes(canvas, courseId, warnings) {
|
|
|
6965
6965
|
canvas.assignments.list(courseId)
|
|
6966
6966
|
]);
|
|
6967
6967
|
const classicQuizzes = quizzes.filter((quiz) => CLASSIC_QUIZ_TYPES3.has(quiz.quiz_type));
|
|
6968
|
-
const classicFindings = await
|
|
6968
|
+
const classicFindings = await _chunk7YQIQJKEcjs.mapWithConcurrency.call(void 0,
|
|
6969
6969
|
classicQuizzes,
|
|
6970
6970
|
QUIZ_SCAN_CONCURRENCY_LIMIT,
|
|
6971
6971
|
async (quiz) => {
|
|
@@ -6991,7 +6991,7 @@ async function scanQuizzes(canvas, courseId, warnings) {
|
|
|
6991
6991
|
}
|
|
6992
6992
|
);
|
|
6993
6993
|
const newQuizAssignments = assignments.filter((a) => a.is_quiz_lti_assignment === true);
|
|
6994
|
-
const newQuizFindings = await
|
|
6994
|
+
const newQuizFindings = await _chunk7YQIQJKEcjs.mapWithConcurrency.call(void 0,
|
|
6995
6995
|
newQuizAssignments,
|
|
6996
6996
|
QUIZ_SCAN_CONCURRENCY_LIMIT,
|
|
6997
6997
|
async (assignment) => {
|
|
@@ -7341,7 +7341,7 @@ async function scanQuizzesAccessibility(canvas, courseId, warnings) {
|
|
|
7341
7341
|
canvas.assignments.list(courseId)
|
|
7342
7342
|
]);
|
|
7343
7343
|
const classicQuizzes = quizzes.filter((quiz) => CLASSIC_QUIZ_TYPES4.has(quiz.quiz_type));
|
|
7344
|
-
const classicFindings = await
|
|
7344
|
+
const classicFindings = await _chunk7YQIQJKEcjs.mapWithConcurrency.call(void 0,
|
|
7345
7345
|
classicQuizzes,
|
|
7346
7346
|
QUIZ_SCAN_CONCURRENCY_LIMIT2,
|
|
7347
7347
|
async (quiz) => {
|
|
@@ -7366,7 +7366,7 @@ async function scanQuizzesAccessibility(canvas, courseId, warnings) {
|
|
|
7366
7366
|
}
|
|
7367
7367
|
);
|
|
7368
7368
|
const newQuizAssignments = assignments.filter((a) => a.is_quiz_lti_assignment === true);
|
|
7369
|
-
const newQuizFindings = await
|
|
7369
|
+
const newQuizFindings = await _chunk7YQIQJKEcjs.mapWithConcurrency.call(void 0,
|
|
7370
7370
|
newQuizAssignments,
|
|
7371
7371
|
QUIZ_SCAN_CONCURRENCY_LIMIT2,
|
|
7372
7372
|
async (assignment) => {
|
|
@@ -7979,7 +7979,7 @@ function buildHandler(tool, pseudonymizer) {
|
|
|
7979
7979
|
}
|
|
7980
7980
|
return response;
|
|
7981
7981
|
} catch (error) {
|
|
7982
|
-
if (!(error instanceof
|
|
7982
|
+
if (!(error instanceof _chunkCZWLLOQCcjs.CanvasApiError)) {
|
|
7983
7983
|
console.error(`Unexpected error in tool "${tool.name}":`, error);
|
|
7984
7984
|
}
|
|
7985
7985
|
return {
|
|
@@ -8067,7 +8067,7 @@ function registerSyllabusResource(server, canvas) {
|
|
|
8067
8067
|
]
|
|
8068
8068
|
};
|
|
8069
8069
|
} catch (error) {
|
|
8070
|
-
if (!(error instanceof
|
|
8070
|
+
if (!(error instanceof _chunkCZWLLOQCcjs.CanvasApiError)) {
|
|
8071
8071
|
console.error("Unexpected error in syllabus resource:", error);
|
|
8072
8072
|
}
|
|
8073
8073
|
return {
|
|
@@ -8121,7 +8121,7 @@ function registerAssignmentDescriptionResource(server, canvas) {
|
|
|
8121
8121
|
]
|
|
8122
8122
|
};
|
|
8123
8123
|
} catch (error) {
|
|
8124
|
-
if (!(error instanceof
|
|
8124
|
+
if (!(error instanceof _chunkCZWLLOQCcjs.CanvasApiError)) {
|
|
8125
8125
|
console.error("Unexpected error in assignment-description resource:", error);
|
|
8126
8126
|
}
|
|
8127
8127
|
return {
|
|
@@ -9521,14 +9521,14 @@ function resolvePseudonymizer(config) {
|
|
|
9521
9521
|
});
|
|
9522
9522
|
}
|
|
9523
9523
|
function createCanvasMCPServer(config) {
|
|
9524
|
-
const canvas = new (0,
|
|
9524
|
+
const canvas = new (0, _chunk7YQIQJKEcjs.CanvasClient)({
|
|
9525
9525
|
token: config.token,
|
|
9526
9526
|
baseUrl: config.baseUrl
|
|
9527
9527
|
});
|
|
9528
9528
|
const pseudonymizer = resolvePseudonymizer(config);
|
|
9529
9529
|
const server = new (0, _mcpjs.McpServer)({
|
|
9530
9530
|
name: "canvas-lms-mcp",
|
|
9531
|
-
version:
|
|
9531
|
+
version: _chunkCZWLLOQCcjs.version
|
|
9532
9532
|
});
|
|
9533
9533
|
const features = {
|
|
9534
9534
|
assignmentSubmission: config.enableAssignmentSubmission,
|
|
@@ -9549,4 +9549,4 @@ function createCanvasMCPServer(config) {
|
|
|
9549
9549
|
|
|
9550
9550
|
|
|
9551
9551
|
exports.Pseudonymizer = Pseudonymizer; exports.createSharedPseudonymizer = createSharedPseudonymizer; exports.createCanvasMCPServer = createCanvasMCPServer;
|
|
9552
|
-
//# sourceMappingURL=chunk-
|
|
9552
|
+
//# sourceMappingURL=chunk-3KSWLZGH.cjs.map
|