canvas-parent-mcp 1.1.3 → 1.1.5

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.
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "metadata": {
9
9
  "description": "MCP server for Canvas LMS (Instructure) — courses, grades, assignments, announcements, planner, conversations, files",
10
- "version": "1.1.3"
10
+ "version": "1.1.5"
11
11
  },
12
12
  "plugins": [
13
13
  {
@@ -15,7 +15,7 @@
15
15
  "displayName": "Canvas LMS",
16
16
  "source": "./",
17
17
  "description": "Canvas LMS (Instructure) MCP server for Claude — student/observer access via natural language",
18
- "version": "1.1.3",
18
+ "version": "1.1.5",
19
19
  "author": {
20
20
  "name": "Chris Hall"
21
21
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "canvas-parent-mcp",
3
3
  "displayName": "Canvas LMS",
4
- "version": "1.1.3",
4
+ "version": "1.1.5",
5
5
  "description": "Canvas LMS (Instructure) MCP server for Claude — courses, grades, assignments, announcements, planner, conversations, files",
6
6
  "author": {
7
7
  "name": "Chris Hall",
package/dist/auth.js CHANGED
@@ -52,20 +52,15 @@
52
52
  // - `loadAccount()` (the existing env-var resolver) is reused as-is so
53
53
  // the legacy paths keep working unchanged.
54
54
  import { bootstrap } from '@fetchproxy/bootstrap';
55
+ import { classifyBridgeError } from '@fetchproxy/server';
56
+ import { readEnvVar } from '@chrischall/mcp-utils';
55
57
  import { loadAccount } from './config.js';
56
58
  import pkg from '../package.json' with { type: 'json' };
59
+ // Fleet-shared env sanitization (`@chrischall/mcp-utils`): trim + suppress
60
+ // empty/"undefined"/"null"/unsubstituted-${...}-placeholder. Reads process.env
61
+ // by default. Thin alias keeps the existing call sites unchanged.
57
62
  function readEnv(key) {
58
- const raw = process.env[key];
59
- if (typeof raw !== 'string')
60
- return undefined;
61
- const trimmed = raw.trim();
62
- if (trimmed.length === 0)
63
- return undefined;
64
- if (trimmed === 'undefined' || trimmed === 'null')
65
- return undefined;
66
- if (/^\$\{[^}]*\}$/.test(trimmed))
67
- return undefined;
68
- return trimmed;
63
+ return readEnvVar(key);
69
64
  }
70
65
  function fetchproxyDisabled() {
71
66
  const raw = readEnv('CANVAS_DISABLE_FETCHPROXY');
@@ -153,6 +148,18 @@ export async function resolveAuth() {
153
148
  };
154
149
  }
155
150
  catch (e) {
151
+ // 0.8.0+ typed-error discrimination. The fetchproxy server already
152
+ // retries once on SW eviction (bridgeReviveDelayMs=2000 default), so
153
+ // a thrown FetchproxyBridgeDownError means the retry also failed —
154
+ // the extension's service worker is genuinely down and the user
155
+ // needs to wake it. The `.hint` is the actionable copy
156
+ // ("click the extension toolbar icon...") that we'd otherwise have
157
+ // to hand-write here. Surface it verbatim so users in path 4 get
158
+ // the same self-service guidance as path 5.
159
+ if (classifyBridgeError(e) === 'bridge_down') {
160
+ const downErr = e;
161
+ throw new Error(`Canvas auth: fetchproxy bridge is down (extension service worker unreachable after retry). ${downErr.hint}`);
162
+ }
156
163
  const msg = e instanceof Error ? e.message : String(e);
157
164
  throw new Error(`Canvas auth: no CANVAS_TOKEN, CANVAS_CLIENT_*/CANVAS_REFRESH_TOKEN, or CANVAS_USERNAME/CANVAS_PASSWORD set, ` +
158
165
  `and fetchproxy fallback failed: ${msg}`);