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.
@@ -1,17 +1,17 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkDWCGX2LJcjs = require('../chunk-DWCGX2LJ.cjs');
3
+ var _chunkQ2CY33KVcjs = require('../chunk-Q2CY33KV.cjs');
4
4
 
5
5
 
6
6
 
7
7
 
8
8
 
9
- var _chunk2ENRMOJWcjs = require('../chunk-2ENRMOJW.cjs');
9
+ var _chunkOVMVID27cjs = require('../chunk-OVMVID27.cjs');
10
10
 
11
11
 
12
12
 
13
13
 
14
14
 
15
15
 
16
- exports.CanvasApiError = _chunk2ENRMOJWcjs.CanvasApiError; exports.CanvasClient = _chunkDWCGX2LJcjs.CanvasClient; exports.CanvasHttpClient = _chunk2ENRMOJWcjs.CanvasHttpClient; exports.appendCanvasQuery = _chunk2ENRMOJWcjs.appendCanvasQuery; exports.toCanvasQuery = _chunk2ENRMOJWcjs.toCanvasQuery;
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
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  CanvasClient
3
- } from "../chunk-3GRH22UA.js";
3
+ } from "../chunk-FZEHZ7CJ.js";
4
4
  import {
5
5
  CanvasApiError,
6
6
  CanvasHttpClient,
7
7
  appendCanvasQuery,
8
8
  toCanvasQuery
9
- } from "../chunk-FHB5523D.js";
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";
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-FHB5523D.js.map
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-FHB5523D.js";
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-3GRH22UA.js.map
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-3GRH22UA.js";
21
+ } from "./chunk-FZEHZ7CJ.js";
22
22
  import {
23
23
  CanvasApiError,
24
24
  version
25
- } from "./chunk-FHB5523D.js";
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-TNJAWWDM.js.map
9061
+ //# sourceMappingURL=chunk-NLW4QKHX.js.map
@@ -18,11 +18,11 @@ var _chunkOOP4MJA7cjs = require('./chunk-OOP4MJA7.cjs');
18
18
 
19
19
 
20
20
 
21
- var _chunkDWCGX2LJcjs = require('./chunk-DWCGX2LJ.cjs');
21
+ var _chunkQ2CY33KVcjs = require('./chunk-Q2CY33KV.cjs');
22
22
 
23
23
 
24
24
 
25
- var _chunk2ENRMOJWcjs = require('./chunk-2ENRMOJW.cjs');
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 _chunk2ENRMOJWcjs.CanvasApiError) {
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(_chunkDWCGX2LJcjs.SEARCH_CONTENT_TYPES)).optional().describe(
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
- ..._chunkDWCGX2LJcjs.SEARCH_CONTENT_TYPES
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 _chunk2ENRMOJWcjs.CanvasApiError && err.status === 404) {
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 _chunk2ENRMOJWcjs.CanvasApiError)) {
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 _chunk2ENRMOJWcjs.CanvasApiError && err.status === 403) {
3953
+ if (err instanceof _chunkOVMVID27cjs.CanvasApiError && err.status === 403) {
3954
3954
  policyUnavailable = true;
3955
- } else if (err instanceof _chunk2ENRMOJWcjs.CanvasApiError && err.status === 404) {
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 _chunk2ENRMOJWcjs.CanvasApiError)) throw err;
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 _chunk2ENRMOJWcjs.CanvasApiError && error.status === 403 && courseId === void 0 && accountId !== void 0 && !error.message.toLowerCase().includes("rate limit exceeded")) {
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(_chunkDWCGX2LJcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcomes from an account or course context."),
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(_chunkDWCGX2LJcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcome groups from an account or course context."),
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(_chunkDWCGX2LJcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcome links from an account or course context."),
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(_chunkDWCGX2LJcjs.OUTCOME_DETAIL_LEVELS).optional().describe('Outcome detail level. Use "full" to include expanded outcome fields.'),
4457
- outcome_group_style: _zod.z.enum(_chunkDWCGX2LJcjs.OUTCOME_DETAIL_LEVELS).optional().describe(
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(_chunkDWCGX2LJcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
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(_chunkDWCGX2LJcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
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(_chunkDWCGX2LJcjs.OUTCOME_DETAIL_LEVELS).optional().describe('Outcome detail level. Use "full" to include expanded outcome fields.')
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(_chunkDWCGX2LJcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
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(_chunkDWCGX2LJcjs.OUTCOME_ROLLUP_AGGREGATE_STATS).optional().describe('Statistic to use when aggregate="course".'),
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(_chunkDWCGX2LJcjs.OUTCOME_EXCLUDE_OPTIONS)).optional().describe("Optional rollup exclusions for missing users or missing outcome results."),
4587
- sort_by: _zod.z.enum(_chunkDWCGX2LJcjs.OUTCOME_ROLLUP_SORT_BY).optional().describe("Sort rollups by student name or by a specific outcome score."),
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(_chunkDWCGX2LJcjs.OUTCOME_SORT_ORDER).optional().describe("Sort order to apply when sorting rollups."),
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(_chunkDWCGX2LJcjs.OUTCOME_EXCLUDE_OPTIONS)).optional().describe("Optional exclusions for missing users or missing outcome results."),
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 _chunk2ENRMOJWcjs.CanvasApiError ? err.message : "Unknown error";
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 _chunk2ENRMOJWcjs.CanvasApiError ? result.err.status : null,
5960
- message: result.err instanceof _chunk2ENRMOJWcjs.CanvasApiError ? result.err.message : String(result.err)
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 _chunkDWCGX2LJcjs.mapWithConcurrency.call(void 0,
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 _chunk2ENRMOJWcjs.CanvasApiError ? r.err.status : null,
6124
- message: r.err instanceof _chunk2ENRMOJWcjs.CanvasApiError ? r.err.message : String(r.err)
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 _chunkDWCGX2LJcjs.mapWithConcurrency.call(void 0,
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 _chunkDWCGX2LJcjs.mapWithConcurrency.call(void 0,
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 _chunkDWCGX2LJcjs.mapWithConcurrency.call(void 0,
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 _chunkDWCGX2LJcjs.mapWithConcurrency.call(void 0,
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 _chunk2ENRMOJWcjs.CanvasApiError)) {
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 _chunk2ENRMOJWcjs.CanvasApiError)) {
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 _chunk2ENRMOJWcjs.CanvasApiError)) {
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, _chunkDWCGX2LJcjs.CanvasClient)({
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: _chunk2ENRMOJWcjs.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-YI3DY6GQ.cjs.map
9061
+ //# sourceMappingURL=chunk-NSLFN2RA.cjs.map