canvas-lms-mcp-remote 1.1.1 → 1.1.2

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/index.js CHANGED
@@ -400,7 +400,7 @@ let skipped = 0;
400
400
  * write - true if the tool changes state (respects CANVAS_ALLOW_WRITES)
401
401
  * confirm - true if irreversible/visible to others (requires confirm:true arg)
402
402
  */
403
- function tool({ name, description, schema = {}, handler, write = false, confirm = false, group = '' }) {
403
+ function tool({ name, description, schema = {}, handler, write = false, confirm = false, group = '', offline = false }) {
404
404
  if (PROFILE === 'core' && !CORE_TOOLS.has(name)) { skipped++; return; }
405
405
  if (write && !ALLOW_WRITES) { skipped++; return; }
406
406
 
@@ -417,11 +417,12 @@ function tool({ name, description, schema = {}, handler, write = false, confirm
417
417
  title: titleFor(name),
418
418
  description: desc,
419
419
  inputSchema: shape,
420
- annotations: { readOnlyHint: !write, destructiveHint: confirm, idempotentHint: !write, openWorldHint: true, ...doc.annotations },
420
+ annotations: { readOnlyHint: !write, destructiveHint: confirm, idempotentHint: !write, openWorldHint: !offline, ...doc.annotations },
421
421
  }, async (args = {}) => {
422
422
  try {
423
- if (!TOKEN) return fail('CANVAS_API_TOKEN is not set. Add it to the .env file next to index.js.');
424
- if (!API) return fail('CANVAS_BASE_URL is not set. Example: https://yourschool.instructure.com');
423
+ // Offline tools never call Canvas, so they work before the token and URL are set.
424
+ if (!offline && !TOKEN) return fail('CANVAS_API_TOKEN is not set. Add it to the .env file next to index.js.');
425
+ if (!offline && !API) return fail('CANVAS_BASE_URL is not set. Example: https://yourschool.instructure.com');
425
426
  if (confirm && args.confirm !== true) {
426
427
  const preview = typeof handler.preview === 'function' ? await handler.preview(args) : null;
427
428
  return ok(preview || args, `DRY RUN. Nothing was sent to Canvas.\nThis action is visible to other people and cannot be fully undone.\nReview the details below, then call ${name} again with confirm=true to execute.`);
@@ -499,7 +500,7 @@ tool({
499
500
  });
500
501
 
501
502
  tool({
502
- name: 'get_rate_limit_status', group: A,
503
+ name: 'get_rate_limit_status', group: A, offline: true,
503
504
  description: 'Report the Canvas rate-limit state observed on the most recent API call. Canvas throttles by cumulative request COST, not request count.',
504
505
  handler: async () => ok({
505
506
  requests_this_session: canvas.requestCount,
@@ -1641,7 +1642,7 @@ tool({
1641
1642
  });
1642
1643
 
1643
1644
  tool({
1644
- name: 'search_tools', group: O,
1645
+ name: 'search_tools', group: O, offline: true,
1645
1646
  description: 'Search the tools this server exposes by keyword. Useful because the tool surface is large.',
1646
1647
  schema: { query: z.string().optional(), group: z.string().optional() },
1647
1648
  handler: async (a) => {
@@ -1674,7 +1675,7 @@ tool({
1674
1675
  });
1675
1676
 
1676
1677
  tool({
1677
- name: 'get_server_config', group: O,
1678
+ name: 'get_server_config', group: O, offline: true,
1678
1679
  description: 'Show how this server is configured and what is enabled, without revealing the token.',
1679
1680
  handler: async () => ok({
1680
1681
  server: SERVER_NAME, version: SERVER_VERSION,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canvas-lms-mcp-remote",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Self-hosted Canvas LMS MCP server for every device: 209 student tools over Streamable HTTP with an OAuth 2.1 login, an ngrok tunnel and multi-computer failover.",
5
5
  "mcpName": "io.github.Fireiscoolsolo/canvas-lms-mcp-server",
6
6
  "type": "module",
package/tool-docs.js CHANGED
@@ -69,7 +69,7 @@ export const TOOL_DOCS = {
69
69
  get_my_profile: { description: 'Get your full Canvas profile: name, bio, avatar, primary email and calendar feed URL. Read-only. For just your ID and name, whoami is cheaper.' },
70
70
  get_my_settings: { description: 'Get your account-level Canvas preferences, such as dashboard view, activity stream visibility and comment notification settings. Read-only. For how often you are notified about each event, use get_notification_preferences.' },
71
71
  check_token_expiry: { description: 'Check when your Canvas access token expires and warn if it is close. Read-only. Canvas often forces student tokens to expire after 30–120 days without warning, so run this at the start of a term.' },
72
- get_rate_limit_status: { description: 'Report Canvas rate-limit state from the most recent API call: remaining quota, last request cost and requests this session. Read-only and makes no Canvas call itself. Canvas throttles by cumulative request cost, so check this before expensive tools like semester_snapshot.', annotations: { openWorldHint: false } },
72
+ get_rate_limit_status: { description: 'Report Canvas rate-limit state from the most recent API call: remaining quota, last request cost and requests this session. Read-only and makes no Canvas call itself. Canvas throttles by cumulative request cost, so check this before expensive tools like semester_snapshot.' },
73
73
  list_my_enrollments: { description: 'List your enrollments across all courses, with role (student, observer…), section and current grade summary. Read-only. Use list_courses for course details; use this when you need roles, sections or per-enrollment grades.' },
74
74
  get_activity_stream: { description: 'Get recent activity across all your courses: new announcements, discussion replies, graded submissions and messages, newest first. Read-only. Titles and messages are fenced as untrusted text. For counts only, use get_activity_stream_summary; for one course, use get_course_activity_stream.', params: { only_active_courses: 'Only include activity from currently active courses. Default true.' } },
75
75
  get_activity_stream_summary: { description: 'Get counts of unread activity by type (announcements, discussions, messages, submissions) across your courses. Read-only and very cheap. Call it before get_activity_stream to see whether the full stream is worth pulling.' },
@@ -299,9 +299,9 @@ export const TOOL_DOCS = {
299
299
 
300
300
  // ---- meta ----
301
301
  raw_canvas_request: { description: 'Call any Canvas REST API endpoint directly, for anything the other tools don\'t cover. GET is read-only. POST, PUT and DELETE can change data: they are blocked when CANVAS_ALLOW_WRITES=false, need confirm=true, and quiz-submission writes are always refused.', params: { max_items: 'With paginate=true, stop after this many items. Default 200.' }, annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false } },
302
- search_tools: { description: 'Search this server\'s tools by keyword and return matching names with one-line descriptions. Read-only. Use it to find the right tool among the 200+ available.', params: { query: 'Keyword to look for in tool names and descriptions, e.g. "grade". Omit to list everything.', group: 'Optional group: identity, courses, assignments, submissions, grades, quizzes, discussions, inbox, calendar, content, groups, rubrics, search, planning or meta.' }, annotations: { openWorldHint: false } },
302
+ search_tools: { description: 'Search this server\'s tools by keyword and return matching names with one-line descriptions. Read-only, makes no Canvas calls and works before a token is set. Use it to find the right tool among the 200+ available.', params: { query: 'Keyword to look for in tool names and descriptions, e.g. "grade". Omit to list everything.', group: 'Optional group: identity, courses, assignments, submissions, grades, quizzes, discussions, inbox, calendar, content, groups, rubrics, search, planning or meta.' } },
303
303
  test_connection: { description: 'Check the token, school URL and access end to end: identity, courses, planner, inbox and missing submissions, and report any features your school disabled. Read-only. Run this first if anything fails.' },
304
- get_server_config: { description: 'Show this server\'s settings (school URL, profile, write mode, cache, time zone, download folder) without revealing the token. Read-only and makes no Canvas API calls.', annotations: { openWorldHint: false } },
304
+ get_server_config: { description: 'Show this server\'s settings (school URL, profile, write mode, cache, time zone, download folder) and whether a token is present, without revealing it. Read-only, makes no Canvas calls and works before a token is set, so use it first to diagnose setup problems.' },
305
305
  };
306
306
 
307
307
  const WORDS = { id: 'ID', ids: 'IDs', url: 'URL', ip: 'IP', imscc: 'IMSCC', whoami: 'Who Am I' };