canvas-lms-mcp 1.29.2 → 1.29.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/dist/canvas/index.cjs +3 -3
- package/dist/canvas/index.js +2 -2
- package/dist/{chunk-FHB5523D.js → chunk-CALVQWQP.js} +2 -2
- package/dist/{chunk-FHB5523D.js.map → chunk-CALVQWQP.js.map} +1 -1
- package/dist/{chunk-3GRH22UA.js → chunk-FZEHZ7CJ.js} +2 -2
- package/dist/{chunk-TNJAWWDM.js → chunk-NLW4QKHX.js} +3 -3
- package/dist/{chunk-YI3DY6GQ.cjs → chunk-NSLFN2RA.cjs} +41 -41
- package/dist/{chunk-YI3DY6GQ.cjs.map → chunk-NSLFN2RA.cjs.map} +1 -1
- package/dist/{chunk-2ENRMOJW.cjs → chunk-OVMVID27.cjs} +2 -2
- package/dist/{chunk-2ENRMOJW.cjs.map → chunk-OVMVID27.cjs.map} +1 -1
- package/dist/{chunk-DWCGX2LJ.cjs → chunk-Q2CY33KV.cjs} +4 -4
- package/dist/{chunk-DWCGX2LJ.cjs.map → chunk-Q2CY33KV.cjs.map} +1 -1
- package/dist/http.cjs +5 -5
- 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-3GRH22UA.js.map → chunk-FZEHZ7CJ.js.map} +0 -0
- /package/dist/{chunk-TNJAWWDM.js.map → chunk-NLW4QKHX.js.map} +0 -0
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 _chunkQ2CY33KVcjs = require('../chunk-Q2CY33KV.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
var
|
|
9
|
+
var _chunkOVMVID27cjs = require('../chunk-OVMVID27.cjs');
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
exports.CanvasApiError =
|
|
16
|
+
exports.CanvasApiError = _chunkOVMVID27cjs.CanvasApiError; exports.CanvasClient = _chunkQ2CY33KVcjs.CanvasClient; exports.CanvasHttpClient = _chunkOVMVID27cjs.CanvasHttpClient; exports.appendCanvasQuery = _chunkOVMVID27cjs.appendCanvasQuery; exports.toCanvasQuery = _chunkOVMVID27cjs.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-FZEHZ7CJ.js";
|
|
4
4
|
import {
|
|
5
5
|
CanvasApiError,
|
|
6
6
|
CanvasHttpClient,
|
|
7
7
|
appendCanvasQuery,
|
|
8
8
|
toCanvasQuery
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-CALVQWQP.js";
|
|
10
10
|
export {
|
|
11
11
|
CanvasApiError,
|
|
12
12
|
CanvasClient,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// package.json
|
|
2
|
-
var version = "1.29.
|
|
2
|
+
var version = "1.29.3";
|
|
3
3
|
|
|
4
4
|
// src/canvas/query.ts
|
|
5
5
|
function appendCanvasQuery(target, params) {
|
|
@@ -163,4 +163,4 @@ export {
|
|
|
163
163
|
CanvasApiError,
|
|
164
164
|
CanvasHttpClient
|
|
165
165
|
};
|
|
166
|
-
//# sourceMappingURL=chunk-
|
|
166
|
+
//# sourceMappingURL=chunk-CALVQWQP.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json","../src/canvas/query.ts","../src/canvas/client.ts"],"sourcesContent":["{\n \"name\": \"canvas-lms-mcp\",\n \"version\": \"1.29.2\",\n \"mcpName\": \"io.github.bruchris/canvas-lms-mcp\",\n \"description\": \"TypeScript MCP 1.x server for Canvas LMS — 165 tools across Canvas courses, assignments, grades, gradebook history, quizzes, New Quizzes (LTI), outcomes, discussions, admin workflows, and more.\",\n \"type\": \"module\",\n \"types\": \"./dist/server.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/server.d.ts\",\n \"import\": \"./dist/server.js\",\n \"require\": \"./dist/server.cjs\"\n },\n \"./stdio\": {\n \"types\": \"./dist/stdio.d.ts\",\n \"import\": \"./dist/stdio.js\",\n \"require\": \"./dist/stdio.cjs\"\n },\n \"./http\": {\n \"types\": \"./dist/http.d.ts\",\n \"import\": \"./dist/http.js\",\n \"require\": \"./dist/http.cjs\"\n },\n \"./canvas\": {\n \"types\": \"./dist/canvas/index.d.ts\",\n \"import\": \"./dist/canvas/index.js\",\n \"require\": \"./dist/canvas/index.cjs\"\n }\n },\n \"bin\": {\n \"canvas-lms-mcp\": \"bin/canvas-lms-mcp.js\"\n },\n \"files\": [\n \"bin/\",\n \"dist/\"\n ],\n \"scripts\": {\n \"dev\": \"tsup --watch\",\n \"build\": \"tsup && tsc -p tsconfig.build.json\",\n \"generate:manifests\": \"tsx scripts/generate-manifests.ts\",\n \"mcpb:pack\": \"node scripts/pack-mcpb.mjs\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"lint\": \"eslint src/ tests/ && prettier --check src/ tests/\",\n \"lint:fix\": \"eslint src/ tests/ --fix && prettier --write src/ tests/\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"keywords\": [\n \"canvas\",\n \"canvas-lms\",\n \"lms\",\n \"mcp\",\n \"model-context-protocol\",\n \"education\",\n \"grading\",\n \"ai-agent\",\n \"ai-tools\",\n \"claude-desktop\",\n \"cursor\",\n \"vscode\",\n \"instructure\",\n \"education-technology\",\n \"edtech\",\n \"teacher\",\n \"student\",\n \"grading-automation\",\n \"typescript\"\n ],\n \"author\": \"Christian Bru\",\n \"license\": \"MIT\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/bruchris/canvas-lms-mcp.git\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"packageManager\": \"pnpm@10.11.0\",\n \"dependencies\": {\n \"@iarna/toml\": \"^2.2.5\",\n \"@modelcontextprotocol/sdk\": \"^1.30.0\",\n \"prompts\": \"^2.4.2\",\n \"zod\": \"^4.4.3\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^10.0.1\",\n \"@types/jsdom\": \"^30.0.0\",\n \"@types/node\": \"^26.4.0\",\n \"@types/prompts\": \"^2.4.9\",\n \"@typescript-eslint/eslint-plugin\": \"^8.65.0\",\n \"@typescript-eslint/parser\": \"^8.65.0\",\n \"@vitest/coverage-v8\": \"^4.1.10\",\n \"ajv\": \"^8.20.0\",\n \"eslint\": \"^10.7.0\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-prettier\": \"^5.5.6\",\n \"jsdom\": \"^30.0.1\",\n \"prettier\": \"^3.9.6\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.23.1\",\n \"typescript\": \"^6.0.3\",\n \"typescript-eslint\": \"^8.65.0\",\n \"vite\": \"^8.1.5\",\n \"vitest\": \"^4.1.10\"\n }\n}\n","export type CanvasQueryPrimitive = string | number | boolean\n\nexport type CanvasQueryValue = CanvasQueryPrimitive | ReadonlyArray<CanvasQueryPrimitive>\n\nexport type CanvasQueryParams = Record<string, CanvasQueryValue | undefined | null>\n\nexport function appendCanvasQuery(target: URLSearchParams, params?: CanvasQueryParams): void {\n if (!params) return\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined || value === null) continue\n if (Array.isArray(value)) {\n if (value.length === 0) continue\n const arrayKey = key.endsWith('[]') ? key : `${key}[]`\n for (const item of value) {\n if (item === undefined || item === null) continue\n target.append(arrayKey, String(item))\n }\n } else {\n target.set(key, String(value))\n }\n }\n}\n\nexport function toCanvasQuery(params?: CanvasQueryParams): URLSearchParams {\n const search = new URLSearchParams()\n appendCanvasQuery(search, params)\n return search\n}\n","import { version } from '../../package.json'\nimport { appendCanvasQuery, type CanvasQueryParams } from './query'\nimport type { CanvasClientConfig, CanvasErrorResponse } from './types'\n\nexport class CanvasApiError extends Error {\n status: number\n endpoint: string\n\n constructor(message: string, status: number, endpoint: string) {\n super(message)\n this.name = 'CanvasApiError'\n this.status = status\n this.endpoint = endpoint\n }\n}\n\nconst DEFAULT_MAX_PAGINATION_PAGES = 1000\nconst USER_AGENT = `canvas-lms-mcp/${version}`\n\nexport interface CanvasRequestOptions extends RequestInit {\n /**\n * Query params to append to the endpoint URL. Arrays produce repeated\n * `key[]=v1&key[]=v2` entries (the convention Canvas uses for `include[]`).\n * Preserves any query string already present on the endpoint.\n */\n query?: CanvasQueryParams\n}\n\nexport class CanvasHttpClient {\n private token: string\n private _baseUrl: string\n private maxPaginationPages: number\n\n constructor(config: CanvasClientConfig) {\n this.token = config.token\n this._baseUrl = config.baseUrl.replace(/\\/+$/, '')\n this.maxPaginationPages = config.maxPaginationPages ?? DEFAULT_MAX_PAGINATION_PAGES\n }\n\n get baseUrl(): string {\n return this._baseUrl\n }\n\n /**\n * Makes a single authenticated request to the Canvas API.\n * Returns `undefined` (typed as `T`) when Canvas responds with 204 No Content,\n * which is the expected response for DELETE operations.\n */\n async request<T>(endpoint: string, options: CanvasRequestOptions = {}): Promise<T> {\n const { query, ...init } = options\n let url = endpoint.startsWith('http') ? endpoint : `${this._baseUrl}${endpoint}`\n if (query) {\n const parsed = new URL(url)\n appendCanvasQuery(parsed.searchParams, query)\n url = parsed.toString()\n }\n\n const method = (init.method ?? 'GET').toUpperCase()\n if (init.body != null && (method === 'GET' || method === 'HEAD')) {\n throw new Error(\n `GET requests must not include a body (Canvas CloudFront CDN rejects them with 403): ${endpoint}`,\n )\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.token}`,\n 'User-Agent': USER_AGENT,\n }\n if (init.body) {\n headers['Content-Type'] = 'application/json'\n }\n\n const response = await fetch(url, {\n ...init,\n headers: {\n ...headers,\n ...init.headers,\n },\n })\n\n if (!response.ok) {\n const body = (await response.json().catch(() => ({}))) as CanvasErrorResponse\n const message =\n body.errors?.[0]?.message ?? body.message ?? `Canvas API error: ${response.status}`\n throw new CanvasApiError(message, response.status, endpoint)\n }\n\n if (response.status === 204) {\n return undefined as T\n }\n\n return response.json() as Promise<T>\n }\n\n async paginate<T>(endpoint: string, params?: CanvasQueryParams): Promise<T[]> {\n const url = new URL(`${this._baseUrl}${endpoint}`)\n if (!url.searchParams.has('per_page')) {\n url.searchParams.set('per_page', '100')\n }\n appendCanvasQuery(url.searchParams, params)\n\n const results: T[] = []\n let nextUrl: string | null = url.toString()\n let pages = 0\n\n while (nextUrl && pages < this.maxPaginationPages) {\n const response = await fetch(nextUrl, {\n headers: {\n Authorization: `Bearer ${this.token}`,\n 'User-Agent': USER_AGENT,\n },\n })\n\n if (!response.ok) {\n const body = (await response.json().catch(() => ({}))) as CanvasErrorResponse\n const message =\n body.errors?.[0]?.message ?? body.message ?? `Canvas API error: ${response.status}`\n throw new CanvasApiError(message, response.status, endpoint)\n }\n\n const data = (await response.json()) as T[]\n results.push(...data)\n pages++\n\n nextUrl = this.parseNextLink(response.headers.get('Link'))\n }\n\n return results\n }\n\n async paginateEnvelope<T>(\n endpoint: string,\n envelopeKey: string,\n params?: CanvasQueryParams,\n ): Promise<T[]> {\n const url = new URL(`${this._baseUrl}${endpoint}`)\n if (!url.searchParams.has('per_page')) {\n url.searchParams.set('per_page', '100')\n }\n appendCanvasQuery(url.searchParams, params)\n\n const results: T[] = []\n let nextUrl: string | null = url.toString()\n let pages = 0\n\n while (nextUrl && pages < this.maxPaginationPages) {\n const response = await fetch(nextUrl, {\n headers: {\n Authorization: `Bearer ${this.token}`,\n 'User-Agent': USER_AGENT,\n },\n })\n\n if (!response.ok) {\n const body = (await response.json().catch(() => ({}))) as CanvasErrorResponse\n const message =\n body.errors?.[0]?.message ?? body.message ?? `Canvas API error: ${response.status}`\n throw new CanvasApiError(message, response.status, endpoint)\n }\n\n const body = (await response.json()) as Record<string, T[]>\n const data = body[envelopeKey] ?? []\n results.push(...data)\n pages++\n\n nextUrl = this.parseNextLink(response.headers.get('Link'))\n }\n\n return results\n }\n\n private parseNextLink(linkHeader: string | null): string | null {\n if (!linkHeader) return null\n const match = linkHeader.match(/<([^>]+)>;\\s*rel=\"next\"/)\n return match?.[1] ?? null\n }\n}\n"],"mappings":"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","names":["body"]}
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/canvas/query.ts","../src/canvas/client.ts"],"sourcesContent":["{\n \"name\": \"canvas-lms-mcp\",\n \"version\": \"1.29.3\",\n \"mcpName\": \"io.github.bruchris/canvas-lms-mcp\",\n \"description\": \"TypeScript MCP 1.x server for Canvas LMS — 165 tools across Canvas courses, assignments, grades, gradebook history, quizzes, New Quizzes (LTI), outcomes, discussions, admin workflows, and more.\",\n \"type\": \"module\",\n \"types\": \"./dist/server.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/server.d.ts\",\n \"import\": \"./dist/server.js\",\n \"require\": \"./dist/server.cjs\"\n },\n \"./stdio\": {\n \"types\": \"./dist/stdio.d.ts\",\n \"import\": \"./dist/stdio.js\",\n \"require\": \"./dist/stdio.cjs\"\n },\n \"./http\": {\n \"types\": \"./dist/http.d.ts\",\n \"import\": \"./dist/http.js\",\n \"require\": \"./dist/http.cjs\"\n },\n \"./canvas\": {\n \"types\": \"./dist/canvas/index.d.ts\",\n \"import\": \"./dist/canvas/index.js\",\n \"require\": \"./dist/canvas/index.cjs\"\n }\n },\n \"bin\": {\n \"canvas-lms-mcp\": \"bin/canvas-lms-mcp.js\"\n },\n \"files\": [\n \"bin/\",\n \"dist/\"\n ],\n \"scripts\": {\n \"dev\": \"tsup --watch\",\n \"build\": \"tsup && tsc -p tsconfig.build.json\",\n \"generate:manifests\": \"tsx scripts/generate-manifests.ts\",\n \"mcpb:pack\": \"node scripts/pack-mcpb.mjs\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"lint\": \"eslint src/ tests/ && prettier --check src/ tests/\",\n \"lint:fix\": \"eslint src/ tests/ --fix && prettier --write src/ tests/\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"keywords\": [\n \"canvas\",\n \"canvas-lms\",\n \"lms\",\n \"mcp\",\n \"model-context-protocol\",\n \"education\",\n \"grading\",\n \"ai-agent\",\n \"ai-tools\",\n \"claude-desktop\",\n \"cursor\",\n \"vscode\",\n \"instructure\",\n \"education-technology\",\n \"edtech\",\n \"teacher\",\n \"student\",\n \"grading-automation\",\n \"typescript\"\n ],\n \"author\": \"Christian Bru\",\n \"license\": \"MIT\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/bruchris/canvas-lms-mcp.git\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"packageManager\": \"pnpm@10.11.0\",\n \"dependencies\": {\n \"@iarna/toml\": \"^2.2.5\",\n \"@modelcontextprotocol/sdk\": \"^1.30.0\",\n \"prompts\": \"^2.4.2\",\n \"zod\": \"^4.4.3\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^10.0.1\",\n \"@types/jsdom\": \"^30.0.0\",\n \"@types/node\": \"^26.4.0\",\n \"@types/prompts\": \"^2.4.9\",\n \"@typescript-eslint/eslint-plugin\": \"^8.65.0\",\n \"@typescript-eslint/parser\": \"^8.65.0\",\n \"@vitest/coverage-v8\": \"^4.1.10\",\n \"ajv\": \"^8.20.0\",\n \"eslint\": \"^10.7.0\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-prettier\": \"^5.5.6\",\n \"jsdom\": \"^30.0.1\",\n \"prettier\": \"^3.9.6\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.23.1\",\n \"typescript\": \"^6.0.3\",\n \"typescript-eslint\": \"^8.65.0\",\n \"vite\": \"^8.1.5\",\n \"vitest\": \"^4.1.10\"\n }\n}\n","export type CanvasQueryPrimitive = string | number | boolean\n\nexport type CanvasQueryValue = CanvasQueryPrimitive | ReadonlyArray<CanvasQueryPrimitive>\n\nexport type CanvasQueryParams = Record<string, CanvasQueryValue | undefined | null>\n\nexport function appendCanvasQuery(target: URLSearchParams, params?: CanvasQueryParams): void {\n if (!params) return\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined || value === null) continue\n if (Array.isArray(value)) {\n if (value.length === 0) continue\n const arrayKey = key.endsWith('[]') ? key : `${key}[]`\n for (const item of value) {\n if (item === undefined || item === null) continue\n target.append(arrayKey, String(item))\n }\n } else {\n target.set(key, String(value))\n }\n }\n}\n\nexport function toCanvasQuery(params?: CanvasQueryParams): URLSearchParams {\n const search = new URLSearchParams()\n appendCanvasQuery(search, params)\n return search\n}\n","import { version } from '../../package.json'\nimport { appendCanvasQuery, type CanvasQueryParams } from './query'\nimport type { CanvasClientConfig, CanvasErrorResponse } from './types'\n\nexport class CanvasApiError extends Error {\n status: number\n endpoint: string\n\n constructor(message: string, status: number, endpoint: string) {\n super(message)\n this.name = 'CanvasApiError'\n this.status = status\n this.endpoint = endpoint\n }\n}\n\nconst DEFAULT_MAX_PAGINATION_PAGES = 1000\nconst USER_AGENT = `canvas-lms-mcp/${version}`\n\nexport interface CanvasRequestOptions extends RequestInit {\n /**\n * Query params to append to the endpoint URL. Arrays produce repeated\n * `key[]=v1&key[]=v2` entries (the convention Canvas uses for `include[]`).\n * Preserves any query string already present on the endpoint.\n */\n query?: CanvasQueryParams\n}\n\nexport class CanvasHttpClient {\n private token: string\n private _baseUrl: string\n private maxPaginationPages: number\n\n constructor(config: CanvasClientConfig) {\n this.token = config.token\n this._baseUrl = config.baseUrl.replace(/\\/+$/, '')\n this.maxPaginationPages = config.maxPaginationPages ?? DEFAULT_MAX_PAGINATION_PAGES\n }\n\n get baseUrl(): string {\n return this._baseUrl\n }\n\n /**\n * Makes a single authenticated request to the Canvas API.\n * Returns `undefined` (typed as `T`) when Canvas responds with 204 No Content,\n * which is the expected response for DELETE operations.\n */\n async request<T>(endpoint: string, options: CanvasRequestOptions = {}): Promise<T> {\n const { query, ...init } = options\n let url = endpoint.startsWith('http') ? endpoint : `${this._baseUrl}${endpoint}`\n if (query) {\n const parsed = new URL(url)\n appendCanvasQuery(parsed.searchParams, query)\n url = parsed.toString()\n }\n\n const method = (init.method ?? 'GET').toUpperCase()\n if (init.body != null && (method === 'GET' || method === 'HEAD')) {\n throw new Error(\n `GET requests must not include a body (Canvas CloudFront CDN rejects them with 403): ${endpoint}`,\n )\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.token}`,\n 'User-Agent': USER_AGENT,\n }\n if (init.body) {\n headers['Content-Type'] = 'application/json'\n }\n\n const response = await fetch(url, {\n ...init,\n headers: {\n ...headers,\n ...init.headers,\n },\n })\n\n if (!response.ok) {\n const body = (await response.json().catch(() => ({}))) as CanvasErrorResponse\n const message =\n body.errors?.[0]?.message ?? body.message ?? `Canvas API error: ${response.status}`\n throw new CanvasApiError(message, response.status, endpoint)\n }\n\n if (response.status === 204) {\n return undefined as T\n }\n\n return response.json() as Promise<T>\n }\n\n async paginate<T>(endpoint: string, params?: CanvasQueryParams): Promise<T[]> {\n const url = new URL(`${this._baseUrl}${endpoint}`)\n if (!url.searchParams.has('per_page')) {\n url.searchParams.set('per_page', '100')\n }\n appendCanvasQuery(url.searchParams, params)\n\n const results: T[] = []\n let nextUrl: string | null = url.toString()\n let pages = 0\n\n while (nextUrl && pages < this.maxPaginationPages) {\n const response = await fetch(nextUrl, {\n headers: {\n Authorization: `Bearer ${this.token}`,\n 'User-Agent': USER_AGENT,\n },\n })\n\n if (!response.ok) {\n const body = (await response.json().catch(() => ({}))) as CanvasErrorResponse\n const message =\n body.errors?.[0]?.message ?? body.message ?? `Canvas API error: ${response.status}`\n throw new CanvasApiError(message, response.status, endpoint)\n }\n\n const data = (await response.json()) as T[]\n results.push(...data)\n pages++\n\n nextUrl = this.parseNextLink(response.headers.get('Link'))\n }\n\n return results\n }\n\n async paginateEnvelope<T>(\n endpoint: string,\n envelopeKey: string,\n params?: CanvasQueryParams,\n ): Promise<T[]> {\n const url = new URL(`${this._baseUrl}${endpoint}`)\n if (!url.searchParams.has('per_page')) {\n url.searchParams.set('per_page', '100')\n }\n appendCanvasQuery(url.searchParams, params)\n\n const results: T[] = []\n let nextUrl: string | null = url.toString()\n let pages = 0\n\n while (nextUrl && pages < this.maxPaginationPages) {\n const response = await fetch(nextUrl, {\n headers: {\n Authorization: `Bearer ${this.token}`,\n 'User-Agent': USER_AGENT,\n },\n })\n\n if (!response.ok) {\n const body = (await response.json().catch(() => ({}))) as CanvasErrorResponse\n const message =\n body.errors?.[0]?.message ?? body.message ?? `Canvas API error: ${response.status}`\n throw new CanvasApiError(message, response.status, endpoint)\n }\n\n const body = (await response.json()) as Record<string, T[]>\n const data = body[envelopeKey] ?? []\n results.push(...data)\n pages++\n\n nextUrl = this.parseNextLink(response.headers.get('Link'))\n }\n\n return results\n }\n\n private parseNextLink(linkHeader: string | null): string | null {\n if (!linkHeader) return null\n const match = linkHeader.match(/<([^>]+)>;\\s*rel=\"next\"/)\n return match?.[1] ?? null\n }\n}\n"],"mappings":"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","names":["body"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CanvasApiError,
|
|
3
3
|
CanvasHttpClient
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-CALVQWQP.js";
|
|
5
5
|
|
|
6
6
|
// src/canvas/courses.ts
|
|
7
7
|
var DEFAULT_LIST_INCLUDE = ["term"];
|
|
@@ -1771,4 +1771,4 @@ export {
|
|
|
1771
1771
|
OUTCOME_EXCLUDE_OPTIONS,
|
|
1772
1772
|
CanvasClient
|
|
1773
1773
|
};
|
|
1774
|
-
//# sourceMappingURL=chunk-
|
|
1774
|
+
//# sourceMappingURL=chunk-FZEHZ7CJ.js.map
|
|
@@ -18,11 +18,11 @@ import {
|
|
|
18
18
|
OUTCOME_SORT_ORDER,
|
|
19
19
|
SEARCH_CONTENT_TYPES,
|
|
20
20
|
mapWithConcurrency
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-FZEHZ7CJ.js";
|
|
22
22
|
import {
|
|
23
23
|
CanvasApiError,
|
|
24
24
|
version
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-CALVQWQP.js";
|
|
26
26
|
|
|
27
27
|
// src/server.ts
|
|
28
28
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -9058,4 +9058,4 @@ export {
|
|
|
9058
9058
|
createSharedPseudonymizer,
|
|
9059
9059
|
createCanvasMCPServer
|
|
9060
9060
|
};
|
|
9061
|
-
//# sourceMappingURL=chunk-
|
|
9061
|
+
//# sourceMappingURL=chunk-NLW4QKHX.js.map
|
|
@@ -18,11 +18,11 @@ var _chunkOOP4MJA7cjs = require('./chunk-OOP4MJA7.cjs');
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
var
|
|
21
|
+
var _chunkQ2CY33KVcjs = require('./chunk-Q2CY33KV.cjs');
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
var
|
|
25
|
+
var _chunkOVMVID27cjs = require('./chunk-OVMVID27.cjs');
|
|
26
26
|
|
|
27
27
|
// src/server.ts
|
|
28
28
|
var _mcpjs = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
@@ -986,7 +986,7 @@ function assignmentSubmissionTools(canvas) {
|
|
|
986
986
|
|
|
987
987
|
// src/tools/errors.ts
|
|
988
988
|
function formatError(error) {
|
|
989
|
-
if (error instanceof
|
|
989
|
+
if (error instanceof _chunkOVMVID27cjs.CanvasApiError) {
|
|
990
990
|
const status = error.status;
|
|
991
991
|
const message = error.message;
|
|
992
992
|
const ltiMarkers = ["Tool not configured", "tool is not configured"];
|
|
@@ -1040,7 +1040,7 @@ function analyticsTools(canvas) {
|
|
|
1040
1040
|
inputSchema: {
|
|
1041
1041
|
course_id: _zod.z.number().describe("The Canvas course ID"),
|
|
1042
1042
|
search_term: _zod.z.string().describe("The keyword or phrase to search for"),
|
|
1043
|
-
content_types: _zod.z.array(_zod.z.enum(
|
|
1043
|
+
content_types: _zod.z.array(_zod.z.enum(_chunkQ2CY33KVcjs.SEARCH_CONTENT_TYPES)).optional().describe(
|
|
1044
1044
|
"Content types to search. Defaults to all types: pages, discussions, assignments, announcements."
|
|
1045
1045
|
)
|
|
1046
1046
|
},
|
|
@@ -1052,7 +1052,7 @@ function analyticsTools(canvas) {
|
|
|
1052
1052
|
const courseId = params.course_id;
|
|
1053
1053
|
const searchTerm = params.search_term;
|
|
1054
1054
|
const types = _nullishCoalesce(params.content_types, () => ( [
|
|
1055
|
-
...
|
|
1055
|
+
..._chunkQ2CY33KVcjs.SEARCH_CONTENT_TYPES
|
|
1056
1056
|
]));
|
|
1057
1057
|
if (types.length === 0) return { results: [] };
|
|
1058
1058
|
const settled = await Promise.allSettled(
|
|
@@ -1305,7 +1305,7 @@ function attentionTools(canvas, pseudonymizer) {
|
|
|
1305
1305
|
summaryMap.set(s.id, s);
|
|
1306
1306
|
}
|
|
1307
1307
|
} catch (err) {
|
|
1308
|
-
if (err instanceof
|
|
1308
|
+
if (err instanceof _chunkOVMVID27cjs.CanvasApiError && err.status === 404) {
|
|
1309
1309
|
analyticsAvailable = false;
|
|
1310
1310
|
} else {
|
|
1311
1311
|
throw err;
|
|
@@ -1649,7 +1649,7 @@ async function fanOut(config) {
|
|
|
1649
1649
|
skipped.push(outcome.result);
|
|
1650
1650
|
}
|
|
1651
1651
|
} catch (err) {
|
|
1652
|
-
if (!(err instanceof
|
|
1652
|
+
if (!(err instanceof _chunkOVMVID27cjs.CanvasApiError)) {
|
|
1653
1653
|
console.error(`Unexpected error ${config.errorContext(item)}:`, err);
|
|
1654
1654
|
}
|
|
1655
1655
|
const message = err instanceof Error ? err.message : "Unknown error";
|
|
@@ -3950,9 +3950,9 @@ function gradingPolicyTools(canvas) {
|
|
|
3950
3950
|
latePolicySource = "api";
|
|
3951
3951
|
} else {
|
|
3952
3952
|
const err = latePolicyResult.reason;
|
|
3953
|
-
if (err instanceof
|
|
3953
|
+
if (err instanceof _chunkOVMVID27cjs.CanvasApiError && err.status === 403) {
|
|
3954
3954
|
policyUnavailable = true;
|
|
3955
|
-
} else if (err instanceof
|
|
3955
|
+
} else if (err instanceof _chunkOVMVID27cjs.CanvasApiError && err.status === 404) {
|
|
3956
3956
|
latePolicySource = "default";
|
|
3957
3957
|
} else {
|
|
3958
3958
|
throw err;
|
|
@@ -3982,7 +3982,7 @@ function gradingPolicyTools(canvas) {
|
|
|
3982
3982
|
}
|
|
3983
3983
|
}
|
|
3984
3984
|
} catch (err) {
|
|
3985
|
-
if (!(err instanceof
|
|
3985
|
+
if (!(err instanceof _chunkOVMVID27cjs.CanvasApiError)) throw err;
|
|
3986
3986
|
if (err.status !== 403 && err.status !== 404) throw err;
|
|
3987
3987
|
}
|
|
3988
3988
|
if (standardTitle === null) {
|
|
@@ -4112,7 +4112,7 @@ function gradingStandardsTools(canvas) {
|
|
|
4112
4112
|
}
|
|
4113
4113
|
throw new Error("Provide either course_id or account_id.");
|
|
4114
4114
|
} catch (error) {
|
|
4115
|
-
if (error instanceof
|
|
4115
|
+
if (error instanceof _chunkOVMVID27cjs.CanvasApiError && error.status === 403 && courseId === void 0 && accountId !== void 0 && !error.message.toLowerCase().includes("rate limit exceeded")) {
|
|
4116
4116
|
throw new Error(
|
|
4117
4117
|
"Creating grading standards at the account level requires Canvas admin permissions. Try creating the standard in a course context instead (use course_id).",
|
|
4118
4118
|
{ cause: error }
|
|
@@ -4423,7 +4423,7 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4423
4423
|
title: "Get Root Outcome Group",
|
|
4424
4424
|
description: "Get the root outcome group for an account or course context.",
|
|
4425
4425
|
inputSchema: {
|
|
4426
|
-
context_type: _zod.z.enum(
|
|
4426
|
+
context_type: _zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcomes from an account or course context."),
|
|
4427
4427
|
context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context.")
|
|
4428
4428
|
},
|
|
4429
4429
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
@@ -4437,7 +4437,7 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4437
4437
|
title: "List Outcome Groups",
|
|
4438
4438
|
description: "List all outcome groups for an account or course context.",
|
|
4439
4439
|
inputSchema: {
|
|
4440
|
-
context_type: _zod.z.enum(
|
|
4440
|
+
context_type: _zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcome groups from an account or course context."),
|
|
4441
4441
|
context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context.")
|
|
4442
4442
|
},
|
|
4443
4443
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
@@ -4451,10 +4451,10 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4451
4451
|
title: "List Outcome Group Links",
|
|
4452
4452
|
description: "List all outcome links in an account or course context.",
|
|
4453
4453
|
inputSchema: {
|
|
4454
|
-
context_type: _zod.z.enum(
|
|
4454
|
+
context_type: _zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcome links from an account or course context."),
|
|
4455
4455
|
context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context."),
|
|
4456
|
-
outcome_style: _zod.z.enum(
|
|
4457
|
-
outcome_group_style: _zod.z.enum(
|
|
4456
|
+
outcome_style: _zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_DETAIL_LEVELS).optional().describe('Outcome detail level. Use "full" to include expanded outcome fields.'),
|
|
4457
|
+
outcome_group_style: _zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_DETAIL_LEVELS).optional().describe(
|
|
4458
4458
|
'Outcome group detail level. Use "full" to include expanded outcome group fields.'
|
|
4459
4459
|
)
|
|
4460
4460
|
},
|
|
@@ -4473,7 +4473,7 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4473
4473
|
title: "Get Outcome Group",
|
|
4474
4474
|
description: "Get details for a specific outcome group in an account or course context.",
|
|
4475
4475
|
inputSchema: {
|
|
4476
|
-
context_type: _zod.z.enum(
|
|
4476
|
+
context_type: _zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
|
|
4477
4477
|
context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context."),
|
|
4478
4478
|
outcome_group_id: _zod.z.number().describe("The Canvas outcome group ID.")
|
|
4479
4479
|
},
|
|
@@ -4489,10 +4489,10 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4489
4489
|
title: "List Outcome Group Outcomes",
|
|
4490
4490
|
description: "List the linked outcomes directly under a specific outcome group.",
|
|
4491
4491
|
inputSchema: {
|
|
4492
|
-
context_type: _zod.z.enum(
|
|
4492
|
+
context_type: _zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
|
|
4493
4493
|
context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context."),
|
|
4494
4494
|
outcome_group_id: _zod.z.number().describe("The Canvas outcome group ID."),
|
|
4495
|
-
outcome_style: _zod.z.enum(
|
|
4495
|
+
outcome_style: _zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_DETAIL_LEVELS).optional().describe('Outcome detail level. Use "full" to include expanded outcome fields.')
|
|
4496
4496
|
},
|
|
4497
4497
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
4498
4498
|
handler: async (params) => canvas.outcomes.listGroupOutcomes(
|
|
@@ -4509,7 +4509,7 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4509
4509
|
title: "List Outcome Group Subgroups",
|
|
4510
4510
|
description: "List the immediate child outcome groups under a specific outcome group.",
|
|
4511
4511
|
inputSchema: {
|
|
4512
|
-
context_type: _zod.z.enum(
|
|
4512
|
+
context_type: _zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
|
|
4513
4513
|
context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context."),
|
|
4514
4514
|
outcome_group_id: _zod.z.number().describe("The Canvas outcome group ID.")
|
|
4515
4515
|
},
|
|
@@ -4579,14 +4579,14 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4579
4579
|
inputSchema: {
|
|
4580
4580
|
course_id: _zod.z.number().describe("The Canvas course ID."),
|
|
4581
4581
|
aggregate: _zod.z.enum(["course"]).optional().describe("Aggregate all student rollups into a single course-level rollup."),
|
|
4582
|
-
aggregate_stat: _zod.z.enum(
|
|
4582
|
+
aggregate_stat: _zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_ROLLUP_AGGREGATE_STATS).optional().describe('Statistic to use when aggregate="course".'),
|
|
4583
4583
|
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:".'),
|
|
4584
4584
|
outcome_ids: _zod.z.array(_zod.z.number()).optional().describe("Optional outcome IDs to restrict the rollups."),
|
|
4585
4585
|
include_courses: _zod.z.boolean().optional().describe("Include linked course details in the response payload."),
|
|
4586
|
-
exclude: _zod.z.array(_zod.z.enum(
|
|
4587
|
-
sort_by: _zod.z.enum(
|
|
4586
|
+
exclude: _zod.z.array(_zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_EXCLUDE_OPTIONS)).optional().describe("Optional rollup exclusions for missing users or missing outcome results."),
|
|
4587
|
+
sort_by: _zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_ROLLUP_SORT_BY).optional().describe("Sort rollups by student name or by a specific outcome score."),
|
|
4588
4588
|
sort_outcome_id: _zod.z.number().optional().describe('Outcome ID to sort by when sort_by="outcome".'),
|
|
4589
|
-
sort_order: _zod.z.enum(
|
|
4589
|
+
sort_order: _zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_SORT_ORDER).optional().describe("Sort order to apply when sorting rollups."),
|
|
4590
4590
|
add_defaults: _zod.z.boolean().optional().describe("Include default mastery colors and levels when Canvas supports it.")
|
|
4591
4591
|
},
|
|
4592
4592
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
@@ -4636,7 +4636,7 @@ function outcomeTools(canvas, pseudonymizer) {
|
|
|
4636
4636
|
description: "Get mastery distribution analytics for outcomes in a course, optionally filtered by students or outcomes.",
|
|
4637
4637
|
inputSchema: {
|
|
4638
4638
|
course_id: _zod.z.number().describe("The Canvas course ID."),
|
|
4639
|
-
exclude: _zod.z.array(_zod.z.enum(
|
|
4639
|
+
exclude: _zod.z.array(_zod.z.enum(_chunkQ2CY33KVcjs.OUTCOME_EXCLUDE_OPTIONS)).optional().describe("Optional exclusions for missing users or missing outcome results."),
|
|
4640
4640
|
outcome_ids: _zod.z.array(_zod.z.number()).optional().describe("Optional outcome IDs to restrict the distribution results."),
|
|
4641
4641
|
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:".'),
|
|
4642
4642
|
include_alignment_distributions: _zod.z.boolean().optional().describe("Include contributing score distributions for alignments."),
|
|
@@ -5416,7 +5416,7 @@ function newQuizAccommodationTools(canvas) {
|
|
|
5416
5416
|
extra_attempts: record.extra_attempts
|
|
5417
5417
|
});
|
|
5418
5418
|
} catch (err) {
|
|
5419
|
-
const message = err instanceof
|
|
5419
|
+
const message = err instanceof _chunkOVMVID27cjs.CanvasApiError ? err.message : "Unknown error";
|
|
5420
5420
|
failed.push({
|
|
5421
5421
|
assignment_id: assignmentId,
|
|
5422
5422
|
time_multiplier: null,
|
|
@@ -5956,8 +5956,8 @@ function studentTools(canvas, pseudonymizer) {
|
|
|
5956
5956
|
} else {
|
|
5957
5957
|
coursesFailed.push({
|
|
5958
5958
|
course_id: result.courseId,
|
|
5959
|
-
status: result.err instanceof
|
|
5960
|
-
message: result.err instanceof
|
|
5959
|
+
status: result.err instanceof _chunkOVMVID27cjs.CanvasApiError ? result.err.status : null,
|
|
5960
|
+
message: result.err instanceof _chunkOVMVID27cjs.CanvasApiError ? result.err.message : String(result.err)
|
|
5961
5961
|
});
|
|
5962
5962
|
}
|
|
5963
5963
|
}
|
|
@@ -6097,7 +6097,7 @@ function studentSearchTools(canvas, pseudonymizer) {
|
|
|
6097
6097
|
const coursesToScan = truncated ? sorted.slice(0, maxCourses) : sorted;
|
|
6098
6098
|
const coursesFailed = [];
|
|
6099
6099
|
const perCourseMatches = [];
|
|
6100
|
-
const scanResults = await
|
|
6100
|
+
const scanResults = await _chunkQ2CY33KVcjs.mapWithConcurrency.call(void 0,
|
|
6101
6101
|
coursesToScan,
|
|
6102
6102
|
CONCURRENT_COURSE_LIMIT,
|
|
6103
6103
|
async (course) => {
|
|
@@ -6120,8 +6120,8 @@ function studentSearchTools(canvas, pseudonymizer) {
|
|
|
6120
6120
|
} else {
|
|
6121
6121
|
coursesFailed.push({
|
|
6122
6122
|
course_id: r.course.id,
|
|
6123
|
-
status: r.err instanceof
|
|
6124
|
-
message: r.err instanceof
|
|
6123
|
+
status: r.err instanceof _chunkOVMVID27cjs.CanvasApiError ? r.err.status : null,
|
|
6124
|
+
message: r.err instanceof _chunkOVMVID27cjs.CanvasApiError ? r.err.message : String(r.err)
|
|
6125
6125
|
});
|
|
6126
6126
|
}
|
|
6127
6127
|
}
|
|
@@ -6799,7 +6799,7 @@ async function scanQuizzes(canvas, courseId, warnings) {
|
|
|
6799
6799
|
canvas.assignments.list(courseId)
|
|
6800
6800
|
]);
|
|
6801
6801
|
const classicQuizzes = quizzes.filter((quiz) => CLASSIC_QUIZ_TYPES3.has(quiz.quiz_type));
|
|
6802
|
-
const classicFindings = await
|
|
6802
|
+
const classicFindings = await _chunkQ2CY33KVcjs.mapWithConcurrency.call(void 0,
|
|
6803
6803
|
classicQuizzes,
|
|
6804
6804
|
QUIZ_SCAN_CONCURRENCY_LIMIT,
|
|
6805
6805
|
async (quiz) => {
|
|
@@ -6825,7 +6825,7 @@ async function scanQuizzes(canvas, courseId, warnings) {
|
|
|
6825
6825
|
}
|
|
6826
6826
|
);
|
|
6827
6827
|
const newQuizAssignments = assignments.filter((a) => a.is_quiz_lti_assignment === true);
|
|
6828
|
-
const newQuizFindings = await
|
|
6828
|
+
const newQuizFindings = await _chunkQ2CY33KVcjs.mapWithConcurrency.call(void 0,
|
|
6829
6829
|
newQuizAssignments,
|
|
6830
6830
|
QUIZ_SCAN_CONCURRENCY_LIMIT,
|
|
6831
6831
|
async (assignment) => {
|
|
@@ -7175,7 +7175,7 @@ async function scanQuizzesAccessibility(canvas, courseId, warnings) {
|
|
|
7175
7175
|
canvas.assignments.list(courseId)
|
|
7176
7176
|
]);
|
|
7177
7177
|
const classicQuizzes = quizzes.filter((quiz) => CLASSIC_QUIZ_TYPES4.has(quiz.quiz_type));
|
|
7178
|
-
const classicFindings = await
|
|
7178
|
+
const classicFindings = await _chunkQ2CY33KVcjs.mapWithConcurrency.call(void 0,
|
|
7179
7179
|
classicQuizzes,
|
|
7180
7180
|
QUIZ_SCAN_CONCURRENCY_LIMIT2,
|
|
7181
7181
|
async (quiz) => {
|
|
@@ -7200,7 +7200,7 @@ async function scanQuizzesAccessibility(canvas, courseId, warnings) {
|
|
|
7200
7200
|
}
|
|
7201
7201
|
);
|
|
7202
7202
|
const newQuizAssignments = assignments.filter((a) => a.is_quiz_lti_assignment === true);
|
|
7203
|
-
const newQuizFindings = await
|
|
7203
|
+
const newQuizFindings = await _chunkQ2CY33KVcjs.mapWithConcurrency.call(void 0,
|
|
7204
7204
|
newQuizAssignments,
|
|
7205
7205
|
QUIZ_SCAN_CONCURRENCY_LIMIT2,
|
|
7206
7206
|
async (assignment) => {
|
|
@@ -7812,7 +7812,7 @@ function buildHandler(tool, pseudonymizer) {
|
|
|
7812
7812
|
}
|
|
7813
7813
|
return response;
|
|
7814
7814
|
} catch (error) {
|
|
7815
|
-
if (!(error instanceof
|
|
7815
|
+
if (!(error instanceof _chunkOVMVID27cjs.CanvasApiError)) {
|
|
7816
7816
|
console.error(`Unexpected error in tool "${tool.name}":`, error);
|
|
7817
7817
|
}
|
|
7818
7818
|
return {
|
|
@@ -7900,7 +7900,7 @@ function registerSyllabusResource(server, canvas) {
|
|
|
7900
7900
|
]
|
|
7901
7901
|
};
|
|
7902
7902
|
} catch (error) {
|
|
7903
|
-
if (!(error instanceof
|
|
7903
|
+
if (!(error instanceof _chunkOVMVID27cjs.CanvasApiError)) {
|
|
7904
7904
|
console.error("Unexpected error in syllabus resource:", error);
|
|
7905
7905
|
}
|
|
7906
7906
|
return {
|
|
@@ -7954,7 +7954,7 @@ function registerAssignmentDescriptionResource(server, canvas) {
|
|
|
7954
7954
|
]
|
|
7955
7955
|
};
|
|
7956
7956
|
} catch (error) {
|
|
7957
|
-
if (!(error instanceof
|
|
7957
|
+
if (!(error instanceof _chunkOVMVID27cjs.CanvasApiError)) {
|
|
7958
7958
|
console.error("Unexpected error in assignment-description resource:", error);
|
|
7959
7959
|
}
|
|
7960
7960
|
return {
|
|
@@ -9032,14 +9032,14 @@ function resolvePseudonymizer(config) {
|
|
|
9032
9032
|
});
|
|
9033
9033
|
}
|
|
9034
9034
|
function createCanvasMCPServer(config) {
|
|
9035
|
-
const canvas = new (0,
|
|
9035
|
+
const canvas = new (0, _chunkQ2CY33KVcjs.CanvasClient)({
|
|
9036
9036
|
token: config.token,
|
|
9037
9037
|
baseUrl: config.baseUrl
|
|
9038
9038
|
});
|
|
9039
9039
|
const pseudonymizer = resolvePseudonymizer(config);
|
|
9040
9040
|
const server = new (0, _mcpjs.McpServer)({
|
|
9041
9041
|
name: "canvas-lms-mcp",
|
|
9042
|
-
version:
|
|
9042
|
+
version: _chunkOVMVID27cjs.version
|
|
9043
9043
|
});
|
|
9044
9044
|
const features = {
|
|
9045
9045
|
assignmentSubmission: config.enableAssignmentSubmission,
|
|
@@ -9058,4 +9058,4 @@ function createCanvasMCPServer(config) {
|
|
|
9058
9058
|
|
|
9059
9059
|
|
|
9060
9060
|
exports.Pseudonymizer = Pseudonymizer; exports.createSharedPseudonymizer = createSharedPseudonymizer; exports.createCanvasMCPServer = createCanvasMCPServer;
|
|
9061
|
-
//# sourceMappingURL=chunk-
|
|
9061
|
+
//# sourceMappingURL=chunk-NSLFN2RA.cjs.map
|